# HG changeset patch # User Rik # Date 1669953944 28800 # Node ID 23664317f0d3cd4e7dc462d00e8e430e228f9add # Parent dfa5d9c3ae722c926638d210f1eb0766c453ded6# Parent aac27ad79be628d6f601be4c7d77b80124382e3a maint: merge stable to default diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/build-env.h --- a/libinterp/build-env.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/build-env.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,148 +34,148 @@ OCTAVE_BEGIN_NAMESPACE(build_env) - extern OCTINTERP_API octave_scalar_map features (void); +extern OCTINTERP_API octave_scalar_map features (void); - extern OCTINTERP_API const char *AMD_CPPFLAGS; - extern OCTINTERP_API const char *AMD_LDFLAGS; - extern OCTINTERP_API const char *AMD_LIBS; - extern OCTINTERP_API const char *ARFLAGS; - extern OCTINTERP_API const char *AR; - extern OCTINTERP_API const char *ARPACK_CPPFLAGS; - extern OCTINTERP_API const char *ARPACK_LDFLAGS; - extern OCTINTERP_API const char *ARPACK_LIBS; - extern OCTINTERP_API const char *BLAS_LIBS; - extern OCTINTERP_API const char *CAMD_CPPFLAGS; - extern OCTINTERP_API const char *CAMD_LDFLAGS; - extern OCTINTERP_API const char *CAMD_LIBS; - extern OCTINTERP_API const char *CARBON_LIBS; - extern OCTINTERP_API const char *CC; - extern OCTINTERP_API const char *CCOLAMD_CPPFLAGS; - extern OCTINTERP_API const char *CCOLAMD_LDFLAGS; - extern OCTINTERP_API const char *CCOLAMD_LIBS; - extern OCTINTERP_API const char *CFLAGS; - extern OCTINTERP_API const char *CHOLMOD_CPPFLAGS; - extern OCTINTERP_API const char *CHOLMOD_LDFLAGS; - extern OCTINTERP_API const char *CHOLMOD_LIBS; - extern OCTINTERP_API const char *COLAMD_CPPFLAGS; - extern OCTINTERP_API const char *COLAMD_LDFLAGS; - extern OCTINTERP_API const char *COLAMD_LIBS; - extern OCTINTERP_API const char *CPICFLAG; - extern OCTINTERP_API const char *CPPFLAGS; - extern OCTINTERP_API const char *CURL_CPPFLAGS; - extern OCTINTERP_API const char *CURL_LDFLAGS; - extern OCTINTERP_API const char *CURL_LIBS; - extern OCTINTERP_API const char *CXSPARSE_CPPFLAGS; - extern OCTINTERP_API const char *CXSPARSE_LDFLAGS; - extern OCTINTERP_API const char *CXSPARSE_LIBS; - extern OCTINTERP_API const char *CXXCPP; - extern OCTINTERP_API const char *CXXFLAGS; - extern OCTINTERP_API const char *CXXPICFLAG; - extern OCTINTERP_API const char *CXX; - extern OCTINTERP_API const char *DEFAULT_PAGER; - extern OCTINTERP_API const char *DEFS; - extern OCTINTERP_API const char *DL_LDFLAGS; - extern OCTINTERP_API const char *EXEEXT; - extern OCTINTERP_API const char *GCC_VERSION; - extern OCTINTERP_API const char *GXX_VERSION; - extern OCTINTERP_API const char *F77; - extern OCTINTERP_API const char *F77_FLOAT_STORE_FLAG; - extern OCTINTERP_API const char *F77_INTEGER_8_FLAG; - extern OCTINTERP_API const char *FFLAGS; - extern OCTINTERP_API const char *FFTW3_CPPFLAGS; - extern OCTINTERP_API const char *FFTW3_LDFLAGS; - extern OCTINTERP_API const char *FFTW3_LIBS; - extern OCTINTERP_API const char *FFTW3F_CPPFLAGS; - extern OCTINTERP_API const char *FFTW3F_LDFLAGS; - extern OCTINTERP_API const char *FFTW3F_LIBS; - extern OCTINTERP_API const char *FLIBS; - extern OCTINTERP_API const char *FLTK_CPPFLAGS; - extern OCTINTERP_API const char *FLTK_LDFLAGS; - extern OCTINTERP_API const char *FLTK_LIBS; - extern OCTINTERP_API const char *FONTCONFIG_CPPFLAGS; - extern OCTINTERP_API const char *FONTCONFIG_LIBS; - extern OCTINTERP_API const char *FPICFLAG; - extern OCTINTERP_API const char *FT2_CPPFLAGS; - extern OCTINTERP_API const char *FT2_LIBS; - extern OCTINTERP_API const char *GLPK_CPPFLAGS; - extern OCTINTERP_API const char *GLPK_LDFLAGS; - extern OCTINTERP_API const char *GLPK_LIBS; - extern OCTINTERP_API const char *GNUPLOT; - extern OCTINTERP_API const char *HDF5_CPPFLAGS; - extern OCTINTERP_API const char *HDF5_LDFLAGS; - extern OCTINTERP_API const char *HDF5_LIBS; - extern OCTINTERP_API const char *INCLUDEDIR; - extern OCTINTERP_API const char *KLU_CPPFLAGS; - extern OCTINTERP_API const char *KLU_LDFLAGS; - extern OCTINTERP_API const char *KLU_LIBS; - extern OCTINTERP_API const char *LAPACK_LIBS; - extern OCTINTERP_API const char *LDFLAGS; - extern OCTINTERP_API const char *LD_STATIC_FLAG; - extern OCTINTERP_API const char *LEXLIB; - extern OCTINTERP_API const char *LEX; - extern OCTINTERP_API const char *LFLAGS; - extern OCTINTERP_API const char *LIBOCTAVE; - extern OCTINTERP_API const char *LIBOCTINTERP; - extern OCTINTERP_API const char *LIBS; - extern OCTINTERP_API const char *LN_S; - extern OCTINTERP_API const char *MAGICK_CPPFLAGS; - extern OCTINTERP_API const char *MAGICK_LDFLAGS; - extern OCTINTERP_API const char *MAGICK_LIBS; - extern OCTINTERP_API const char *MKOCTFILE_DL_LDFLAGS; - extern OCTINTERP_API const char *OCTAVE_LINK_DEPS; - extern OCTINTERP_API const char *OCTAVE_LINK_OPTS; - extern OCTINTERP_API const char *OCTINCLUDEDIR; - extern OCTINTERP_API const char *OCTLIBDIR; - extern OCTINTERP_API const char *OCT_LINK_DEPS; - extern OCTINTERP_API const char *OCT_LINK_OPTS; - extern OCTINTERP_API const char *OPENGL_LIBS; - extern OCTINTERP_API const char *PCRE_CPPFLAGS; - extern OCTINTERP_API const char *PCRE_LDFLAGS; - extern OCTINTERP_API const char *PCRE_LIBS; - extern OCTINTERP_API const char *PREFIX; - extern OCTINTERP_API const char *PTHREAD_CFLAGS; - extern OCTINTERP_API const char *PTHREAD_LIBS; - extern OCTINTERP_API const char *QHULL_CPPFLAGS; - extern OCTINTERP_API const char *QHULL_LDFLAGS; - extern OCTINTERP_API const char *QHULL_LIBS; - extern OCTINTERP_API const char *QRUPDATE_CPPFLAGS; - extern OCTINTERP_API const char *QRUPDATE_LDFLAGS; - extern OCTINTERP_API const char *QRUPDATE_LIBS; - extern OCTINTERP_API const char *QT_CPPFLAGS; - extern OCTINTERP_API const char *QT_LDFLAGS; - extern OCTINTERP_API const char *QT_LIBS; - extern OCTINTERP_API const char *QT_OPENGL_LIBS; - extern OCTINTERP_API const char *RANLIB; - extern OCTINTERP_API const char *RDYNAMIC_FLAG; - extern OCTINTERP_API const char *READLINE_LIBS; - extern OCTINTERP_API const char *SHARED_LIBS; - extern OCTINTERP_API const char *SH_LDFLAGS; - extern OCTINTERP_API const char *STATIC_LIBS; - extern OCTINTERP_API const char *SUITESPARSECONFIG_LIBS; - extern OCTINTERP_API const char *SUNDIALS_IDA_CPPFLAGS; - extern OCTINTERP_API const char *SUNDIALS_IDA_LDFLAGS; - extern OCTINTERP_API const char *SUNDIALS_IDA_LIBS; - extern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_CPPFLAGS; - extern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_LDFLAGS; - extern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_LIBS; - extern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS; - extern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS; - extern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_LIBS; - extern OCTINTERP_API const char *UMFPACK_CPPFLAGS; - extern OCTINTERP_API const char *UMFPACK_LDFLAGS; - extern OCTINTERP_API const char *UMFPACK_LIBS; - extern OCTINTERP_API const char *WARN_CFLAGS; - extern OCTINTERP_API const char *WARN_CXXFLAGS; - extern OCTINTERP_API const char *X11_INCFLAGS; - extern OCTINTERP_API const char *X11_LIBS; - extern OCTINTERP_API const char *XTRA_CFLAGS; - extern OCTINTERP_API const char *XTRA_CXXFLAGS; - extern OCTINTERP_API const char *YACC; - extern OCTINTERP_API const char *YFLAGS; - extern OCTINTERP_API const char *Z_CPPFLAGS; - extern OCTINTERP_API const char *Z_LDFLAGS; - extern OCTINTERP_API const char *Z_LIBS; - extern OCTINTERP_API const char *config_opts; +extern OCTINTERP_API const char *AMD_CPPFLAGS; +extern OCTINTERP_API const char *AMD_LDFLAGS; +extern OCTINTERP_API const char *AMD_LIBS; +extern OCTINTERP_API const char *ARFLAGS; +extern OCTINTERP_API const char *AR; +extern OCTINTERP_API const char *ARPACK_CPPFLAGS; +extern OCTINTERP_API const char *ARPACK_LDFLAGS; +extern OCTINTERP_API const char *ARPACK_LIBS; +extern OCTINTERP_API const char *BLAS_LIBS; +extern OCTINTERP_API const char *CAMD_CPPFLAGS; +extern OCTINTERP_API const char *CAMD_LDFLAGS; +extern OCTINTERP_API const char *CAMD_LIBS; +extern OCTINTERP_API const char *CARBON_LIBS; +extern OCTINTERP_API const char *CC; +extern OCTINTERP_API const char *CCOLAMD_CPPFLAGS; +extern OCTINTERP_API const char *CCOLAMD_LDFLAGS; +extern OCTINTERP_API const char *CCOLAMD_LIBS; +extern OCTINTERP_API const char *CFLAGS; +extern OCTINTERP_API const char *CHOLMOD_CPPFLAGS; +extern OCTINTERP_API const char *CHOLMOD_LDFLAGS; +extern OCTINTERP_API const char *CHOLMOD_LIBS; +extern OCTINTERP_API const char *COLAMD_CPPFLAGS; +extern OCTINTERP_API const char *COLAMD_LDFLAGS; +extern OCTINTERP_API const char *COLAMD_LIBS; +extern OCTINTERP_API const char *CPICFLAG; +extern OCTINTERP_API const char *CPPFLAGS; +extern OCTINTERP_API const char *CURL_CPPFLAGS; +extern OCTINTERP_API const char *CURL_LDFLAGS; +extern OCTINTERP_API const char *CURL_LIBS; +extern OCTINTERP_API const char *CXSPARSE_CPPFLAGS; +extern OCTINTERP_API const char *CXSPARSE_LDFLAGS; +extern OCTINTERP_API const char *CXSPARSE_LIBS; +extern OCTINTERP_API const char *CXXCPP; +extern OCTINTERP_API const char *CXXFLAGS; +extern OCTINTERP_API const char *CXXPICFLAG; +extern OCTINTERP_API const char *CXX; +extern OCTINTERP_API const char *DEFAULT_PAGER; +extern OCTINTERP_API const char *DEFS; +extern OCTINTERP_API const char *DL_LDFLAGS; +extern OCTINTERP_API const char *EXEEXT; +extern OCTINTERP_API const char *GCC_VERSION; +extern OCTINTERP_API const char *GXX_VERSION; +extern OCTINTERP_API const char *F77; +extern OCTINTERP_API const char *F77_FLOAT_STORE_FLAG; +extern OCTINTERP_API const char *F77_INTEGER_8_FLAG; +extern OCTINTERP_API const char *FFLAGS; +extern OCTINTERP_API const char *FFTW3_CPPFLAGS; +extern OCTINTERP_API const char *FFTW3_LDFLAGS; +extern OCTINTERP_API const char *FFTW3_LIBS; +extern OCTINTERP_API const char *FFTW3F_CPPFLAGS; +extern OCTINTERP_API const char *FFTW3F_LDFLAGS; +extern OCTINTERP_API const char *FFTW3F_LIBS; +extern OCTINTERP_API const char *FLIBS; +extern OCTINTERP_API const char *FLTK_CPPFLAGS; +extern OCTINTERP_API const char *FLTK_LDFLAGS; +extern OCTINTERP_API const char *FLTK_LIBS; +extern OCTINTERP_API const char *FONTCONFIG_CPPFLAGS; +extern OCTINTERP_API const char *FONTCONFIG_LIBS; +extern OCTINTERP_API const char *FPICFLAG; +extern OCTINTERP_API const char *FT2_CPPFLAGS; +extern OCTINTERP_API const char *FT2_LIBS; +extern OCTINTERP_API const char *GLPK_CPPFLAGS; +extern OCTINTERP_API const char *GLPK_LDFLAGS; +extern OCTINTERP_API const char *GLPK_LIBS; +extern OCTINTERP_API const char *GNUPLOT; +extern OCTINTERP_API const char *HDF5_CPPFLAGS; +extern OCTINTERP_API const char *HDF5_LDFLAGS; +extern OCTINTERP_API const char *HDF5_LIBS; +extern OCTINTERP_API const char *INCLUDEDIR; +extern OCTINTERP_API const char *KLU_CPPFLAGS; +extern OCTINTERP_API const char *KLU_LDFLAGS; +extern OCTINTERP_API const char *KLU_LIBS; +extern OCTINTERP_API const char *LAPACK_LIBS; +extern OCTINTERP_API const char *LDFLAGS; +extern OCTINTERP_API const char *LD_STATIC_FLAG; +extern OCTINTERP_API const char *LEXLIB; +extern OCTINTERP_API const char *LEX; +extern OCTINTERP_API const char *LFLAGS; +extern OCTINTERP_API const char *LIBOCTAVE; +extern OCTINTERP_API const char *LIBOCTINTERP; +extern OCTINTERP_API const char *LIBS; +extern OCTINTERP_API const char *LN_S; +extern OCTINTERP_API const char *MAGICK_CPPFLAGS; +extern OCTINTERP_API const char *MAGICK_LDFLAGS; +extern OCTINTERP_API const char *MAGICK_LIBS; +extern OCTINTERP_API const char *MKOCTFILE_DL_LDFLAGS; +extern OCTINTERP_API const char *OCTAVE_LINK_DEPS; +extern OCTINTERP_API const char *OCTAVE_LINK_OPTS; +extern OCTINTERP_API const char *OCTINCLUDEDIR; +extern OCTINTERP_API const char *OCTLIBDIR; +extern OCTINTERP_API const char *OCT_LINK_DEPS; +extern OCTINTERP_API const char *OCT_LINK_OPTS; +extern OCTINTERP_API const char *OPENGL_LIBS; +extern OCTINTERP_API const char *PCRE_CPPFLAGS; +extern OCTINTERP_API const char *PCRE_LDFLAGS; +extern OCTINTERP_API const char *PCRE_LIBS; +extern OCTINTERP_API const char *PREFIX; +extern OCTINTERP_API const char *PTHREAD_CFLAGS; +extern OCTINTERP_API const char *PTHREAD_LIBS; +extern OCTINTERP_API const char *QHULL_CPPFLAGS; +extern OCTINTERP_API const char *QHULL_LDFLAGS; +extern OCTINTERP_API const char *QHULL_LIBS; +extern OCTINTERP_API const char *QRUPDATE_CPPFLAGS; +extern OCTINTERP_API const char *QRUPDATE_LDFLAGS; +extern OCTINTERP_API const char *QRUPDATE_LIBS; +extern OCTINTERP_API const char *QT_CPPFLAGS; +extern OCTINTERP_API const char *QT_LDFLAGS; +extern OCTINTERP_API const char *QT_LIBS; +extern OCTINTERP_API const char *QT_OPENGL_LIBS; +extern OCTINTERP_API const char *RANLIB; +extern OCTINTERP_API const char *RDYNAMIC_FLAG; +extern OCTINTERP_API const char *READLINE_LIBS; +extern OCTINTERP_API const char *SHARED_LIBS; +extern OCTINTERP_API const char *SH_LDFLAGS; +extern OCTINTERP_API const char *STATIC_LIBS; +extern OCTINTERP_API const char *SUITESPARSECONFIG_LIBS; +extern OCTINTERP_API const char *SUNDIALS_IDA_CPPFLAGS; +extern OCTINTERP_API const char *SUNDIALS_IDA_LDFLAGS; +extern OCTINTERP_API const char *SUNDIALS_IDA_LIBS; +extern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_CPPFLAGS; +extern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_LDFLAGS; +extern OCTINTERP_API const char *SUNDIALS_NVECSERIAL_LIBS; +extern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS; +extern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS; +extern OCTINTERP_API const char *SUNDIALS_SUNLINSOLKLU_LIBS; +extern OCTINTERP_API const char *UMFPACK_CPPFLAGS; +extern OCTINTERP_API const char *UMFPACK_LDFLAGS; +extern OCTINTERP_API const char *UMFPACK_LIBS; +extern OCTINTERP_API const char *WARN_CFLAGS; +extern OCTINTERP_API const char *WARN_CXXFLAGS; +extern OCTINTERP_API const char *X11_INCFLAGS; +extern OCTINTERP_API const char *X11_LIBS; +extern OCTINTERP_API const char *XTRA_CFLAGS; +extern OCTINTERP_API const char *XTRA_CXXFLAGS; +extern OCTINTERP_API const char *YACC; +extern OCTINTERP_API const char *YFLAGS; +extern OCTINTERP_API const char *Z_CPPFLAGS; +extern OCTINTERP_API const char *Z_LDFLAGS; +extern OCTINTERP_API const char *Z_LIBS; +extern OCTINTERP_API const char *config_opts; OCTAVE_END_NAMESPACE(build_env) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/build-env.in.cc --- a/libinterp/build-env.in.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/build-env.in.cc Thu Dec 01 20:05:44 2022 -0800 @@ -35,285 +35,285 @@ OCTAVE_BEGIN_NAMESPACE(build_env) - const char *AMD_CPPFLAGS = %OCTAVE_CONF_AMD_CPPFLAGS%; +const char *AMD_CPPFLAGS = %OCTAVE_CONF_AMD_CPPFLAGS%; - const char *AMD_LDFLAGS = %OCTAVE_CONF_AMD_LDFLAGS%; +const char *AMD_LDFLAGS = %OCTAVE_CONF_AMD_LDFLAGS%; - const char *AMD_LIBS = %OCTAVE_CONF_AMD_LIBS%; +const char *AMD_LIBS = %OCTAVE_CONF_AMD_LIBS%; - const char *ARFLAGS = %OCTAVE_CONF_ARFLAGS%; +const char *ARFLAGS = %OCTAVE_CONF_ARFLAGS%; - const char *AR = %OCTAVE_CONF_AR%; +const char *AR = %OCTAVE_CONF_AR%; - const char *ARPACK_CPPFLAGS = %OCTAVE_CONF_ARPACK_CPPFLAGS%; +const char *ARPACK_CPPFLAGS = %OCTAVE_CONF_ARPACK_CPPFLAGS%; - const char *ARPACK_LDFLAGS = %OCTAVE_CONF_ARPACK_LDFLAGS%; +const char *ARPACK_LDFLAGS = %OCTAVE_CONF_ARPACK_LDFLAGS%; - const char *ARPACK_LIBS = %OCTAVE_CONF_ARPACK_LIBS%; +const char *ARPACK_LIBS = %OCTAVE_CONF_ARPACK_LIBS%; - const char *BLAS_LIBS = %OCTAVE_CONF_BLAS_LIBS%; +const char *BLAS_LIBS = %OCTAVE_CONF_BLAS_LIBS%; - const char *CAMD_CPPFLAGS = %OCTAVE_CONF_CAMD_CPPFLAGS%; +const char *CAMD_CPPFLAGS = %OCTAVE_CONF_CAMD_CPPFLAGS%; - const char *CAMD_LDFLAGS = %OCTAVE_CONF_CAMD_LDFLAGS%; +const char *CAMD_LDFLAGS = %OCTAVE_CONF_CAMD_LDFLAGS%; - const char *CAMD_LIBS = %OCTAVE_CONF_CAMD_LIBS%; +const char *CAMD_LIBS = %OCTAVE_CONF_CAMD_LIBS%; - const char *CARBON_LIBS = %OCTAVE_CONF_CARBON_LIBS%; +const char *CARBON_LIBS = %OCTAVE_CONF_CARBON_LIBS%; - const char *CC = %OCTAVE_CONF_CC%; +const char *CC = %OCTAVE_CONF_CC%; - const char *CCOLAMD_CPPFLAGS = %OCTAVE_CONF_CCOLAMD_CPPFLAGS%; +const char *CCOLAMD_CPPFLAGS = %OCTAVE_CONF_CCOLAMD_CPPFLAGS%; - const char *CCOLAMD_LDFLAGS = %OCTAVE_CONF_CCOLAMD_LDFLAGS%; +const char *CCOLAMD_LDFLAGS = %OCTAVE_CONF_CCOLAMD_LDFLAGS%; - const char *CCOLAMD_LIBS = %OCTAVE_CONF_CCOLAMD_LIBS%; +const char *CCOLAMD_LIBS = %OCTAVE_CONF_CCOLAMD_LIBS%; - const char *CFLAGS = %OCTAVE_CONF_CFLAGS%; +const char *CFLAGS = %OCTAVE_CONF_CFLAGS%; - const char *CHOLMOD_CPPFLAGS = %OCTAVE_CONF_CHOLMOD_CPPFLAGS%; +const char *CHOLMOD_CPPFLAGS = %OCTAVE_CONF_CHOLMOD_CPPFLAGS%; - const char *CHOLMOD_LDFLAGS = %OCTAVE_CONF_CHOLMOD_LDFLAGS%; +const char *CHOLMOD_LDFLAGS = %OCTAVE_CONF_CHOLMOD_LDFLAGS%; - const char *CHOLMOD_LIBS = %OCTAVE_CONF_CHOLMOD_LIBS%; +const char *CHOLMOD_LIBS = %OCTAVE_CONF_CHOLMOD_LIBS%; - const char *COLAMD_CPPFLAGS = %OCTAVE_CONF_COLAMD_CPPFLAGS%; +const char *COLAMD_CPPFLAGS = %OCTAVE_CONF_COLAMD_CPPFLAGS%; - const char *COLAMD_LDFLAGS = %OCTAVE_CONF_COLAMD_LDFLAGS%; +const char *COLAMD_LDFLAGS = %OCTAVE_CONF_COLAMD_LDFLAGS%; - const char *COLAMD_LIBS = %OCTAVE_CONF_COLAMD_LIBS%; +const char *COLAMD_LIBS = %OCTAVE_CONF_COLAMD_LIBS%; - const char *CPICFLAG = %OCTAVE_CONF_CPICFLAG%; +const char *CPICFLAG = %OCTAVE_CONF_CPICFLAG%; - const char *CPPFLAGS = %OCTAVE_CONF_CPPFLAGS%; +const char *CPPFLAGS = %OCTAVE_CONF_CPPFLAGS%; - const char *CURL_CPPFLAGS = %OCTAVE_CONF_CURL_CPPFLAGS%; +const char *CURL_CPPFLAGS = %OCTAVE_CONF_CURL_CPPFLAGS%; - const char *CURL_LDFLAGS = %OCTAVE_CONF_CURL_LDFLAGS%; +const char *CURL_LDFLAGS = %OCTAVE_CONF_CURL_LDFLAGS%; - const char *CURL_LIBS = %OCTAVE_CONF_CURL_LIBS%; +const char *CURL_LIBS = %OCTAVE_CONF_CURL_LIBS%; - const char *CXSPARSE_CPPFLAGS = %OCTAVE_CONF_CXSPARSE_CPPFLAGS%; +const char *CXSPARSE_CPPFLAGS = %OCTAVE_CONF_CXSPARSE_CPPFLAGS%; - const char *CXSPARSE_LDFLAGS = %OCTAVE_CONF_CXSPARSE_LDFLAGS%; +const char *CXSPARSE_LDFLAGS = %OCTAVE_CONF_CXSPARSE_LDFLAGS%; - const char *CXSPARSE_LIBS = %OCTAVE_CONF_CXSPARSE_LIBS%; +const char *CXSPARSE_LIBS = %OCTAVE_CONF_CXSPARSE_LIBS%; - const char *CXXCPP = %OCTAVE_CONF_CXXCPP%; +const char *CXXCPP = %OCTAVE_CONF_CXXCPP%; - const char *CXXFLAGS = %OCTAVE_CONF_CXXFLAGS%; +const char *CXXFLAGS = %OCTAVE_CONF_CXXFLAGS%; - const char *CXXPICFLAG = %OCTAVE_CONF_CXXPICFLAG%; +const char *CXXPICFLAG = %OCTAVE_CONF_CXXPICFLAG%; - const char *CXX = %OCTAVE_CONF_CXX%; +const char *CXX = %OCTAVE_CONF_CXX%; - const char *DEFAULT_PAGER = %OCTAVE_CONF_DEFAULT_PAGER%; +const char *DEFAULT_PAGER = %OCTAVE_CONF_DEFAULT_PAGER%; - const char *DEFS = %OCTAVE_CONF_DEFS%; +const char *DEFS = %OCTAVE_CONF_DEFS%; - const char *DL_LDFLAGS = %OCTAVE_CONF_DL_LDFLAGS%; +const char *DL_LDFLAGS = %OCTAVE_CONF_DL_LDFLAGS%; - const char *EXEEXT = %OCTAVE_CONF_EXEEXT%; +const char *EXEEXT = %OCTAVE_CONF_EXEEXT%; - const char *GCC_VERSION = %OCTAVE_CONF_GCC_VERSION%; +const char *GCC_VERSION = %OCTAVE_CONF_GCC_VERSION%; - const char *GXX_VERSION = %OCTAVE_CONF_GXX_VERSION%; +const char *GXX_VERSION = %OCTAVE_CONF_GXX_VERSION%; - const char *F77 = %OCTAVE_CONF_F77%; +const char *F77 = %OCTAVE_CONF_F77%; - const char *F77_FLOAT_STORE_FLAG = %OCTAVE_CONF_F77_FLOAT_STORE_FLAG%; +const char *F77_FLOAT_STORE_FLAG = %OCTAVE_CONF_F77_FLOAT_STORE_FLAG%; - const char *F77_INTEGER_8_FLAG = %OCTAVE_CONF_F77_INTEGER_8_FLAG%; +const char *F77_INTEGER_8_FLAG = %OCTAVE_CONF_F77_INTEGER_8_FLAG%; - const char *FFLAGS = %OCTAVE_CONF_FFLAGS%; +const char *FFLAGS = %OCTAVE_CONF_FFLAGS%; - const char *FFTW3_CPPFLAGS = %OCTAVE_CONF_FFTW3_CPPFLAGS%; +const char *FFTW3_CPPFLAGS = %OCTAVE_CONF_FFTW3_CPPFLAGS%; - const char *FFTW3_LDFLAGS = %OCTAVE_CONF_FFTW3_LDFLAGS%; +const char *FFTW3_LDFLAGS = %OCTAVE_CONF_FFTW3_LDFLAGS%; - const char *FFTW3_LIBS = %OCTAVE_CONF_FFTW3_LIBS%; +const char *FFTW3_LIBS = %OCTAVE_CONF_FFTW3_LIBS%; - const char *FFTW3F_CPPFLAGS = %OCTAVE_CONF_FFTW3F_CPPFLAGS%; +const char *FFTW3F_CPPFLAGS = %OCTAVE_CONF_FFTW3F_CPPFLAGS%; - const char *FFTW3F_LDFLAGS = %OCTAVE_CONF_FFTW3F_LDFLAGS%; +const char *FFTW3F_LDFLAGS = %OCTAVE_CONF_FFTW3F_LDFLAGS%; - const char *FFTW3F_LIBS = %OCTAVE_CONF_FFTW3F_LIBS%; +const char *FFTW3F_LIBS = %OCTAVE_CONF_FFTW3F_LIBS%; - const char *FLIBS = %OCTAVE_CONF_FLIBS%; +const char *FLIBS = %OCTAVE_CONF_FLIBS%; - const char *FLTK_CPPFLAGS = %OCTAVE_CONF_FLTK_CPPFLAGS%; +const char *FLTK_CPPFLAGS = %OCTAVE_CONF_FLTK_CPPFLAGS%; - const char *FLTK_LDFLAGS = %OCTAVE_CONF_FLTK_LDFLAGS%; +const char *FLTK_LDFLAGS = %OCTAVE_CONF_FLTK_LDFLAGS%; - const char *FLTK_LIBS = %OCTAVE_CONF_FLTK_LIBS%; +const char *FLTK_LIBS = %OCTAVE_CONF_FLTK_LIBS%; - const char *FONTCONFIG_CPPFLAGS = %OCTAVE_CONF_FONTCONFIG_CPPFLAGS%; +const char *FONTCONFIG_CPPFLAGS = %OCTAVE_CONF_FONTCONFIG_CPPFLAGS%; - const char *FONTCONFIG_LIBS = %OCTAVE_CONF_FONTCONFIG_LIBS%; +const char *FONTCONFIG_LIBS = %OCTAVE_CONF_FONTCONFIG_LIBS%; - const char *FPICFLAG = %OCTAVE_CONF_FPICFLAG%; +const char *FPICFLAG = %OCTAVE_CONF_FPICFLAG%; - const char *FT2_CPPFLAGS = %OCTAVE_CONF_FT2_CPPFLAGS%; +const char *FT2_CPPFLAGS = %OCTAVE_CONF_FT2_CPPFLAGS%; - const char *FT2_LIBS = %OCTAVE_CONF_FT2_LIBS%; +const char *FT2_LIBS = %OCTAVE_CONF_FT2_LIBS%; - const char *GLPK_CPPFLAGS = %OCTAVE_CONF_GLPK_CPPFLAGS%; +const char *GLPK_CPPFLAGS = %OCTAVE_CONF_GLPK_CPPFLAGS%; - const char *GLPK_LDFLAGS = %OCTAVE_CONF_GLPK_LDFLAGS%; +const char *GLPK_LDFLAGS = %OCTAVE_CONF_GLPK_LDFLAGS%; - const char *GLPK_LIBS = %OCTAVE_CONF_GLPK_LIBS%; +const char *GLPK_LIBS = %OCTAVE_CONF_GLPK_LIBS%; - const char *GNUPLOT = %OCTAVE_CONF_GNUPLOT%; +const char *GNUPLOT = %OCTAVE_CONF_GNUPLOT%; - const char *HDF5_CPPFLAGS = %OCTAVE_CONF_HDF5_CPPFLAGS%; +const char *HDF5_CPPFLAGS = %OCTAVE_CONF_HDF5_CPPFLAGS%; - const char *HDF5_LDFLAGS = %OCTAVE_CONF_HDF5_LDFLAGS%; +const char *HDF5_LDFLAGS = %OCTAVE_CONF_HDF5_LDFLAGS%; - const char *HDF5_LIBS = %OCTAVE_CONF_HDF5_LIBS%; +const char *HDF5_LIBS = %OCTAVE_CONF_HDF5_LIBS%; - const char *INCLUDEDIR = %OCTAVE_CONF_INCLUDEDIR%; +const char *INCLUDEDIR = %OCTAVE_CONF_INCLUDEDIR%; - const char *KLU_CPPFLAGS = %OCTAVE_CONF_KLU_CPPFLAGS%; +const char *KLU_CPPFLAGS = %OCTAVE_CONF_KLU_CPPFLAGS%; - const char *KLU_LDFLAGS = %OCTAVE_CONF_KLU_LDFLAGS%; +const char *KLU_LDFLAGS = %OCTAVE_CONF_KLU_LDFLAGS%; - const char *KLU_LIBS = %OCTAVE_CONF_KLU_LIBS%; +const char *KLU_LIBS = %OCTAVE_CONF_KLU_LIBS%; - const char *LAPACK_LIBS = %OCTAVE_CONF_LAPACK_LIBS%; +const char *LAPACK_LIBS = %OCTAVE_CONF_LAPACK_LIBS%; - const char *LDFLAGS = %OCTAVE_CONF_LDFLAGS%; +const char *LDFLAGS = %OCTAVE_CONF_LDFLAGS%; - const char *LD_STATIC_FLAG = %OCTAVE_CONF_LD_STATIC_FLAG%; +const char *LD_STATIC_FLAG = %OCTAVE_CONF_LD_STATIC_FLAG%; - const char *LEXLIB = %OCTAVE_CONF_LEXLIB%; +const char *LEXLIB = %OCTAVE_CONF_LEXLIB%; - const char *LEX = %OCTAVE_CONF_LEX%; +const char *LEX = %OCTAVE_CONF_LEX%; - const char *LFLAGS = %OCTAVE_CONF_LFLAGS%; +const char *LFLAGS = %OCTAVE_CONF_LFLAGS%; - const char *LIBOCTAVE = %OCTAVE_CONF_LIBOCTAVE%; +const char *LIBOCTAVE = %OCTAVE_CONF_LIBOCTAVE%; - const char *LIBOCTINTERP = %OCTAVE_CONF_LIBOCTINTERP%; +const char *LIBOCTINTERP = %OCTAVE_CONF_LIBOCTINTERP%; - const char *LIBS = %OCTAVE_CONF_LIBS%; +const char *LIBS = %OCTAVE_CONF_LIBS%; - const char *LN_S = %OCTAVE_CONF_LN_S%; +const char *LN_S = %OCTAVE_CONF_LN_S%; - const char *MAGICK_CPPFLAGS = %OCTAVE_CONF_MAGICK_CPPFLAGS%; +const char *MAGICK_CPPFLAGS = %OCTAVE_CONF_MAGICK_CPPFLAGS%; - const char *MAGICK_LDFLAGS = %OCTAVE_CONF_MAGICK_LDFLAGS%; +const char *MAGICK_LDFLAGS = %OCTAVE_CONF_MAGICK_LDFLAGS%; - const char *MAGICK_LIBS = %OCTAVE_CONF_MAGICK_LIBS%; +const char *MAGICK_LIBS = %OCTAVE_CONF_MAGICK_LIBS%; - const char *MKOCTFILE_DL_LDFLAGS = %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%; +const char *MKOCTFILE_DL_LDFLAGS = %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%; - const char *OCTAVE_LINK_DEPS = %OCTAVE_CONF_OCTAVE_LINK_DEPS%; +const char *OCTAVE_LINK_DEPS = %OCTAVE_CONF_OCTAVE_LINK_DEPS%; - const char *OCTAVE_LINK_OPTS = %OCTAVE_CONF_OCTAVE_LINK_OPTS%; +const char *OCTAVE_LINK_OPTS = %OCTAVE_CONF_OCTAVE_LINK_OPTS%; - const char *OCTINCLUDEDIR = %OCTAVE_CONF_OCTINCLUDEDIR%; +const char *OCTINCLUDEDIR = %OCTAVE_CONF_OCTINCLUDEDIR%; - const char *OCTLIBDIR = %OCTAVE_CONF_OCTLIBDIR%; +const char *OCTLIBDIR = %OCTAVE_CONF_OCTLIBDIR%; - const char *OCT_LINK_DEPS = %OCTAVE_CONF_OCT_LINK_DEPS%; +const char *OCT_LINK_DEPS = %OCTAVE_CONF_OCT_LINK_DEPS%; - const char *OCT_LINK_OPTS = %OCTAVE_CONF_OCT_LINK_OPTS%; +const char *OCT_LINK_OPTS = %OCTAVE_CONF_OCT_LINK_OPTS%; - const char *OPENGL_LIBS = %OCTAVE_CONF_OPENGL_LIBS%; +const char *OPENGL_LIBS = %OCTAVE_CONF_OPENGL_LIBS%; - const char *PCRE_CPPFLAGS = %OCTAVE_CONF_PCRE_CPPFLAGS%; +const char *PCRE_CPPFLAGS = %OCTAVE_CONF_PCRE_CPPFLAGS%; - const char *PCRE_LDFLAGS = %OCTAVE_CONF_PCRE_LDFLAGS%; +const char *PCRE_LDFLAGS = %OCTAVE_CONF_PCRE_LDFLAGS%; - const char *PCRE_LIBS = %OCTAVE_CONF_PCRE_LIBS%; +const char *PCRE_LIBS = %OCTAVE_CONF_PCRE_LIBS%; - const char *PREFIX = %OCTAVE_CONF_PREFIX%; +const char *PREFIX = %OCTAVE_CONF_PREFIX%; - const char *PTHREAD_CFLAGS = %OCTAVE_CONF_PTHREAD_CFLAGS%; +const char *PTHREAD_CFLAGS = %OCTAVE_CONF_PTHREAD_CFLAGS%; - const char *PTHREAD_LIBS = %OCTAVE_CONF_PTHREAD_LIBS%; +const char *PTHREAD_LIBS = %OCTAVE_CONF_PTHREAD_LIBS%; - const char *QHULL_CPPFLAGS = %OCTAVE_CONF_QHULL_CPPFLAGS%; +const char *QHULL_CPPFLAGS = %OCTAVE_CONF_QHULL_CPPFLAGS%; - const char *QHULL_LDFLAGS = %OCTAVE_CONF_QHULL_LDFLAGS%; +const char *QHULL_LDFLAGS = %OCTAVE_CONF_QHULL_LDFLAGS%; - const char *QHULL_LIBS = %OCTAVE_CONF_QHULL_LIBS%; +const char *QHULL_LIBS = %OCTAVE_CONF_QHULL_LIBS%; - const char *QRUPDATE_CPPFLAGS = %OCTAVE_CONF_QRUPDATE_CPPFLAGS%; +const char *QRUPDATE_CPPFLAGS = %OCTAVE_CONF_QRUPDATE_CPPFLAGS%; - const char *QRUPDATE_LDFLAGS = %OCTAVE_CONF_QRUPDATE_LDFLAGS%; +const char *QRUPDATE_LDFLAGS = %OCTAVE_CONF_QRUPDATE_LDFLAGS%; - const char *QRUPDATE_LIBS = %OCTAVE_CONF_QRUPDATE_LIBS%; +const char *QRUPDATE_LIBS = %OCTAVE_CONF_QRUPDATE_LIBS%; - const char *QT_CPPFLAGS = %OCTAVE_CONF_QT_CPPFLAGS%; +const char *QT_CPPFLAGS = %OCTAVE_CONF_QT_CPPFLAGS%; - const char *QT_LDFLAGS = %OCTAVE_CONF_QT_LDFLAGS%; +const char *QT_LDFLAGS = %OCTAVE_CONF_QT_LDFLAGS%; - const char *QT_LIBS = %OCTAVE_CONF_QT_LIBS%; +const char *QT_LIBS = %OCTAVE_CONF_QT_LIBS%; - const char *QT_OPENGL_LIBS = %OCTAVE_CONF_QT_OPENGL_LIBS%; +const char *QT_OPENGL_LIBS = %OCTAVE_CONF_QT_OPENGL_LIBS%; - const char *RANLIB = %OCTAVE_CONF_RANLIB%; +const char *RANLIB = %OCTAVE_CONF_RANLIB%; - const char *RDYNAMIC_FLAG = %OCTAVE_CONF_RDYNAMIC_FLAG%; +const char *RDYNAMIC_FLAG = %OCTAVE_CONF_RDYNAMIC_FLAG%; - const char *READLINE_LIBS = %OCTAVE_CONF_READLINE_LIBS%; +const char *READLINE_LIBS = %OCTAVE_CONF_READLINE_LIBS%; - const char *SHARED_LIBS = %OCTAVE_CONF_SHARED_LIBS%; +const char *SHARED_LIBS = %OCTAVE_CONF_SHARED_LIBS%; - const char *SH_LDFLAGS = %OCTAVE_CONF_SH_LDFLAGS%; +const char *SH_LDFLAGS = %OCTAVE_CONF_SH_LDFLAGS%; - const char *STATIC_LIBS = %OCTAVE_CONF_STATIC_LIBS%; +const char *STATIC_LIBS = %OCTAVE_CONF_STATIC_LIBS%; - const char *SUITESPARSECONFIG_LIBS = %OCTAVE_CONF_SUITESPARSECONFIG_LIBS%; +const char *SUITESPARSECONFIG_LIBS = %OCTAVE_CONF_SUITESPARSECONFIG_LIBS%; - const char *SUNDIALS_IDA_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_IDA_CPPFLAGS%; +const char *SUNDIALS_IDA_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_IDA_CPPFLAGS%; - const char *SUNDIALS_IDA_LDFLAGS = %OCTAVE_CONF_SUNDIALS_IDA_LDFLAGS%; +const char *SUNDIALS_IDA_LDFLAGS = %OCTAVE_CONF_SUNDIALS_IDA_LDFLAGS%; - const char *SUNDIALS_IDA_LIBS = %OCTAVE_CONF_SUNDIALS_IDA_LIBS%; +const char *SUNDIALS_IDA_LIBS = %OCTAVE_CONF_SUNDIALS_IDA_LIBS%; - const char *SUNDIALS_NVECSERIAL_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%; +const char *SUNDIALS_NVECSERIAL_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_CPPFLAGS%; - const char *SUNDIALS_NVECSERIAL_LDFLAGS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%; +const char *SUNDIALS_NVECSERIAL_LDFLAGS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LDFLAGS%; - const char *SUNDIALS_NVECSERIAL_LIBS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%; +const char *SUNDIALS_NVECSERIAL_LIBS = %OCTAVE_CONF_SUNDIALS_NVECSERIAL_LIBS%; - const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%; +const char *SUNDIALS_SUNLINSOLKLU_CPPFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_CPPFLAGS%; - const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%; +const char *SUNDIALS_SUNLINSOLKLU_LDFLAGS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LDFLAGS%; - const char *SUNDIALS_SUNLINSOLKLU_LIBS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%; +const char *SUNDIALS_SUNLINSOLKLU_LIBS = %OCTAVE_CONF_SUNDIALS_SUNLINSOLKLU_LIBS%; - const char *UMFPACK_CPPFLAGS = %OCTAVE_CONF_UMFPACK_CPPFLAGS%; +const char *UMFPACK_CPPFLAGS = %OCTAVE_CONF_UMFPACK_CPPFLAGS%; - const char *UMFPACK_LDFLAGS = %OCTAVE_CONF_UMFPACK_LDFLAGS%; +const char *UMFPACK_LDFLAGS = %OCTAVE_CONF_UMFPACK_LDFLAGS%; - const char *UMFPACK_LIBS = %OCTAVE_CONF_UMFPACK_LIBS%; +const char *UMFPACK_LIBS = %OCTAVE_CONF_UMFPACK_LIBS%; - const char *WARN_CFLAGS = %OCTAVE_CONF_WARN_CFLAGS%; +const char *WARN_CFLAGS = %OCTAVE_CONF_WARN_CFLAGS%; - const char *WARN_CXXFLAGS = %OCTAVE_CONF_WARN_CXXFLAGS%; +const char *WARN_CXXFLAGS = %OCTAVE_CONF_WARN_CXXFLAGS%; - const char *X11_INCFLAGS = %OCTAVE_CONF_X11_INCFLAGS%; +const char *X11_INCFLAGS = %OCTAVE_CONF_X11_INCFLAGS%; - const char *X11_LIBS = %OCTAVE_CONF_X11_LIBS%; +const char *X11_LIBS = %OCTAVE_CONF_X11_LIBS%; - const char *XTRA_CFLAGS = %OCTAVE_CONF_XTRA_CFLAGS%; +const char *XTRA_CFLAGS = %OCTAVE_CONF_XTRA_CFLAGS%; - const char *XTRA_CXXFLAGS = %OCTAVE_CONF_XTRA_CXXFLAGS%; +const char *XTRA_CXXFLAGS = %OCTAVE_CONF_XTRA_CXXFLAGS%; - const char *YACC = %OCTAVE_CONF_YACC%; +const char *YACC = %OCTAVE_CONF_YACC%; - const char *YFLAGS = %OCTAVE_CONF_YFLAGS%; +const char *YFLAGS = %OCTAVE_CONF_YFLAGS%; - const char *Z_CPPFLAGS = %OCTAVE_CONF_Z_CPPFLAGS%; +const char *Z_CPPFLAGS = %OCTAVE_CONF_Z_CPPFLAGS%; - const char *Z_LDFLAGS = %OCTAVE_CONF_Z_LDFLAGS%; +const char *Z_LDFLAGS = %OCTAVE_CONF_Z_LDFLAGS%; - const char *Z_LIBS = %OCTAVE_CONF_Z_LIBS%; +const char *Z_LIBS = %OCTAVE_CONF_Z_LIBS%; - const char *config_opts = %OCTAVE_CONF_config_opts%; +const char *config_opts = %OCTAVE_CONF_config_opts%; OCTAVE_END_NAMESPACE(build_env) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/Cell.h --- a/libinterp/corefcn/Cell.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/Cell.h Thu Dec 01 20:05:44 2022 -0800 @@ -87,7 +87,7 @@ octave_idx_type i = 0; for (const auto& val : container) - elem(i++,0) = val; + elem(i++, 0) = val; } } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__betainc__.cc --- a/libinterp/corefcn/__betainc__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__betainc__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -118,7 +118,7 @@ alpha_j = ((aj + j - 1) * (aj + bj + j -1) * (bj - j) * j) / ((aj + 2 * j - 1) * (aj + 2 * j - 1)) * x2; beta_j = aj + 2 * j + ((j * (bj - j)) / (aj + 2 * j - 1) - - ((aj + j) * (aj + bj + j)) / (aj + 2 * j + 1)) * xj; + - ((aj + j) * (aj + bj + j)) / (aj + 2 * j + 1)) * xj; j++; } @@ -189,7 +189,7 @@ alpha_j = ((aj + j - 1) * (aj + bj + j - 1) * (bj - j) * j) / ((aj + 2 * j - 1) * (aj + 2 * j - 1)) * x2; beta_j = aj + 2 * j + ((j * (bj - j)) / (aj + 2 * j - 1) - - ((aj + j) * (aj + bj + j)) / (aj + 2 * j + 1)) * xj; + - ((aj + j) * (aj + bj + j)) / (aj + 2 * j + 1)) * xj; j++; } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__eigs__.cc --- a/libinterp/corefcn/__eigs__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__eigs__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -327,7 +327,8 @@ if (! args(3+arg_offset).isstruct ()) error ("eigs: OPTS argument must be a structure"); - octave_scalar_map map = args(3+arg_offset).xscalar_map_value ("eigs: OPTS argument must be a scalar structure"); + octave_scalar_map map = args(3 + +arg_offset).xscalar_map_value ("eigs: OPTS argument must be a scalar structure"); octave_value tmp; @@ -445,9 +446,9 @@ EigsComplexFunc eigs_complex_fcn = [&callback] (const ComplexColumnVector& x, int& eigs_error) - { - return callback.eigs_complex_func (x, eigs_error); - }; + { + return callback.eigs_complex_func (x, eigs_error); + }; ComplexMatrix eig_vec; ComplexColumnVector eig_val; @@ -512,9 +513,9 @@ EigsComplexFunc eigs_complex_fcn = [&callback] (const ComplexColumnVector& x, int& eigs_error) - { - return callback.eigs_complex_func (x, eigs_error); - }; + { + return callback.eigs_complex_func (x, eigs_error); + }; // Promote real problem to a complex one. ComplexMatrix eig_vec; @@ -565,9 +566,9 @@ else { EigsFunc eigs_fcn = [&callback] (const ColumnVector& x, int& eigs_error) - { - return callback.eigs_func (x, eigs_error); - }; + { + return callback.eigs_func (x, eigs_error); + }; if (symmetric) { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__ftp__.cc --- a/libinterp/corefcn/__ftp__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__ftp__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -384,7 +384,7 @@ // FIXME: Does ascii mode need to be flagged here? std::ifstream ifile = sys::ifstream (file.c_str (), - std::ios::in | std::ios::binary); + std::ios::in | std::ios::binary); if (! ifile.is_open ()) error ("__ftp_mput__: unable to open file"); @@ -450,7 +450,7 @@ { std::ofstream ofile = sys::ofstream ((target + sv(i)).c_str (), - std::ios::out | std::ios::binary); + std::ios::out | std::ios::binary); if (! ofile.is_open ()) error ("__ftp_mget__: unable to open file"); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__ichol__.cc --- a/libinterp/corefcn/__ichol__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__ichol__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -203,7 +203,7 @@ { SparseMatrix sm = Ftril (args(0))(0).sparse_matrix_value (); ichol_0 (sm, michol); + ichol_checkpivot_real> (sm, michol); return ovl (sm); } else @@ -211,14 +211,14 @@ SparseComplexMatrix sm = Ftril (args(0))(0).sparse_complex_matrix_value (); ichol_0 (sm, michol); + ichol_checkpivot_complex> (sm, michol); return ovl (sm); } } template -void ichol_t (const octave_matrix_t& sm, octave_matrix_t& L, const T* cols_norm, +void ichol_t (const octave_matrix_t& sm, octave_matrix_t& L, const T *cols_norm, const T droptol, const std::string michol = "off") { @@ -437,8 +437,8 @@ SparseMatrix sm_l = Ftril (args(0))(0).sparse_matrix_value (); RowVector sm_col_norms = xcolnorms (sm_l, 1); ichol_t - (sm_l, L, sm_col_norms.fortran_vec (), droptol, michol); + double, ichol_mult_real, ichol_checkpivot_real> + (sm_l, L, sm_col_norms.fortran_vec (), droptol, michol); return ovl (L); } @@ -449,9 +449,9 @@ = Ftril (args(0))(0).sparse_complex_matrix_value (); Array cols_norm = xcolnorms (sm_l, 1); ichol_t - (sm_l, L, cols_norm.fortran_vec (), - Complex (droptol), michol); + Complex, ichol_mult_complex, ichol_checkpivot_complex> + (sm_l, L, cols_norm.fortran_vec (), + Complex (droptol), michol); return ovl (L); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__ilu__.cc --- a/libinterp/corefcn/__ilu__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__ilu__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -504,9 +504,9 @@ Array rows_norm = xrownorms (sm); ilu_crout (sm_l, sm_u, L, U, - cols_norm.fortran_vec (), - rows_norm.fortran_vec (), - Complex (droptol), milu); + cols_norm.fortran_vec (), + rows_norm.fortran_vec (), + Complex (droptol), milu); SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0)); @@ -974,8 +974,8 @@ Array perm (dim_vector (sm.cols (), 1)); ilu_tp - (sm, L, U, nnz_u, nnz_l, rc_norm.fortran_vec (), perm, - Complex (droptol), Complex (thresh), milu, udiag); + (sm, L, U, nnz_u, nnz_l, rc_norm.fortran_vec (), perm, + Complex (droptol), Complex (thresh), milu, udiag); SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0)); if (milu == "row") diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__isprimelarge__.cc --- a/libinterp/corefcn/__isprimelarge__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__isprimelarge__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -117,11 +117,11 @@ // If it fails any, then it is composite. // The first 12 primes suffice to test all 64-bit integers. return millerrabin ( 2, d, r, n) && millerrabin ( 3, d, r, n) - && millerrabin ( 5, d, r, n) && millerrabin ( 7, d, r, n) - && millerrabin (11, d, r, n) && millerrabin (13, d, r, n) - && millerrabin (17, d, r, n) && millerrabin (19, d, r, n) - && millerrabin (23, d, r, n) && millerrabin (29, d, r, n) - && millerrabin (31, d, r, n) && millerrabin (37, d, r, n); + && millerrabin ( 5, d, r, n) && millerrabin ( 7, d, r, n) + && millerrabin (11, d, r, n) && millerrabin (13, d, r, n) + && millerrabin (17, d, r, n) && millerrabin (19, d, r, n) + && millerrabin (23, d, r, n) && millerrabin (29, d, r, n) + && millerrabin (31, d, r, n) && millerrabin (37, d, r, n); /* Mathematical references for the curious as to why we need only @@ -162,7 +162,7 @@ // so the following error handling should not be necessary. But it is // probably good practice for any curious users calling it directly. uint64NDArray vec = args(0).xuint64_array_value - ("__isprimelarge__: unable to convert input. Call isprime() instead."); + ("__isprimelarge__: unable to convert input. Call isprime() instead."); boolNDArray retval (vec.dims(), false); @@ -205,7 +205,7 @@ localgcd (uint64_t a, uint64_t b) { return (a <= b) ? ( (b % a == 0) ? a : localgcd (a, b % a) ) - : ( (a % b == 0) ? b : localgcd (a % b, b) ); + : ( (a % b == 0) ? b : localgcd (a % b, b) ); } // This function implements a textbook version of the Pollard Rho @@ -263,7 +263,7 @@ print_usage (); octave_uint64 inp = args(0).xuint64_scalar_value - ("__pollardrho__: unable to convert input. Call factor() instead."); + ("__pollardrho__: unable to convert input. Call factor() instead."); uint64_t n = inp; octave_uint64 retval = pollardrho (n); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__magick_read__.cc --- a/libinterp/corefcn/__magick_read__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__magick_read__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -533,7 +533,7 @@ const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (col_start, row_start, - col_cache, row_cache); + col_cache, row_cache); for (octave_idx_type col = 0; col < nCols; col++) { @@ -562,7 +562,7 @@ const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (col_start, row_start, - col_cache, row_cache); + col_cache, row_cache); for (octave_idx_type col = 0; col < nCols; col++) { @@ -593,7 +593,7 @@ const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (col_start, row_start, - col_cache, row_cache); + col_cache, row_cache); octave_idx_type idx = 0; P *rbuf = img_fvec; @@ -636,7 +636,7 @@ const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (col_start, row_start, - col_cache, row_cache); + col_cache, row_cache); octave_idx_type idx = 0; P *rbuf = img_fvec; @@ -674,7 +674,7 @@ const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (col_start, row_start, - col_cache, row_cache); + col_cache, row_cache); octave_idx_type idx = 0; P *cbuf = img_fvec; @@ -719,7 +719,7 @@ const Magick::PixelPacket *pix = imvec[frameidx(frame)].getConstPixels (col_start, row_start, - col_cache, row_cache); + col_cache, row_cache); // Note that for CMYKColorspace + matte (CMYKA), the opacity is // stored in the associated IndexPacket. const Magick::IndexPacket *apix @@ -914,13 +914,13 @@ { if (depth <= 1) output = read_indexed_images (imvec, frameidx, - nargout, options); + nargout, options); else if (depth <= 8) output = read_indexed_images (imvec, frameidx, - nargout, options); + nargout, options); else if (depth <= 16) output = read_indexed_images (imvec, frameidx, - nargout, options); + nargout, options); else error ("imread: indexed images with depths greater than 16-bit are not supported"); } @@ -1051,8 +1051,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - Magick::PaletteType, - Magick::PseudoClass); + Magick::PaletteType, + Magick::PseudoClass); // Insert colormap. m_img.colorMapSize (cmap_size); @@ -1112,8 +1112,8 @@ // However, this will still work fine and a binary image will be // saved because we are setting the bitdepth to 1. Magick::Image m_img = init_enconde_image (nCols, nRows, 1, - Magick::GrayscaleType, - Magick::DirectClass); + Magick::GrayscaleType, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); octave_idx_type GM_idx = 0; @@ -1201,8 +1201,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - type, - Magick::DirectClass); + type, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); octave_idx_type GM_idx = 0; @@ -1232,8 +1232,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - type, - Magick::DirectClass); + type, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); octave_idx_type GM_idx = 0; @@ -1268,8 +1268,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - type, - Magick::DirectClass); + type, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); octave_idx_type GM_idx = 0; @@ -1304,8 +1304,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - type, - Magick::DirectClass); + type, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); octave_idx_type GM_idx = 0; @@ -1343,8 +1343,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - type, - Magick::DirectClass); + type, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); octave_idx_type GM_idx = 0; @@ -1381,8 +1381,8 @@ octave_quit (); Magick::Image m_img = init_enconde_image (nCols, nRows, bitdepth, - type, - Magick::DirectClass); + type, + Magick::DirectClass); Magick::PixelPacket *pix = m_img.getPixels (0, 0, nCols, nRows); Magick::IndexPacket *ind = m_img.getIndexes (); @@ -1541,9 +1541,9 @@ if (img.is_single_type ()) { clip_img = img_float2uint - (img.float_array_value ()); + (img.float_array_value ()); clip_alpha = img_float2uint - (alpha.float_array_value ()); + (alpha.float_array_value ()); } else { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/__pchip_deriv__.cc --- a/libinterp/corefcn/__pchip_deriv__.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/__pchip_deriv__.cc Thu Dec 01 20:05:44 2022 -0800 @@ -81,22 +81,22 @@ for (volatile octave_idx_type i = (rows ? nyr : nyc); i > 0; i--) { F77_XFCN (pchim, PCHIM, (nx, xvec.data (), - reinterpret_cast(ymat.data ()) + k * inc, - reinterpret_cast(dmat.fortran_vec ()) + k * inc, + reinterpret_cast(ymat.data ()) + k * inc, + reinterpret_cast(dmat.fortran_vec ()) + k * inc, incfd, ierr)); if (ierr < 0) error ("__pchip_deriv__: PCHIM failed for real part with ierr = %" - OCTAVE_F77_INT_TYPE_FORMAT, ierr); + OCTAVE_F77_INT_TYPE_FORMAT, ierr); F77_XFCN (pchim, PCHIM, (nx, xvec.data (), - reinterpret_cast(ymat.data ()) + 1 + k * inc, - reinterpret_cast(dmat.fortran_vec ()) + 1 + k * inc, + reinterpret_cast(ymat.data ()) + 1 + k * inc, + reinterpret_cast(dmat.fortran_vec ()) + 1 + k * inc, incfd, ierr)); if (ierr < 0) error ("__pchip_deriv__: PCHIM failed for imaginary part with ierr = %" - OCTAVE_F77_INT_TYPE_FORMAT, ierr); + OCTAVE_F77_INT_TYPE_FORMAT, ierr); k++; } @@ -131,7 +131,7 @@ if (ierr < 0) error ("__pchip_deriv__: PCHIM failed with ierr = %" - OCTAVE_F77_INT_TYPE_FORMAT, ierr); + OCTAVE_F77_INT_TYPE_FORMAT, ierr); } retval = dmat; @@ -164,22 +164,22 @@ for (volatile octave_idx_type i = (rows ? nyr : nyc); i > 0; i--) { F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (), - reinterpret_cast(ymat.data ()) + k * inc, - reinterpret_cast(dmat.fortran_vec ()) + k * inc, + reinterpret_cast(ymat.data ()) + k * inc, + reinterpret_cast(dmat.fortran_vec ()) + k * inc, incfd, ierr)); if (ierr < 0) error ("__pchip_deriv__: DPCHIM failed for real part with ierr = %" - OCTAVE_F77_INT_TYPE_FORMAT, ierr); + OCTAVE_F77_INT_TYPE_FORMAT, ierr); F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (), - reinterpret_cast(ymat.data ()) + 1 + k * inc, - reinterpret_cast(dmat.fortran_vec ()) + 1 + k * inc, + reinterpret_cast(ymat.data ()) + 1 + k * inc, + reinterpret_cast(dmat.fortran_vec ()) + 1 + k * inc, incfd, ierr)); if (ierr < 0) error ("__pchip_deriv__: DPCHIM failed for imaginary part with ierr = %" - OCTAVE_F77_INT_TYPE_FORMAT, ierr); + OCTAVE_F77_INT_TYPE_FORMAT, ierr); k++; } @@ -213,7 +213,7 @@ if (ierr < 0) error ("__pchip_deriv__: DPCHIM failed with ierr = %" - OCTAVE_F77_INT_TYPE_FORMAT, ierr); + OCTAVE_F77_INT_TYPE_FORMAT, ierr); } retval = dmat; diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/amd.cc --- a/libinterp/corefcn/amd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/amd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -132,7 +132,8 @@ AMD_NAME (_defaults) (Control); if (nargin > 1) { - octave_scalar_map arg1 = args(1).xscalar_map_value ("amd: OPTS argument must be a scalar structure"); + octave_scalar_map arg1 = args( + 1).xscalar_map_value ("amd: OPTS argument must be a scalar structure"); octave_value tmp; @@ -158,7 +159,7 @@ SUITESPARSE_ASSIGN_FPTR (printf_func, amd_printf, printf); octave_idx_type result = AMD_NAME (_order) (n_col, cidx, ridx, P, Control, - Info); + Info); if (result == AMD_OUT_OF_MEMORY) error ("amd: out of memory"); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/base-text-renderer.cc --- a/libinterp/corefcn/base-text-renderer.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/base-text-renderer.cc Thu Dec 01 20:05:44 2022 -0800 @@ -31,144 +31,144 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - base_text_renderer::rotate_pixels (uint8NDArray& pixels, int rot_mode) const - { - switch (rot_mode) - { - case ROTATION_0: - break; +void +base_text_renderer::rotate_pixels (uint8NDArray& pixels, int rot_mode) const +{ + switch (rot_mode) + { + case ROTATION_0: + break; - case ROTATION_90: - { - Array perm (dim_vector (3, 1)); - perm(0) = 0; - perm(1) = 2; - perm(2) = 1; - pixels = pixels.permute (perm); + case ROTATION_90: + { + Array perm (dim_vector (3, 1)); + perm(0) = 0; + perm(1) = 2; + perm(2) = 1; + pixels = pixels.permute (perm); - Array idx (dim_vector (3, 1)); - idx(0) = idx_vector (':'); - idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1); - idx(2) = idx_vector (':'); - pixels = uint8NDArray (pixels.index (idx)); - } - break; + Array idx (dim_vector (3, 1)); + idx(0) = idx_vector (':'); + idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1); + idx(2) = idx_vector (':'); + pixels = uint8NDArray (pixels.index (idx)); + } + break; - case ROTATION_180: - { - Array idx (dim_vector (3, 1)); - idx(0) = idx_vector (':'); - idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1); - idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1); - pixels = uint8NDArray (pixels.index (idx)); - } - break; + case ROTATION_180: + { + Array idx (dim_vector (3, 1)); + idx(0) = idx_vector (':'); + idx(1) = idx_vector (pixels.dim2 ()-1, -1, -1); + idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1); + pixels = uint8NDArray (pixels.index (idx)); + } + break; - case ROTATION_270: - { - Array perm (dim_vector (3, 1)); - perm(0) = 0; - perm(1) = 2; - perm(2) = 1; - pixels = pixels.permute (perm); + case ROTATION_270: + { + Array perm (dim_vector (3, 1)); + perm(0) = 0; + perm(1) = 2; + perm(2) = 1; + pixels = pixels.permute (perm); - Array idx (dim_vector (3, 1)); - idx(0) = idx_vector (':'); - idx(1) = idx_vector (':'); - idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1); - pixels = uint8NDArray (pixels.index (idx)); - } - break; - + Array idx (dim_vector (3, 1)); + idx(0) = idx_vector (':'); + idx(1) = idx_vector (':'); + idx(2) = idx_vector (pixels.dim3 ()-1, -1, -1); + pixels = uint8NDArray (pixels.index (idx)); } - } + break; + + } +} - int - base_text_renderer::rotation_to_mode (double rotation) const - { - // Wrap rotation to range [0, 360] - while (rotation < 0) - rotation += 360.0; - while (rotation > 360.0) - rotation -= 360.0; +int +base_text_renderer::rotation_to_mode (double rotation) const +{ + // Wrap rotation to range [0, 360] + while (rotation < 0) + rotation += 360.0; + while (rotation > 360.0) + rotation -= 360.0; - if (rotation == 0.0) - return ROTATION_0; - else if (rotation == 90.0) - return ROTATION_90; - else if (rotation == 180.0) - return ROTATION_180; - else if (rotation == 270.0) - return ROTATION_270; - else - return ROTATION_0; - } + if (rotation == 0.0) + return ROTATION_0; + else if (rotation == 90.0) + return ROTATION_90; + else if (rotation == 180.0) + return ROTATION_180; + else if (rotation == 270.0) + return ROTATION_270; + else + return ROTATION_0; +} - void - base_text_renderer::fix_bbox_anchor (Matrix& bbox, int halign, - int valign, int rot_mode, - bool handle_rotation) const - { - switch (halign) - { - case 1: - bbox(0) = -bbox(2)/2; - break; +void +base_text_renderer::fix_bbox_anchor (Matrix& bbox, int halign, + int valign, int rot_mode, + bool handle_rotation) const +{ + switch (halign) + { + case 1: + bbox(0) = -bbox(2)/2; + break; - case 2: - bbox(0) = -bbox(2); - break; + case 2: + bbox(0) = -bbox(2); + break; - default: - bbox(0) = 0; - break; - } + default: + bbox(0) = 0; + break; + } - switch (valign) - { - case 1: - bbox(1) = -bbox(3)/2; - break; + switch (valign) + { + case 1: + bbox(1) = -bbox(3)/2; + break; - case 2: - bbox(1) = -bbox(3); - break; + case 2: + bbox(1) = -bbox(3); + break; - case 3: - break; + case 3: + break; - case 4: - bbox(1) = -bbox(3)-bbox(1); - break; + case 4: + bbox(1) = -bbox(3)-bbox(1); + break; - default: - bbox(1) = 0; - break; - } + default: + bbox(1) = 0; + break; + } - if (handle_rotation) - { - switch (rot_mode) - { - case ROTATION_90: - std::swap (bbox(0), bbox(1)); - std::swap (bbox(2), bbox(3)); - bbox(0) = -bbox(0)-bbox(2); - break; + if (handle_rotation) + { + switch (rot_mode) + { + case ROTATION_90: + std::swap (bbox(0), bbox(1)); + std::swap (bbox(2), bbox(3)); + bbox(0) = -bbox(0)-bbox(2); + break; - case ROTATION_180: - bbox(0) = -bbox(0)-bbox(2); - bbox(1) = -bbox(1)-bbox(3); - break; + case ROTATION_180: + bbox(0) = -bbox(0)-bbox(2); + bbox(1) = -bbox(1)-bbox(3); + break; - case ROTATION_270: - std::swap (bbox(0), bbox(1)); - std::swap (bbox(2), bbox(3)); - bbox(1) = -bbox(1)-bbox(3); - break; - } - } - } + case ROTATION_270: + std::swap (bbox(0), bbox(1)); + std::swap (bbox(2), bbox(3)); + bbox(1) = -bbox(1)-bbox(3); + break; + } + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/base-text-renderer.h --- a/libinterp/corefcn/base-text-renderer.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/base-text-renderer.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,72 +40,72 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - base_text_renderer : public text_processor - { - public: +class +base_text_renderer : public text_processor +{ +public: - enum - { - ROTATION_0 = 0, - ROTATION_90 = 1, - ROTATION_180 = 2, - ROTATION_270 = 3 - }; + enum + { + ROTATION_0 = 0, + ROTATION_90 = 1, + ROTATION_180 = 2, + ROTATION_270 = 3 + }; - base_text_renderer (void) : text_processor () { } + base_text_renderer (void) : text_processor () { } - // No copying! + // No copying! - base_text_renderer (const base_text_renderer&) = delete; + base_text_renderer (const base_text_renderer&) = delete; - base_text_renderer& operator = (const base_text_renderer&) = delete; + base_text_renderer& operator = (const base_text_renderer&) = delete; - virtual ~base_text_renderer (void) = default; + virtual ~base_text_renderer (void) = default; - virtual void - set_anti_aliasing (bool val) = 0; + virtual void + set_anti_aliasing (bool val) = 0; - virtual Matrix - get_extent (text_element *elt, double rotation) = 0; + virtual Matrix + get_extent (text_element *elt, double rotation) = 0; - virtual Matrix - get_extent (const std::string& txt, double rotation, - const caseless_str& interpreter) = 0; + virtual Matrix + get_extent (const std::string& txt, double rotation, + const caseless_str& interpreter) = 0; - virtual void - set_font (const std::string& name, const std::string& weight, - const std::string& angle, double size) = 0; + virtual void + set_font (const std::string& name, const std::string& weight, + const std::string& angle, double size) = 0; - virtual bool - ok (void) { return true; }; + virtual bool + ok (void) { return true; }; - virtual octave_map - get_system_fonts (void) = 0; + virtual octave_map + get_system_fonts (void) = 0; - virtual void set_color (const Matrix& c) = 0; + virtual void set_color (const Matrix& c) = 0; - virtual void - text_to_pixels (const std::string& txt, uint8NDArray& pxls, - Matrix& bbox, int halign, int valign, double rotation, - const caseless_str& interpreter, - bool handle_rotation) = 0; + virtual void + text_to_pixels (const std::string& txt, uint8NDArray& pxls, + Matrix& bbox, int halign, int valign, double rotation, + const caseless_str& interpreter, + bool handle_rotation) = 0; - virtual void - text_to_strlist (const std::string& txt, - std::list& lst, - Matrix& box, int halign, int valign, double rotation, - const caseless_str& interpreter = "tex") = 0; + virtual void + text_to_strlist (const std::string& txt, + std::list& lst, + Matrix& box, int halign, int valign, double rotation, + const caseless_str& interpreter = "tex") = 0; - void rotate_pixels (uint8NDArray& pixels, int rot_mode) const; + void rotate_pixels (uint8NDArray& pixels, int rot_mode) const; - int rotation_to_mode (double rotation) const; + int rotation_to_mode (double rotation) const; - void fix_bbox_anchor (Matrix& bbox, int halign, - int valign, int rot_mode, - bool handle_rotation) const; + void fix_bbox_anchor (Matrix& bbox, int halign, + int valign, int rot_mode, + bool handle_rotation) const; - }; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/besselj.cc --- a/libinterp/corefcn/besselj.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/besselj.cc Thu Dec 01 20:05:44 2022 -0800 @@ -161,7 +161,8 @@ if (args0_is_row_vector && args1_is_col_vector) { - FloatRowVector ralpha = args(0).xfloat_row_vector_value ("%s: ALPHA must be a scalar or matrix", fcn); + FloatRowVector ralpha = args(0).xfloat_row_vector_value ("%s: ALPHA must be a scalar or matrix", + fcn); FloatComplexColumnVector cx = x_arg.xfloat_complex_column_vector_value ("%s: X must be a scalar or matrix", fcn); @@ -795,12 +796,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %!assert (besselj (-alpha,x), jx, 100*eps) %!assert (bessely (-alpha,x), yx, 100*eps) @@ -809,12 +810,12 @@ %!assert (besselh (-alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (-alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (-alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (-alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (-alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (-alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (-alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (-alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (-alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (-alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (-alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! x *= -1; %! yx = -1.193199310178553861283790424 + 0.3421822624810469647226182835*I; @@ -827,12 +828,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! ## Bessel functions, odd order, positive and negative x %! alpha = 3; x = 2.5; @@ -848,12 +849,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %!assert (besselj (-alpha,x), -jx, 100*eps) %!assert (bessely (-alpha,x), -yx, 100*eps) @@ -862,12 +863,12 @@ %!assert (besselh (-alpha,1,x), -(jx + I*yx), 100*eps) %!assert (besselh (-alpha,2,x), -(jx - I*yx), 100*eps) %! -%!assert (besselj (-alpha,x,1), -jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (-alpha,x,1), -yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (-alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (-alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (-alpha,1,x,1), -(jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (-alpha,2,x,1), -(jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (-alpha,x,1), -yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (-alpha,1,x,1), -(jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (-alpha,2,x,1), -(jx - I*yx)* exp (I*x), 100*eps) %! %! x *= -1; %! jx = -jx; @@ -882,12 +883,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! ## Bessel functions, fractional order, positive and negative x %! @@ -904,12 +905,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! nix = 0.2119931212254662995364461998; %! @@ -920,12 +921,12 @@ %!assert (besselh (-alpha,1,x), -I*(jx + I*yx), 100*eps) %!assert (besselh (-alpha,2,x), I*(jx - I*yx), 100*eps) %! -%!assert (besselj (-alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (-alpha,x,1), -jx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (-alpha,x,1), nix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (-alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (-alpha,1,x,1), -I*(jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (-alpha,2,x,1), I*(jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (-alpha,x,1), nix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (-alpha,1,x,1), -I*(jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (-alpha,2,x,1), I*(jx - I*yx)* exp (I*x), 100*eps) %! %! x *= -1; %! jx *= -I; @@ -940,12 +941,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! ## Bessel functions, even order, complex x %! @@ -962,12 +963,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %!assert (besselj (-alpha,x), jx, 100*eps) %!assert (bessely (-alpha,x), yx, 100*eps) @@ -976,12 +977,12 @@ %!assert (besselh (-alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (-alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (-alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (-alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (-alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (-alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (-alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (-alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (-alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (-alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (-alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! ## Bessel functions, odd order, complex x %! @@ -998,12 +999,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %!assert (besselj (-alpha,x), -jx, 100*eps) %!assert (bessely (-alpha,x), -yx, 100*eps) @@ -1012,12 +1013,12 @@ %!assert (besselh (-alpha,1,x), -(jx + I*yx), 100*eps) %!assert (besselh (-alpha,2,x), -(jx - I*yx), 100*eps) %! -%!assert (besselj (-alpha,x,1), -jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (-alpha,x,1), -yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (-alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (-alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (-alpha,1,x,1), -(jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (-alpha,2,x,1), -(jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (-alpha,x,1), -yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (-alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (-alpha,1,x,1), -(jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (-alpha,2,x,1), -(jx - I*yx)* exp (I*x), 100*eps) %! %! ## Bessel functions, fractional order, complex x %! @@ -1034,12 +1035,12 @@ %!assert (besselh (alpha,1,x), jx + I*yx, 100*eps) %!assert (besselh (alpha,2,x), jx - I*yx, 100*eps) %! -%!assert (besselj (alpha,x,1), jx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (alpha,x,1), ix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (alpha,1,x,1), (jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (alpha,2,x,1), (jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (alpha,x,1), jx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (alpha,x,1), ix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (alpha,1,x,1), (jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (alpha,2,x,1), (jx - I*yx)* exp (I*x), 100*eps) %! %! nix = 0.09822388691172060573913739253 - 0.7110230642207380127317227407*I; %! @@ -1050,12 +1051,12 @@ %!assert (besselh (-alpha,1,x), -I*(jx + I*yx), 100*eps) %!assert (besselh (-alpha,2,x), I*(jx - I*yx), 100*eps) %! -%!assert (besselj (-alpha,x,1), yx*exp (-abs (imag (x))), 100*eps) -%!assert (bessely (-alpha,x,1), -jx*exp (-abs (imag (x))), 100*eps) -%!assert (besseli (-alpha,x,1), nix*exp (-abs (real (x))), 100*eps) -%!assert (besselk (-alpha,x,1), kx*exp (x), 100*eps) -%!assert (besselh (-alpha,1,x,1), -I*(jx + I*yx)*exp (-I*x), 100*eps) -%!assert (besselh (-alpha,2,x,1), I*(jx - I*yx)*exp (I*x), 100*eps) +%!assert (besselj (-alpha,x,1), yx* exp (-abs (imag (x))), 100*eps) +%!assert (bessely (-alpha,x,1), -jx* exp (-abs (imag (x))), 100*eps) +%!assert (besseli (-alpha,x,1), nix* exp (-abs (real (x))), 100*eps) +%!assert (besselk (-alpha,x,1), kx* exp (x), 100*eps) +%!assert (besselh (-alpha,1,x,1), -I*(jx + I*yx)* exp (-I*x), 100*eps) +%!assert (besselh (-alpha,2,x,1), I*(jx - I*yx)* exp (I*x), 100*eps) Tests contributed by Robert T. Short. Tests are based on the properties and tables in A&S: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/bitfcns.cc --- a/libinterp/corefcn/bitfcns.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/bitfcns.cc Thu Dec 01 20:05:44 2022 -0800 @@ -53,26 +53,26 @@ #if ! defined (HAVE_CXX_BITWISE_OP_TEMPLATES) OCTAVE_BEGIN_NAMESPACE(std) - template - struct bit_and - { - public: - T operator() (const T& op1, const T& op2) const { return (op1 & op2); } - }; +template +struct bit_and +{ +public: + T operator() (const T& op1, const T& op2) const { return (op1 & op2); } +}; - template - struct bit_or - { - public: - T operator() (const T& op1, const T& op2) const { return (op1 | op2); } - }; +template +struct bit_or +{ +public: + T operator() (const T& op1, const T& op2) const { return (op1 | op2); } +}; - template - struct bit_xor - { - public: - T operator() (const T& op1, const T& op2) const { return (op1 ^ op2); } - }; +template +struct bit_xor +{ +public: + T operator() (const T& op1, const T& op2) const { return (op1 ^ op2); } +}; OCTAVE_END_NAMESPACE(std) #endif diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/bsxfun.cc --- a/libinterp/corefcn/bsxfun.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/bsxfun.cc Thu Dec 01 20:05:44 2022 -0800 @@ -405,9 +405,9 @@ for (octave_idx_type i = 0; i < nd; i++) dvc(i) = (dva(i) < 1 ? dva(i) - : (dvb(i) < 1 ? dvb(i) - : (dva(i) > dvb(i) ? dva(i) - : dvb(i)))); + : (dvb(i) < 1 ? dvb(i) + : (dva(i) > dvb(i) ? dva(i) + : dvb(i)))); if (dva == dvb || dva.numel () == 1 || dvb.numel () == 1) { @@ -512,19 +512,19 @@ } } else if BSXINIT(boolNDArray, "logical", bool) - else if BSXINIT(int8NDArray, "int8", int8) - else if BSXINIT(int16NDArray, "int16", int16) - else if BSXINIT(int32NDArray, "int32", int32) - else if BSXINIT(int64NDArray, "int64", int64) - else if BSXINIT(uint8NDArray, "uint8", uint8) - else if BSXINIT(uint16NDArray, "uint16", uint16) - else if BSXINIT(uint32NDArray, "uint32", uint32) - else if BSXINIT(uint64NDArray, "uint64", uint64) - else - { - C = tmp(0); - C = C.resize (dvc); - } + else if BSXINIT(int8NDArray, "int8", int8) + else if BSXINIT(int16NDArray, "int16", int16) + else if BSXINIT(int32NDArray, "int32", int32) + else if BSXINIT(int64NDArray, "int64", int64) + else if BSXINIT(uint8NDArray, "uint8", uint8) + else if BSXINIT(uint16NDArray, "uint16", uint16) + else if BSXINIT(uint32NDArray, "uint32", uint32) + else if BSXINIT(uint64NDArray, "uint64", uint64) + else + { + C = tmp(0); + C = C.resize (dvc); + } } else // Skip semi-fast path for sparse matrices { @@ -551,7 +551,7 @@ result_ComplexNDArray = ComplexNDArray (result_NDArray); result_ComplexNDArray.insert - (tmp(0).complex_array_value (), ra_idx); + (tmp(0).complex_array_value (), ra_idx); have_NDArray = false; have_ComplexNDArray = true; } @@ -566,13 +566,13 @@ } else if (tmp(0).isreal ()) result_FloatNDArray.insert - (tmp(0).float_array_value (), ra_idx); + (tmp(0).float_array_value (), ra_idx); else { result_FloatComplexNDArray = FloatComplexNDArray (result_FloatNDArray); result_FloatComplexNDArray.insert - (tmp(0).float_complex_array_value (), ra_idx); + (tmp(0).float_complex_array_value (), ra_idx); have_FloatNDArray = false; have_FloatComplexNDArray = true; } @@ -592,18 +592,18 @@ } else if BSXLOOP(ComplexNDArray, "double", complex) - else if BSXLOOP(FloatComplexNDArray, "single", float_complex) - else if BSXLOOP(boolNDArray, "logical", bool) - else if BSXLOOP(int8NDArray, "int8", int8) - else if BSXLOOP(int16NDArray, "int16", int16) - else if BSXLOOP(int32NDArray, "int32", int32) - else if BSXLOOP(int64NDArray, "int64", int64) - else if BSXLOOP(uint8NDArray, "uint8", uint8) - else if BSXLOOP(uint16NDArray, "uint16", uint16) - else if BSXLOOP(uint32NDArray, "uint32", uint32) - else if BSXLOOP(uint64NDArray, "uint64", uint64) - else - C = cat_op (C, tmp(0), ra_idx); + else if BSXLOOP(FloatComplexNDArray, "single", float_complex) + else if BSXLOOP(boolNDArray, "logical", bool) + else if BSXLOOP(int8NDArray, "int8", int8) + else if BSXLOOP(int16NDArray, "int16", int16) + else if BSXLOOP(int32NDArray, "int32", int32) + else if BSXLOOP(int64NDArray, "int64", int64) + else if BSXLOOP(uint8NDArray, "uint8", uint8) + else if BSXLOOP(uint16NDArray, "uint16", uint16) + else if BSXLOOP(uint32NDArray, "uint32", uint32) + else if BSXLOOP(uint64NDArray, "uint64", uint64) + else + C = cat_op (C, tmp(0), ra_idx); } } @@ -612,20 +612,20 @@ retval(0) = result_ ## T; if BSXEND(NDArray) - else if BSXEND(ComplexNDArray) - else if BSXEND(FloatNDArray) - else if BSXEND(FloatComplexNDArray) - else if BSXEND(boolNDArray) - else if BSXEND(int8NDArray) - else if BSXEND(int16NDArray) - else if BSXEND(int32NDArray) - else if BSXEND(int64NDArray) - else if BSXEND(uint8NDArray) - else if BSXEND(uint16NDArray) - else if BSXEND(uint32NDArray) - else if BSXEND(uint64NDArray) - else - retval(0) = C; + else if BSXEND(ComplexNDArray) + else if BSXEND(FloatNDArray) + else if BSXEND(FloatComplexNDArray) + else if BSXEND(boolNDArray) + else if BSXEND(int8NDArray) + else if BSXEND(int16NDArray) + else if BSXEND(int32NDArray) + else if BSXEND(int64NDArray) + else if BSXEND(uint8NDArray) + else if BSXEND(uint16NDArray) + else if BSXEND(uint32NDArray) + else if BSXEND(uint64NDArray) + else + retval(0) = C; } } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/c-file-ptr-stream.h --- a/libinterp/corefcn/c-file-ptr-stream.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/c-file-ptr-stream.h Thu Dec 01 20:05:44 2022 -0800 @@ -46,7 +46,7 @@ typedef int (*close_fcn) (FILE *); - FILE *stdiofile (void) { return m_f; } + FILE * stdiofile (void) { return m_f; } c_file_ptr_buf (FILE *f, close_fcn cf = file_close) : std::streambuf (), m_f (f), m_cf (cf) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/call-stack.cc --- a/libinterp/corefcn/call-stack.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/call-stack.cc Thu Dec 01 20:05:44 2022 -0800 @@ -49,1090 +49,1090 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Use static fields for the best efficiency. - // NOTE: C++0x will allow these two to be merged into one. - static const char *bt_fieldnames[] = - { "file", "name", "line", "column", nullptr }; +// Use static fields for the best efficiency. +// NOTE: C++0x will allow these two to be merged into one. +static const char *bt_fieldnames[] = +{ "file", "name", "line", "column", nullptr }; - static const octave_fields bt_fields (bt_fieldnames); +static const octave_fields bt_fields (bt_fieldnames); - call_stack::call_stack (tree_evaluator& evaluator) - : m_evaluator (evaluator), m_cs (), m_curr_frame (0), - m_max_stack_depth (1024), m_global_values () - { - push (symbol_scope ("top scope")); - } +call_stack::call_stack (tree_evaluator& evaluator) + : m_evaluator (evaluator), m_cs (), m_curr_frame (0), + m_max_stack_depth (1024), m_global_values () +{ + push (symbol_scope ("top scope")); +} - octave_function * call_stack::current_function (bool skip_first) const - { - if (m_cs.empty ()) - error ("current_function: call stack is empty"); +octave_function *call_stack::current_function (bool skip_first) const +{ + if (m_cs.empty ()) + error ("current_function: call stack is empty"); - octave_function *fcn = nullptr; + octave_function *fcn = nullptr; - std::size_t idx = m_curr_frame; + std::size_t idx = m_curr_frame; - if (idx > 0 && skip_first) - --idx; + if (idx > 0 && skip_first) + --idx; - while (true) - { - fcn = m_cs[idx]->function (); + while (true) + { + fcn = m_cs[idx]->function (); - if (fcn || idx == 0) - break; + if (fcn || idx == 0) + break; - --idx; - } + --idx; + } - return fcn; - } + return fcn; +} - int call_stack::current_line (void) const - { - int retval = -1; +int call_stack::current_line (void) const +{ + int retval = -1; - if (! m_cs.empty ()) - { - const std::shared_ptr elt = m_cs[m_curr_frame]; - retval = elt->line (); - } + if (! m_cs.empty ()) + { + const std::shared_ptr elt = m_cs[m_curr_frame]; + retval = elt->line (); + } - return retval; - } + return retval; +} - int call_stack::current_column (void) const - { - int retval = -1; +int call_stack::current_column (void) const +{ + int retval = -1; - if (! m_cs.empty ()) - { - const std::shared_ptr elt = m_cs[m_curr_frame]; - retval = elt->column (); - } + if (! m_cs.empty ()) + { + const std::shared_ptr elt = m_cs[m_curr_frame]; + retval = elt->column (); + } - return retval; - } + return retval; +} - octave_user_code * call_stack::current_user_code (void) const - { - // Start at current frame. +octave_user_code *call_stack::current_user_code (void) const +{ + // Start at current frame. - std::size_t xframe = find_current_user_frame (); + std::size_t xframe = find_current_user_frame (); - if (xframe > 0) - { - const std::shared_ptr elt = m_cs[xframe]; + if (xframe > 0) + { + const std::shared_ptr elt = m_cs[xframe]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - return dynamic_cast (f); - } + if (f && f->is_user_code ()) + return dynamic_cast (f); + } - return nullptr; - } + return nullptr; +} - int call_stack::current_user_code_line (void) const - { - // Start at current frame. +int call_stack::current_user_code_line (void) const +{ + // Start at current frame. - std::size_t xframe = find_current_user_frame (); + std::size_t xframe = find_current_user_frame (); - if (xframe > 0) - { - const std::shared_ptr elt = m_cs[xframe]; + if (xframe > 0) + { + const std::shared_ptr elt = m_cs[xframe]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - { - int line = elt->line (); + if (f && f->is_user_code ()) + { + int line = elt->line (); - if (line > 0) - return line; - } - } + if (line > 0) + return line; + } + } - return -1; - } + return -1; +} - int call_stack::current_user_code_column (void) const - { - // Start at current frame. +int call_stack::current_user_code_column (void) const +{ + // Start at current frame. - std::size_t xframe = find_current_user_frame (); + std::size_t xframe = find_current_user_frame (); - if (xframe > 0) - { - const std::shared_ptr elt = m_cs[xframe]; + if (xframe > 0) + { + const std::shared_ptr elt = m_cs[xframe]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - { - int column = elt->column (); + if (f && f->is_user_code ()) + { + int column = elt->column (); - if (column > 0) - return column; - } - } + if (column > 0) + return column; + } + } - return -1; - } + return -1; +} - unwind_protect * call_stack::curr_fcn_unwind_protect_frame (void) - { - // Start at current frame. +unwind_protect *call_stack::curr_fcn_unwind_protect_frame (void) +{ + // Start at current frame. - std::size_t xframe = find_current_user_frame (); + std::size_t xframe = find_current_user_frame (); - if (xframe > 0) - { - const std::shared_ptr elt = m_cs[xframe]; + if (xframe > 0) + { + const std::shared_ptr elt = m_cs[xframe]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - return elt->unwind_protect_frame (); - } + if (f && f->is_user_code ()) + return elt->unwind_protect_frame (); + } - return nullptr; - } + return nullptr; +} - octave_user_code * call_stack::debug_user_code (void) const - { - octave_user_code *retval = nullptr; +octave_user_code *call_stack::debug_user_code (void) const +{ + octave_user_code *retval = nullptr; - // This should never happen... - if (m_curr_frame == 0) - return retval; + // This should never happen... + if (m_curr_frame == 0) + return retval; - std::size_t i = m_curr_frame; + std::size_t i = m_curr_frame; - while (i != 0) - { - const std::shared_ptr elt = m_cs[i--]; + while (i != 0) + { + const std::shared_ptr elt = m_cs[i--]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - { - retval = dynamic_cast (f); - break; - } - } + if (f && f->is_user_code ()) + { + retval = dynamic_cast (f); + break; + } + } - return retval; - } + return retval; +} - int call_stack::debug_user_code_line (void) const - { - int retval = -1; +int call_stack::debug_user_code_line (void) const +{ + int retval = -1; - // This should never happen... - if (m_curr_frame == 0) - return retval; + // This should never happen... + if (m_curr_frame == 0) + return retval; - std::size_t i = m_curr_frame; + std::size_t i = m_curr_frame; - while (i != 0) - { - const std::shared_ptr elt = m_cs[i--]; + while (i != 0) + { + const std::shared_ptr elt = m_cs[i--]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - { - if (elt->line ()) - { - retval = elt->line (); - break; - } - } - } + if (f && f->is_user_code ()) + { + if (elt->line ()) + { + retval = elt->line (); + break; + } + } + } - return retval; - } + return retval; +} - int call_stack::debug_user_code_column (void) const - { - int retval = -1; +int call_stack::debug_user_code_column (void) const +{ + int retval = -1; - // This should never happen... - if (m_curr_frame == 0) - return retval; + // This should never happen... + if (m_curr_frame == 0) + return retval; - // Start looking with the caller of the calling debug function. - std::size_t i = m_curr_frame; + // Start looking with the caller of the calling debug function. + std::size_t i = m_curr_frame; - while (i != 0) - { - const std::shared_ptr elt = m_cs[i--]; + while (i != 0) + { + const std::shared_ptr elt = m_cs[i--]; - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && f->is_user_code ()) - { - if (elt->column ()) - { - retval = elt->column (); - break; - } - } - } + if (f && f->is_user_code ()) + { + if (elt->column ()) + { + retval = elt->column (); + break; + } + } + } - return retval; - } + return retval; +} - std::string call_stack::get_dispatch_class (void) const - { - return m_cs[m_curr_frame]->get_dispatch_class (); - } +std::string call_stack::get_dispatch_class (void) const +{ + return m_cs[m_curr_frame]->get_dispatch_class (); +} - void call_stack::set_dispatch_class (const std::string& class_name) - { - m_cs[m_curr_frame]->set_dispatch_class (class_name); - } +void call_stack::set_dispatch_class (const std::string& class_name) +{ + m_cs[m_curr_frame]->set_dispatch_class (class_name); +} - bool call_stack::is_class_method_executing (std::string& dispatch_class) const - { - dispatch_class = ""; +bool call_stack::is_class_method_executing (std::string& dispatch_class) const +{ + dispatch_class = ""; - octave_function *f = current_function (); + octave_function *f = current_function (); - bool retval = (f && f->is_class_method ()); + bool retval = (f && f->is_class_method ()); - if (retval) - dispatch_class = f->dispatch_class (); + if (retval) + dispatch_class = f->dispatch_class (); - return retval; - } + return retval; +} - bool call_stack::is_class_constructor_executing (std::string& dispatch_class) const - { - dispatch_class = ""; +bool call_stack::is_class_constructor_executing (std::string& dispatch_class) const +{ + dispatch_class = ""; - octave_function *f = current_function (); + octave_function *f = current_function (); - bool retval = (f && f->is_class_constructor ()); + bool retval = (f && f->is_class_constructor ()); - if (retval) - dispatch_class = f->dispatch_class (); + if (retval) + dispatch_class = f->dispatch_class (); - return retval; - } + return retval; +} - bool call_stack::all_scripts (void) const - { - bool retval = true; +bool call_stack::all_scripts (void) const +{ + bool retval = true; - auto p = m_cs.cend (); + auto p = m_cs.cend (); - while (p != m_cs.cbegin ()) - { - const std::shared_ptr elt = *(--p); + while (p != m_cs.cbegin ()) + { + const std::shared_ptr elt = *(--p); - octave_function *f = elt->function (); + octave_function *f = elt->function (); - if (f && ! f->is_user_script ()) - { - retval = false; - break; - } - } + if (f && ! f->is_user_script ()) + { + retval = false; + break; + } + } - return retval; - } + return retval; +} - void call_stack::get_new_frame_index_and_links - (std::size_t& new_frame_idx, std::shared_ptr& parent_link, - std::shared_ptr& static_link) const - { - // FIXME: is there a better way? +void call_stack::get_new_frame_index_and_links +(std::size_t& new_frame_idx, std::shared_ptr& parent_link, + std::shared_ptr& static_link) const +{ + // FIXME: is there a better way? - std::size_t prev_frame_idx = m_curr_frame; + std::size_t prev_frame_idx = m_curr_frame; - new_frame_idx = m_cs.size (); + new_frame_idx = m_cs.size (); - // m_max_stack_depth should never be less than zero. - if (new_frame_idx > static_cast (m_max_stack_depth)) - error ("max_stack_depth exceeded"); + // m_max_stack_depth should never be less than zero. + if (new_frame_idx > static_cast (m_max_stack_depth)) + error ("max_stack_depth exceeded"); - // There can't be any links to previous frames if this is the first - // frame on the stack. + // There can't be any links to previous frames if this is the first + // frame on the stack. - if (new_frame_idx == 0) - return; + if (new_frame_idx == 0) + return; - parent_link = m_cs[prev_frame_idx]; + parent_link = m_cs[prev_frame_idx]; - octave_function *t_fcn = parent_link->function (); + octave_function *t_fcn = parent_link->function (); - static_link = (t_fcn - ? (t_fcn->is_user_code () - ? parent_link : parent_link->static_link ()) - : parent_link); - } + static_link = (t_fcn + ? (t_fcn->is_user_code () + ? parent_link : parent_link->static_link ()) + : parent_link); +} - void call_stack::push (const symbol_scope& scope) - { - std::size_t new_frame_idx; - std::shared_ptr parent_link; - std::shared_ptr static_link; +void call_stack::push (const symbol_scope& scope) +{ + std::size_t new_frame_idx; + std::shared_ptr parent_link; + std::shared_ptr static_link; - get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); + get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); - std::shared_ptr - new_frame (stack_frame::create (m_evaluator, scope, new_frame_idx, - parent_link, static_link)); + std::shared_ptr + new_frame (stack_frame::create (m_evaluator, scope, new_frame_idx, + parent_link, static_link)); - m_cs.push_back (new_frame); + m_cs.push_back (new_frame); - m_curr_frame = new_frame_idx; - } + m_curr_frame = new_frame_idx; +} - void call_stack::push (octave_user_function *fcn, - const std::shared_ptr& closure_frames) - { - std::size_t new_frame_idx; - std::shared_ptr parent_link; - std::shared_ptr static_link; +void call_stack::push (octave_user_function *fcn, + const std::shared_ptr& closure_frames) +{ + std::size_t new_frame_idx; + std::shared_ptr parent_link; + std::shared_ptr static_link; - get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); + get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); - std::shared_ptr - new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx, - parent_link, static_link, - closure_frames)); + std::shared_ptr + new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx, + parent_link, static_link, + closure_frames)); - m_cs.push_back (new_frame); + m_cs.push_back (new_frame); - m_curr_frame = new_frame_idx; - } + m_curr_frame = new_frame_idx; +} - void call_stack::push (octave_user_function *fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& closure_frames) - { - std::size_t new_frame_idx; - std::shared_ptr parent_link; - std::shared_ptr static_link; +void call_stack::push (octave_user_function *fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& closure_frames) +{ + std::size_t new_frame_idx; + std::shared_ptr parent_link; + std::shared_ptr static_link; - get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); + get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); - std::shared_ptr - new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx, - parent_link, static_link, local_vars, - closure_frames)); + std::shared_ptr + new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx, + parent_link, static_link, local_vars, + closure_frames)); - m_cs.push_back (new_frame); + m_cs.push_back (new_frame); - m_curr_frame = new_frame_idx; - } + m_curr_frame = new_frame_idx; +} - void call_stack::push (octave_user_script *script) - { - std::size_t new_frame_idx; - std::shared_ptr parent_link; - std::shared_ptr static_link; +void call_stack::push (octave_user_script *script) +{ + std::size_t new_frame_idx; + std::shared_ptr parent_link; + std::shared_ptr static_link; - get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); + get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); - std::shared_ptr - new_frame (stack_frame::create (m_evaluator, script, new_frame_idx, - parent_link, static_link)); + std::shared_ptr + new_frame (stack_frame::create (m_evaluator, script, new_frame_idx, + parent_link, static_link)); - m_cs.push_back (new_frame); + m_cs.push_back (new_frame); - m_curr_frame = new_frame_idx; - } + m_curr_frame = new_frame_idx; +} - void call_stack::push (octave_function *fcn) - { - std::size_t new_frame_idx; - std::shared_ptr parent_link; - std::shared_ptr static_link; +void call_stack::push (octave_function *fcn) +{ + std::size_t new_frame_idx; + std::shared_ptr parent_link; + std::shared_ptr static_link; - get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); + get_new_frame_index_and_links (new_frame_idx, parent_link, static_link); - std::shared_ptr - new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx, - parent_link, static_link)); + std::shared_ptr + new_frame (stack_frame::create (m_evaluator, fcn, new_frame_idx, + parent_link, static_link)); - m_cs.push_back (new_frame); + m_cs.push_back (new_frame); - m_curr_frame = new_frame_idx; - } + m_curr_frame = new_frame_idx; +} - bool call_stack::goto_frame (std::size_t n, bool verbose) - { - bool retval = false; +bool call_stack::goto_frame (std::size_t n, bool verbose) +{ + bool retval = false; - if (n < m_cs.size ()) - { - retval = true; + if (n < m_cs.size ()) + { + retval = true; - m_curr_frame = n; + m_curr_frame = n; - if (verbose) - { - const std::shared_ptr elt = m_cs[n]; + if (verbose) + { + const std::shared_ptr elt = m_cs[n]; - elt->display_stopped_in_message (octave_stdout); - } - } + elt->display_stopped_in_message (octave_stdout); + } + } - return retval; - } + return retval; +} - std::size_t call_stack::find_current_user_frame (void) const - { - std::size_t user_frame = m_curr_frame; +std::size_t call_stack::find_current_user_frame (void) const +{ + std::size_t user_frame = m_curr_frame; - std::shared_ptr frm = m_cs[user_frame]; + std::shared_ptr frm = m_cs[user_frame]; - if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame () - || frm->is_scope_frame ())) - { - frm = frm->static_link (); + if (! (frm->is_user_fcn_frame () || frm->is_user_script_frame () + || frm->is_scope_frame ())) + { + frm = frm->static_link (); - user_frame = frm->index (); - } + user_frame = frm->index (); + } - return user_frame; - } + return user_frame; +} - std::shared_ptr call_stack::current_user_frame (void) const - { - std::size_t frame = find_current_user_frame (); +std::shared_ptr call_stack::current_user_frame (void) const +{ + std::size_t frame = find_current_user_frame (); - return m_cs[frame]; - } + return m_cs[frame]; +} - // Go to the Nth frame (up if N is negative or down if positive) in - // the call stack that corresponds to a script, function, or scope - // beginning with the frame indexed by START. +// Go to the Nth frame (up if N is negative or down if positive) in +// the call stack that corresponds to a script, function, or scope +// beginning with the frame indexed by START. - std::size_t call_stack::dbupdown (std::size_t start, int n, bool verbose) - { - if (start >= m_cs.size ()) - error ("invalid stack frame"); +std::size_t call_stack::dbupdown (std::size_t start, int n, bool verbose) +{ + if (start >= m_cs.size ()) + error ("invalid stack frame"); - // Can't go up from here. + // Can't go up from here. - if (start == 0 && n < 0) - { - if (verbose) - m_cs[start]->display_stopped_in_message (octave_stdout); + if (start == 0 && n < 0) + { + if (verbose) + m_cs[start]->display_stopped_in_message (octave_stdout); - return start; - } + return start; + } - std::shared_ptr frm = m_cs[start]; + std::shared_ptr frm = m_cs[start]; - if (! (frm && (frm->is_user_fcn_frame () - || frm->is_user_script_frame () - || frm->is_scope_frame ()))) - error ("call_stack::dbupdown: invalid initial frame in call stack!"); + if (! (frm && (frm->is_user_fcn_frame () + || frm->is_user_script_frame () + || frm->is_scope_frame ()))) + error ("call_stack::dbupdown: invalid initial frame in call stack!"); - // Use index into the call stack to begin the search. At this point - // we iterate up or down using indexing instead of static links - // because ... FIXME: it's a bit complicated, but deserves - // explanation. May be easiest with some pictures of the call stack - // for an example or two. + // Use index into the call stack to begin the search. At this point + // we iterate up or down using indexing instead of static links + // because ... FIXME: it's a bit complicated, but deserves + // explanation. May be easiest with some pictures of the call stack + // for an example or two. - std::size_t xframe = frm->index (); + std::size_t xframe = frm->index (); - if (n == 0) - { - if (verbose) - frm->display_stopped_in_message (octave_stdout); + if (n == 0) + { + if (verbose) + frm->display_stopped_in_message (octave_stdout); - return xframe; - } + return xframe; + } - int incr = 0; + int incr = 0; - if (n < 0) - { - incr = -1; - n = -n; - } - else if (n > 0) - incr = 1; + if (n < 0) + { + incr = -1; + n = -n; + } + else if (n > 0) + incr = 1; - std::size_t last_good_frame = 0; + std::size_t last_good_frame = 0; - while (true) - { - frm = m_cs[xframe]; + while (true) + { + frm = m_cs[xframe]; - if (frm->is_user_fcn_frame () || frm->is_user_script_frame () - || frm->is_scope_frame ()) - { - last_good_frame = xframe; + if (frm->is_user_fcn_frame () || frm->is_user_script_frame () + || frm->is_scope_frame ()) + { + last_good_frame = xframe; - if (n == 0) - break; + if (n == 0) + break; - n--; - } + n--; + } - xframe += incr; + xframe += incr; - if (xframe == 0) - { - last_good_frame = 0; - break; - } + if (xframe == 0) + { + last_good_frame = 0; + break; + } - if (xframe == m_cs.size ()) - break; - } + if (xframe == m_cs.size ()) + break; + } - if (verbose) - m_cs[last_good_frame]->display_stopped_in_message (octave_stdout); + if (verbose) + m_cs[last_good_frame]->display_stopped_in_message (octave_stdout); - return last_good_frame; - } + return last_good_frame; +} - // Like dbupdown above but find the starting frame automatically from - // the current frame. If the current frame is already a user - // function, script, or scope frame, use that. Otherwise, follow - // the static link for the current frame. If that is not a user - // function, script or scope frame then there is an error in the - // implementation. +// Like dbupdown above but find the starting frame automatically from +// the current frame. If the current frame is already a user +// function, script, or scope frame, use that. Otherwise, follow +// the static link for the current frame. If that is not a user +// function, script or scope frame then there is an error in the +// implementation. - std::size_t call_stack::dbupdown (int n, bool verbose) - { - std::size_t start = find_current_user_frame (); +std::size_t call_stack::dbupdown (int n, bool verbose) +{ + std::size_t start = find_current_user_frame (); - return dbupdown (start, n, verbose); - } + return dbupdown (start, n, verbose); +} - // May be used to temporarily change the value ov m_curr_frame inside - // a function like evalin. If used in a function like dbup, the new - // value of m_curr_frame would be wiped out when dbup returns and the - // stack frame for dbup is popped. +// May be used to temporarily change the value ov m_curr_frame inside +// a function like evalin. If used in a function like dbup, the new +// value of m_curr_frame would be wiped out when dbup returns and the +// stack frame for dbup is popped. - void call_stack::goto_caller_frame (void) - { - std::size_t start = find_current_user_frame (); +void call_stack::goto_caller_frame (void) +{ + std::size_t start = find_current_user_frame (); - std::shared_ptr caller_frame = m_cs[start]->static_link (); + std::shared_ptr caller_frame = m_cs[start]->static_link (); - // Allow evalin ('caller', ...) to work when called from the - // top-level prompt. + // Allow evalin ('caller', ...) to work when called from the + // top-level prompt. - m_curr_frame = caller_frame ? caller_frame->index () : 0; - } + m_curr_frame = caller_frame ? caller_frame->index () : 0; +} - void call_stack::goto_base_frame (void) - { - if (m_curr_frame > 0) - m_curr_frame = 0; - } +void call_stack::goto_base_frame (void) +{ + if (m_curr_frame > 0) + m_curr_frame = 0; +} - std::list> - call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const - { - std::list> frames; +std::list> + call_stack::backtrace_frames (octave_idx_type& curr_user_frame) const +{ + std::list> frames; - // curr_frame is the index to the current frame in the overall call - // stack, which includes any compiled function frames and scope - // frames. The curr_user_frame value we set is the index into the - // subset of frames returned in the octave_map object. + // curr_frame is the index to the current frame in the overall call + // stack, which includes any compiled function frames and scope + // frames. The curr_user_frame value we set is the index into the + // subset of frames returned in the octave_map object. - std::size_t curr_frame = find_current_user_frame (); + std::size_t curr_frame = find_current_user_frame (); - // Don't include top-level stack frame in the list. + // Don't include top-level stack frame in the list. - for (std::size_t n = m_cs.size () - 1; n > 0; n--) - { - std::shared_ptr frm = m_cs[n]; + for (std::size_t n = m_cs.size () - 1; n > 0; n--) + { + std::shared_ptr frm = m_cs[n]; - if (frm->is_user_script_frame () || frm->is_user_fcn_frame () - || frm->is_scope_frame ()) - { - if (frm->index () == curr_frame) - curr_user_frame = frames.size (); + if (frm->is_user_script_frame () || frm->is_user_fcn_frame () + || frm->is_scope_frame ()) + { + if (frm->index () == curr_frame) + curr_user_frame = frames.size (); - frames.push_back (frm); - } + frames.push_back (frm); + } - if (n == 0) - break; - } + if (n == 0) + break; + } - return frames; - } + return frames; +} - std::list> - call_stack::backtrace_frames (void) const - { - octave_idx_type curr_user_frame = -1; +std::list> + call_stack::backtrace_frames (void) const +{ + octave_idx_type curr_user_frame = -1; - return backtrace_frames (curr_user_frame); - } + return backtrace_frames (curr_user_frame); +} - std::list - call_stack::backtrace_info (octave_idx_type& curr_user_frame, - bool print_subfn) const - { - std::list> frames - = backtrace_frames (curr_user_frame); +std::list +call_stack::backtrace_info (octave_idx_type& curr_user_frame, + bool print_subfn) const +{ + std::list> frames + = backtrace_frames (curr_user_frame); - std::list retval; + std::list retval; - for (const auto& frm : frames) - { - if (frm->is_user_script_frame () || frm->is_user_fcn_frame () - || frm->is_scope_frame ()) - { - retval.push_back (frame_info (frm->fcn_file_name (), - frm->fcn_name (print_subfn), - frm->line (), frm->column ())); - } - } + for (const auto& frm : frames) + { + if (frm->is_user_script_frame () || frm->is_user_fcn_frame () + || frm->is_scope_frame ()) + { + retval.push_back (frame_info (frm->fcn_file_name (), + frm->fcn_name (print_subfn), + frm->line (), frm->column ())); + } + } - return retval; - } + return retval; +} - std::list call_stack::backtrace_info (void) const - { - octave_idx_type curr_user_frame = -1; +std::list call_stack::backtrace_info (void) const +{ + octave_idx_type curr_user_frame = -1; - return backtrace_info (curr_user_frame, true); - } + return backtrace_info (curr_user_frame, true); +} - octave_map call_stack::backtrace (octave_idx_type& curr_user_frame, - bool print_subfn) const - { - std::list> frames - = backtrace_frames (curr_user_frame); +octave_map call_stack::backtrace (octave_idx_type& curr_user_frame, + bool print_subfn) const +{ + std::list> frames + = backtrace_frames (curr_user_frame); - std::size_t nframes = frames.size (); + std::size_t nframes = frames.size (); - octave_map retval (dim_vector (nframes, 1), bt_fields); + octave_map retval (dim_vector (nframes, 1), bt_fields); - Cell& file = retval.contents (0); - Cell& name = retval.contents (1); - Cell& line = retval.contents (2); - Cell& column = retval.contents (3); + Cell& file = retval.contents (0); + Cell& name = retval.contents (1); + Cell& line = retval.contents (2); + Cell& column = retval.contents (3); - octave_idx_type k = 0; + octave_idx_type k = 0; - for (const auto& frm : frames) - { - if (frm->is_user_script_frame () || frm->is_user_fcn_frame () - || frm->is_scope_frame ()) - { - file(k) = frm->fcn_file_name (); - name(k) = frm->fcn_name (print_subfn); - line(k) = frm->line (); - column(k) = frm->column (); + for (const auto& frm : frames) + { + if (frm->is_user_script_frame () || frm->is_user_fcn_frame () + || frm->is_scope_frame ()) + { + file(k) = frm->fcn_file_name (); + name(k) = frm->fcn_name (print_subfn); + line(k) = frm->line (); + column(k) = frm->column (); - k++; - } - } + k++; + } + } - return retval; - } + return retval; +} - octave_map call_stack::backtrace (void) const - { - octave_idx_type curr_user_frame = -1; +octave_map call_stack::backtrace (void) const +{ + octave_idx_type curr_user_frame = -1; - return backtrace (curr_user_frame, true); - } + return backtrace (curr_user_frame, true); +} - octave_map call_stack::empty_backtrace (void) const - { - return octave_map (dim_vector (0, 1), bt_fields); - } +octave_map call_stack::empty_backtrace (void) const +{ + return octave_map (dim_vector (0, 1), bt_fields); +} - void call_stack::pop (void) - { - // Never pop top scope. - // FIXME: is it possible for this case to happen? +void call_stack::pop (void) +{ + // Never pop top scope. + // FIXME: is it possible for this case to happen? - if (m_cs.size () > 1) - { - std::shared_ptr elt = m_cs.back (); + if (m_cs.size () > 1) + { + std::shared_ptr elt = m_cs.back (); - std::shared_ptr caller = elt->parent_link (); + std::shared_ptr caller = elt->parent_link (); - m_curr_frame = caller->index (); + m_curr_frame = caller->index (); - if (elt->is_closure_context ()) - elt->break_closure_cycles (elt); + if (elt->is_closure_context ()) + elt->break_closure_cycles (elt); - m_cs.pop_back (); - } - } + m_cs.pop_back (); + } +} - void call_stack::clear (void) - { - while (! m_cs.empty ()) - pop (); - } +void call_stack::clear (void) +{ + while (! m_cs.empty ()) + pop (); +} - symbol_info_list call_stack::all_variables (void) - { - return m_cs[m_curr_frame]->all_variables (); - } +symbol_info_list call_stack::all_variables (void) +{ + return m_cs[m_curr_frame]->all_variables (); +} - std::list call_stack::global_variable_names (void) const - { - std::list retval; +std::list call_stack::global_variable_names (void) const +{ + std::list retval; - for (const auto& nm_ov : m_global_values) - { - if (nm_ov.second.is_defined ()) - retval.push_back (nm_ov.first); - } + for (const auto& nm_ov : m_global_values) + { + if (nm_ov.second.is_defined ()) + retval.push_back (nm_ov.first); + } - retval.sort (); + retval.sort (); - return retval; - } + return retval; +} - std::list call_stack::top_level_variable_names (void) const - { - return m_cs[0]->variable_names (); - } +std::list call_stack::top_level_variable_names (void) const +{ + return m_cs[0]->variable_names (); +} - std::list call_stack::variable_names (void) const - { - return m_cs[m_curr_frame]->variable_names (); - } +std::list call_stack::variable_names (void) const +{ + return m_cs[m_curr_frame]->variable_names (); +} - void call_stack::clear_global_variable (const std::string& name) - { - auto p = m_global_values.find (name); +void call_stack::clear_global_variable (const std::string& name) +{ + auto p = m_global_values.find (name); - if (p != m_global_values.end ()) - p->second = octave_value (); - } + if (p != m_global_values.end ()) + p->second = octave_value (); +} - void call_stack::clear_global_variable_pattern (const std::string& pattern) - { - glob_match pat (pattern); +void call_stack::clear_global_variable_pattern (const std::string& pattern) +{ + glob_match pat (pattern); - for (auto& nm_ov : m_global_values) - { - if (pat.match (nm_ov.first)) - nm_ov.second = octave_value (); - } - } + for (auto& nm_ov : m_global_values) + { + if (pat.match (nm_ov.first)) + nm_ov.second = octave_value (); + } +} - void call_stack::clear_global_variable_regexp (const std::string& pattern) - { - regexp pat (pattern); +void call_stack::clear_global_variable_regexp (const std::string& pattern) +{ + regexp pat (pattern); - for (auto& nm_ov : m_global_values) - { - if (pat.is_match (nm_ov.first)) - nm_ov.second = octave_value (); - } - } + for (auto& nm_ov : m_global_values) + { + if (pat.is_match (nm_ov.first)) + nm_ov.second = octave_value (); + } +} - void call_stack::clear_global_variables (void) - { - for (auto& nm_ov : m_global_values) - nm_ov.second = octave_value (); - } +void call_stack::clear_global_variables (void) +{ + for (auto& nm_ov : m_global_values) + nm_ov.second = octave_value (); +} - symbol_info_list - call_stack::glob_symbol_info (const std::string& pattern) const - { - return m_cs[m_curr_frame]->glob_symbol_info (pattern); - } +symbol_info_list +call_stack::glob_symbol_info (const std::string& pattern) const +{ + return m_cs[m_curr_frame]->glob_symbol_info (pattern); +} - symbol_info_list - call_stack::regexp_symbol_info (const std::string& pattern) const - { - return m_cs[m_curr_frame]->regexp_symbol_info (pattern); - } +symbol_info_list +call_stack::regexp_symbol_info (const std::string& pattern) const +{ + return m_cs[m_curr_frame]->regexp_symbol_info (pattern); +} - symbol_info_list call_stack::get_symbol_info (void) - { - return m_cs[m_curr_frame]->get_symbol_info (); - } +symbol_info_list call_stack::get_symbol_info (void) +{ + return m_cs[m_curr_frame]->get_symbol_info (); +} - symbol_info_list call_stack::top_scope_symbol_info (void) const - { - return m_cs[0]->get_symbol_info (); - } +symbol_info_list call_stack::top_scope_symbol_info (void) const +{ + return m_cs[0]->get_symbol_info (); +} - octave_value call_stack::max_stack_depth (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_max_stack_depth, args, nargout, - "max_stack_depth", 0); - } +octave_value call_stack::max_stack_depth (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_max_stack_depth, args, nargout, + "max_stack_depth", 0); +} - void call_stack::make_persistent (const symbol_record& sym) - { - m_cs[m_curr_frame]->make_persistent (sym); - } +void call_stack::make_persistent (const symbol_record& sym) +{ + m_cs[m_curr_frame]->make_persistent (sym); +} - void call_stack::make_global (const symbol_record& sym) - { - m_cs[m_curr_frame]->make_global (sym); - } +void call_stack::make_global (const symbol_record& sym) +{ + m_cs[m_curr_frame]->make_global (sym); +} - octave_value call_stack::global_varval (const std::string& name) const - { - auto p = m_global_values.find (name); +octave_value call_stack::global_varval (const std::string& name) const +{ + auto p = m_global_values.find (name); - return p == m_global_values.end () ? octave_value () : p->second; - } + return p == m_global_values.end () ? octave_value () : p->second; +} - octave_value& call_stack::global_varref (const std::string& name) - { - return m_global_values[name]; - } +octave_value& call_stack::global_varref (const std::string& name) +{ + return m_global_values[name]; +} - octave_value call_stack::get_top_level_value (const std::string& name) const - { - return m_cs[0]->varval (name); - } +octave_value call_stack::get_top_level_value (const std::string& name) const +{ + return m_cs[0]->varval (name); +} - void call_stack::set_top_level_value (const std::string& name, - const octave_value& value) - { - m_cs[0]->assign (name, value); - } +void call_stack::set_top_level_value (const std::string& name, + const octave_value& value) +{ + m_cs[0]->assign (name, value); +} - octave_value call_stack::do_who (int argc, const string_vector& argv, - bool return_list, bool verbose) - { - octave_value retval; +octave_value call_stack::do_who (int argc, const string_vector& argv, + bool return_list, bool verbose) +{ + octave_value retval; - std::string my_name = argv[0]; + std::string my_name = argv[0]; - std::string file_name; + std::string file_name; - bool from_file = false; - bool global_only = false; - bool have_regexp = false; + bool from_file = false; + bool global_only = false; + bool have_regexp = false; - int i = 1; - while (i < argc) - { - if (argv[i] == "-file") - { - if (from_file) - error ("%s: -file option may only be specified once", - my_name.c_str ()); + int i = 1; + while (i < argc) + { + if (argv[i] == "-file") + { + if (from_file) + error ("%s: -file option may only be specified once", + my_name.c_str ()); - from_file = true; + from_file = true; - if (i == argc - 1) - error ("%s: -file argument must be followed by a filename", - my_name.c_str ()); + if (i == argc - 1) + error ("%s: -file argument must be followed by a filename", + my_name.c_str ()); - file_name = argv[++i]; - } - else if (argv[i] == "-regexp") - { - have_regexp = true; - } - else if (argv[i] == "global") - global_only = true; - else if (argv[i][0] == '-') - warning ("%s: unrecognized option '%s'", my_name.c_str (), - argv[i].c_str ()); - else - break; + file_name = argv[++i]; + } + else if (argv[i] == "-regexp") + { + have_regexp = true; + } + else if (argv[i] == "global") + global_only = true; + else if (argv[i][0] == '-') + warning ("%s: unrecognized option '%s'", my_name.c_str (), + argv[i].c_str ()); + else + break; - i++; - } + i++; + } - int npatterns = argc - i; - string_vector patterns; - if (npatterns > 0) - { - patterns.resize (npatterns); - for (int j = 0; j < npatterns; j++) - patterns[j] = argv[i+j]; - } - else - { - patterns.resize (1); - patterns[0] = "*"; - } + int npatterns = argc - i; + string_vector patterns; + if (npatterns > 0) + { + patterns.resize (npatterns); + for (int j = 0; j < npatterns; j++) + patterns[j] = argv[i+j]; + } + else + { + patterns.resize (1); + patterns[0] = "*"; + } - if (from_file) - { - // FIXME: This is an inefficient manner to implement this as the - // variables are loaded in to a temporary context and then treated. - // It would be better to refactor symbol_info_list to not store the - // symbol records and then use it in load-save.cc (do_load) to - // implement this option there so that the variables are never - // stored at all. + if (from_file) + { + // FIXME: This is an inefficient manner to implement this as the + // variables are loaded in to a temporary context and then treated. + // It would be better to refactor symbol_info_list to not store the + // symbol records and then use it in load-save.cc (do_load) to + // implement this option there so that the variables are never + // stored at all. - // Set up temporary scope. + // Set up temporary scope. - symbol_scope tmp_scope ("$dummy_scope$"); + symbol_scope tmp_scope ("$dummy_scope$"); - push (tmp_scope); + push (tmp_scope); - unwind_action restore_scope ([=] (void) { pop (); }); + unwind_action restore_scope ([=] (void) { pop (); }); - feval ("load", octave_value (file_name), 0); + feval ("load", octave_value (file_name), 0); - std::string newmsg = "Variables in the file " + file_name + ":\n\n"; + std::string newmsg = "Variables in the file " + file_name + ":\n\n"; - if (global_only) - return do_global_who_two (patterns, have_regexp, return_list, - verbose, newmsg); - else - return do_who_two (patterns, have_regexp, return_list, verbose, - newmsg); - } - else - { - if (global_only) - return do_global_who_two (patterns, have_regexp, return_list, - verbose); - else - return do_who_two (patterns, have_regexp, return_list, verbose); - } - } + if (global_only) + return do_global_who_two (patterns, have_regexp, return_list, + verbose, newmsg); + else + return do_who_two (patterns, have_regexp, return_list, verbose, + newmsg); + } + else + { + if (global_only) + return do_global_who_two (patterns, have_regexp, return_list, + verbose); + else + return do_who_two (patterns, have_regexp, return_list, verbose); + } +} - octave_value call_stack::do_who_two (const string_vector& patterns, - bool have_regexp, bool return_list, - bool verbose, const std::string& msg) - { - return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list, - verbose, m_evaluator.whos_line_format (), - msg); - } +octave_value call_stack::do_who_two (const string_vector& patterns, + bool have_regexp, bool return_list, + bool verbose, const std::string& msg) +{ + return m_cs[m_curr_frame]->who (patterns, have_regexp, return_list, + verbose, m_evaluator.whos_line_format (), + msg); +} - octave_value call_stack::do_global_who_two (const string_vector& patterns, - bool have_regexp, - bool return_list, bool verbose, - const std::string& msg) - { - symbol_info_list symbol_stats; - std::list symbol_names; +octave_value call_stack::do_global_who_two (const string_vector& patterns, + bool have_regexp, + bool return_list, bool verbose, + const std::string& msg) +{ + symbol_info_list symbol_stats; + std::list symbol_names; - octave_idx_type npatterns = patterns.numel (); + octave_idx_type npatterns = patterns.numel (); - for (octave_idx_type j = 0; j < npatterns; j++) - { - std::string pattern = patterns[j]; + for (octave_idx_type j = 0; j < npatterns; j++) + { + std::string pattern = patterns[j]; - std::list tmp; + std::list tmp; - if (have_regexp) - { - regexp pat (pattern); + if (have_regexp) + { + regexp pat (pattern); - for (auto& nm_ov : m_global_values) - { - if (pat.is_match (nm_ov.first)) - tmp.push_back (nm_ov.first); - } - } - else - { - glob_match pat (pattern); + for (auto& nm_ov : m_global_values) + { + if (pat.is_match (nm_ov.first)) + tmp.push_back (nm_ov.first); + } + } + else + { + glob_match pat (pattern); - for (auto& nm_ov : m_global_values) - { - if (pat.match (nm_ov.first)) - tmp.push_back (nm_ov.first); - } - } + for (auto& nm_ov : m_global_values) + { + if (pat.match (nm_ov.first)) + tmp.push_back (nm_ov.first); + } + } - for (const auto& nm : tmp) - { - octave_value value = m_global_values[nm]; + for (const auto& nm : tmp) + { + octave_value value = m_global_values[nm]; - if (value.is_defined ()) - { - if (verbose) - { - bool is_formal = false; - bool is_global = true; - bool is_persistent = false; + if (value.is_defined ()) + { + if (verbose) + { + bool is_formal = false; + bool is_global = true; + bool is_persistent = false; - symbol_info syminf (nm, value, is_formal, is_global, - is_persistent); + symbol_info syminf (nm, value, is_formal, is_global, + is_persistent); - symbol_stats.append (syminf); - } - else - symbol_names.push_back (nm); - } - } - } + symbol_stats.append (syminf); + } + else + symbol_names.push_back (nm); + } + } + } - if (return_list) - { - if (verbose) - { - std::string caller_fcn_name; - octave_function *caller_fcn = caller_function (); - if (caller_fcn) - caller_fcn_name = caller_fcn->name (); + if (return_list) + { + if (verbose) + { + std::string caller_fcn_name; + octave_function *caller_fcn = caller_function (); + if (caller_fcn) + caller_fcn_name = caller_fcn->name (); - return symbol_stats.map_value (caller_fcn_name, 1); - } - else - return Cell (string_vector (symbol_names)); - } - else if (! (symbol_stats.empty () && symbol_names.empty ())) - { - if (msg.empty ()) - octave_stdout << "Global variables:\n\n"; - else - octave_stdout << msg; + return symbol_stats.map_value (caller_fcn_name, 1); + } + else + return Cell (string_vector (symbol_names)); + } + else if (! (symbol_stats.empty () && symbol_names.empty ())) + { + if (msg.empty ()) + octave_stdout << "Global variables:\n\n"; + else + octave_stdout << msg; - if (verbose) - symbol_stats.display (octave_stdout, - m_evaluator.whos_line_format ()); - else - { - string_vector names (symbol_names); + if (verbose) + symbol_stats.display (octave_stdout, + m_evaluator.whos_line_format ()); + else + { + string_vector names (symbol_names); - names.list_in_columns (octave_stdout); - } + names.list_in_columns (octave_stdout); + } - octave_stdout << "\n"; - } + octave_stdout << "\n"; + } - return octave_value (); - } + return octave_value (); +} - void call_stack::display (void) const - { - std::ostream& os = octave_stdout; +void call_stack::display (void) const +{ + std::ostream& os = octave_stdout; - std::size_t nframes = size (); + std::size_t nframes = size (); - for (std::size_t i = 0; i < nframes; i++) - { - m_cs[i]->display (false); - if (i < nframes - 1) - os << std::endl; - } - } + for (std::size_t i = 0; i < nframes; i++) + { + m_cs[i]->display (false); + if (i < nframes - 1) + os << std::endl; + } +} - void call_stack::set_auto_fcn_var (stack_frame::auto_var_type avt, - const octave_value& val) - { - m_cs[m_curr_frame]->set_auto_fcn_var (avt, val); - } +void call_stack::set_auto_fcn_var (stack_frame::auto_var_type avt, + const octave_value& val) +{ + m_cs[m_curr_frame]->set_auto_fcn_var (avt, val); +} - octave_value call_stack::get_auto_fcn_var (stack_frame::auto_var_type avt) const - { - return m_cs[m_curr_frame]->get_auto_fcn_var (avt); - } +octave_value call_stack::get_auto_fcn_var (stack_frame::auto_var_type avt) const +{ + return m_cs[m_curr_frame]->get_auto_fcn_var (avt); +} DEFMETHOD (max_stack_depth, interp, args, nargout, doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/call-stack.h --- a/libinterp/corefcn/call-stack.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/call-stack.h Thu Dec 01 20:05:44 2022 -0800 @@ -46,285 +46,285 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; - class symbol_info_list; - class unwind_protect; +class tree_evaluator; +class symbol_info_list; +class unwind_protect; - class - OCTINTERP_API - call_stack - { - public: +class +OCTINTERP_API +call_stack +{ +public: - typedef std::deque> stack_frames; + typedef std::deque> stack_frames; - typedef stack_frames::iterator iterator; - typedef stack_frames::const_iterator const_iterator; + typedef stack_frames::iterator iterator; + typedef stack_frames::const_iterator const_iterator; - typedef stack_frames::reverse_iterator reverse_iterator; - typedef stack_frames::const_reverse_iterator const_reverse_iterator; + typedef stack_frames::reverse_iterator reverse_iterator; + typedef stack_frames::const_reverse_iterator const_reverse_iterator; - call_stack (tree_evaluator& evaluator); + call_stack (tree_evaluator& evaluator); - // Lock current function. Look for the first stack frame that is - // a function. If SKIP_FIST is true, then skip the first frame. - // That allows functions like Fmlock to find and lock the calling - // function instead of locking Fmlock itself. + // Lock current function. Look for the first stack frame that is + // a function. If SKIP_FIST is true, then skip the first frame. + // That allows functions like Fmlock to find and lock the calling + // function instead of locking Fmlock itself. - octave_function * current_function (bool skip_first = false) const; + octave_function * current_function (bool skip_first = false) const; - octave_function * caller_function (void) const - { - return current_function (true); - } + octave_function * caller_function (void) const + { + return current_function (true); + } - // Current line in current function. - int current_line (void) const; + // Current line in current function. + int current_line (void) const; - // Current column in current function. - int current_column (void) const; + // Current column in current function. + int current_column (void) const; - std::size_t current_frame (void) const { return m_curr_frame; } + std::size_t current_frame (void) const { return m_curr_frame; } - std::size_t size (void) const { return m_cs.size (); } + std::size_t size (void) const { return m_cs.size (); } - std::shared_ptr get_current_stack_frame (void) const - { - return m_cs[m_curr_frame]; - } + std::shared_ptr get_current_stack_frame (void) const + { + return m_cs[m_curr_frame]; + } - symbol_scope top_scope (void) const - { - return m_cs[0]->get_scope (); - } + symbol_scope top_scope (void) const + { + return m_cs[0]->get_scope (); + } - symbol_scope current_scope (void) const - { - // FIXME: Can m_curr_frame ever be invalid? - return (m_curr_frame < m_cs.size () - ? m_cs[m_curr_frame]->get_scope () : symbol_scope ()); - } + symbol_scope current_scope (void) const + { + // FIXME: Can m_curr_frame ever be invalid? + return (m_curr_frame < m_cs.size () + ? m_cs[m_curr_frame]->get_scope () : symbol_scope ()); + } - bool at_top_level (void) const - { - return current_scope () == top_scope (); - } + bool at_top_level (void) const + { + return current_scope () == top_scope (); + } - // Function at location N on the call stack (N == 0 is current), may - // be built-in. - octave_function * element (std::size_t n) - { - octave_function *retval = nullptr; + // Function at location N on the call stack (N == 0 is current), may + // be built-in. + octave_function * element (std::size_t n) + { + octave_function *retval = nullptr; - if (m_cs.size () > n) - retval = m_cs[n]->function (); + if (m_cs.size () > n) + retval = m_cs[n]->function (); - return retval; - } + return retval; + } - // User code caller. - octave_user_code * current_user_code (void) const; + // User code caller. + octave_user_code * current_user_code (void) const; - unwind_protect * curr_fcn_unwind_protect_frame (void); + unwind_protect * curr_fcn_unwind_protect_frame (void); - // Line in user code caller. - int current_user_code_line (void) const; + // Line in user code caller. + int current_user_code_line (void) const; - // Column in user code caller. - int current_user_code_column (void) const; + // Column in user code caller. + int current_user_code_column (void) const; - // Current function that we are debugging. - octave_user_code * debug_user_code (void) const; + // Current function that we are debugging. + octave_user_code * debug_user_code (void) const; - // Line number in current function that we are debugging. - int debug_user_code_line (void) const; + // Line number in current function that we are debugging. + int debug_user_code_line (void) const; - // Column number in current function that we are debugging. - int debug_user_code_column (void) const; + // Column number in current function that we are debugging. + int debug_user_code_column (void) const; - std::string get_dispatch_class (void) const; + std::string get_dispatch_class (void) const; - void set_dispatch_class (const std::string& class_name); + void set_dispatch_class (const std::string& class_name); - bool is_class_method_executing (std::string& dispatch_class) const; + bool is_class_method_executing (std::string& dispatch_class) const; - bool is_class_constructor_executing (std::string& dispatch_class) const; + bool is_class_constructor_executing (std::string& dispatch_class) const; - // Return TRUE if all elements on the call stack are scripts. - bool all_scripts (void) const; + // Return TRUE if all elements on the call stack are scripts. + bool all_scripts (void) const; - void push (const symbol_scope& scope); + void push (const symbol_scope& scope); - void push (octave_user_function *fcn, - const std::shared_ptr& closure_frames = std::shared_ptr ()); + void push (octave_user_function *fcn, + const std::shared_ptr& closure_frames = std::shared_ptr ()); - void push (octave_user_function *fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& closure_frames = std::shared_ptr ()); + void push (octave_user_function *fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& closure_frames = std::shared_ptr ()); - void push (octave_user_script *script); + void push (octave_user_script *script); - void push (octave_function *fcn); + void push (octave_function *fcn); - void set_location (int l, int c) - { - if (! m_cs.empty ()) - { - std::shared_ptr elt = m_cs.back (); + void set_location (int l, int c) + { + if (! m_cs.empty ()) + { + std::shared_ptr elt = m_cs.back (); - elt->line (l); - elt->column (c); - } - } + elt->line (l); + elt->column (c); + } + } - void set_line (int l) - { - if (! m_cs.empty ()) - { - std::shared_ptr elt = m_cs.back (); + void set_line (int l) + { + if (! m_cs.empty ()) + { + std::shared_ptr elt = m_cs.back (); - elt->line (l); - } - } + elt->line (l); + } + } - void set_column (int c) - { - if (! m_cs.empty ()) - { - std::shared_ptr elt = m_cs.back (); + void set_column (int c) + { + if (! m_cs.empty ()) + { + std::shared_ptr elt = m_cs.back (); - elt->column (c); - } - } + elt->column (c); + } + } - bool goto_frame (std::size_t n = 0, bool verbose = false); + bool goto_frame (std::size_t n = 0, bool verbose = false); - void restore_frame (std::size_t n) - { - goto_frame (n); - } + void restore_frame (std::size_t n) + { + goto_frame (n); + } - std::size_t find_current_user_frame (void) const; + std::size_t find_current_user_frame (void) const; - std::shared_ptr current_user_frame (void) const; + std::shared_ptr current_user_frame (void) const; - std::size_t dbupdown (std::size_t start, int n, bool verbose); - std::size_t dbupdown (int n = -1, bool verbose = false); + std::size_t dbupdown (std::size_t start, int n, bool verbose); + std::size_t dbupdown (int n = -1, bool verbose = false); - void goto_caller_frame (void); + void goto_caller_frame (void); - void goto_base_frame (void); + void goto_base_frame (void); - std::list> - backtrace_frames (octave_idx_type& curr_user_frame) const; + std::list> + backtrace_frames (octave_idx_type& curr_user_frame) const; - // List of raw stack frames. + // List of raw stack frames. - std::list> backtrace_frames (void) const; + std::list> backtrace_frames (void) const; - // List of stack_info objects that can be used in liboctave and - // stored in the execution_exception object. + // List of stack_info objects that can be used in liboctave and + // stored in the execution_exception object. - std::list backtrace_info (octave_idx_type& curr_user_frame, - bool print_subfn = true) const; + std::list backtrace_info (octave_idx_type& curr_user_frame, + bool print_subfn = true) const; - std::list backtrace_info (void) const; + std::list backtrace_info (void) const; - // The same as backtrace_info but in the form of a struct array - // object that may be used in the interpreter. + // The same as backtrace_info but in the form of a struct array + // object that may be used in the interpreter. - octave_map backtrace (octave_idx_type& curr_user_frame, - bool print_subfn = true) const; + octave_map backtrace (octave_idx_type& curr_user_frame, + bool print_subfn = true) const; - octave_map backtrace (void) const; + octave_map backtrace (void) const; - octave_map empty_backtrace (void) const; + octave_map empty_backtrace (void) const; - void pop (void); + void pop (void); - void clear (void); + void clear (void); - symbol_info_list all_variables (void); + symbol_info_list all_variables (void); - std::list global_variable_names (void) const; + std::list global_variable_names (void) const; - std::list top_level_variable_names (void) const; + std::list top_level_variable_names (void) const; - std::list variable_names (void) const; + std::list variable_names (void) const; - void clear_global_variable (const std::string& name); + void clear_global_variable (const std::string& name); - void clear_global_variable_pattern (const std::string& pattern); + void clear_global_variable_pattern (const std::string& pattern); - void clear_global_variable_regexp(const std::string& pattern); + void clear_global_variable_regexp(const std::string& pattern); - void clear_global_variables (void); + void clear_global_variables (void); - symbol_info_list glob_symbol_info (const std::string& pattern) const; + symbol_info_list glob_symbol_info (const std::string& pattern) const; - symbol_info_list regexp_symbol_info (const std::string& pattern) const; + symbol_info_list regexp_symbol_info (const std::string& pattern) const; - symbol_info_list get_symbol_info (void); + symbol_info_list get_symbol_info (void); - symbol_info_list top_scope_symbol_info (void) const; + symbol_info_list top_scope_symbol_info (void) const; - octave_value max_stack_depth (const octave_value_list& args, int nargout); + octave_value max_stack_depth (const octave_value_list& args, int nargout); - void make_persistent (const symbol_record& sym); + void make_persistent (const symbol_record& sym); - void make_global (const symbol_record& sym); + void make_global (const symbol_record& sym); - octave_value global_varval (const std::string& name) const; + octave_value global_varval (const std::string& name) const; - octave_value& global_varref (const std::string& name); + octave_value& global_varref (const std::string& name); - octave_value get_top_level_value (const std::string& name) const; + octave_value get_top_level_value (const std::string& name) const; - void set_top_level_value (const std::string& name, - const octave_value& value); + void set_top_level_value (const std::string& name, + const octave_value& value); - octave_value do_who (int argc, const string_vector& argv, - bool return_list, bool verbose = false); + octave_value do_who (int argc, const string_vector& argv, + bool return_list, bool verbose = false); - octave_value do_who_two (const string_vector& patterns, bool have_regexp, - bool return_list, bool verbose, - const std::string& msg = ""); + octave_value do_who_two (const string_vector& patterns, bool have_regexp, + bool return_list, bool verbose, + const std::string& msg = ""); - octave_value do_global_who_two (const string_vector& patterns, - bool have_regexp, bool return_list, - bool verbose, const std::string& msg = ""); + octave_value do_global_who_two (const string_vector& patterns, + bool have_regexp, bool return_list, + bool verbose, const std::string& msg = ""); - void display (void) const; + void display (void) const; - void set_auto_fcn_var (stack_frame::auto_var_type avt, - const octave_value& val); + void set_auto_fcn_var (stack_frame::auto_var_type avt, + const octave_value& val); - octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const; + octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const; - private: +private: - void get_new_frame_index_and_links - (std::size_t& new_frame_idx, std::shared_ptr& parent_link, - std::shared_ptr& static_link) const; + void get_new_frame_index_and_links + (std::size_t& new_frame_idx, std::shared_ptr& parent_link, + std::shared_ptr& static_link) const; - tree_evaluator& m_evaluator; + tree_evaluator& m_evaluator; - // The list of stack frames. - stack_frames m_cs; + // The list of stack frames. + stack_frames m_cs; - // The current frame. When a new frame is pushed, m_curr_frame - // moves to the end of the list of stack frames (also referred to as - // the top of the call stack) but may be temporarily moved to - // another location by evalin or debugging functions. + // The current frame. When a new frame is pushed, m_curr_frame + // moves to the end of the list of stack frames (also referred to as + // the top of the call stack) but may be temporarily moved to + // another location by evalin or debugging functions. - // FIXME: should the current frame be managed by the evaluator - // instead? - std::size_t m_curr_frame; + // FIXME: should the current frame be managed by the evaluator + // instead? + std::size_t m_curr_frame; - int m_max_stack_depth; + int m_max_stack_depth; - std::map m_global_values; - }; + std::map m_global_values; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ccolamd.cc --- a/libinterp/corefcn/ccolamd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ccolamd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -187,7 +187,7 @@ octave_stdout << "knobs(2): " << User_knobs(1) << ", rows with > max (16," << knobs[CCOLAMD_DENSE_ROW] - << "*sqrt (columns(A)))" + << "* sqrt (columns(A)))" << " entries removed\n"; else octave_stdout << "knobs(2): " << User_knobs(1) @@ -196,7 +196,7 @@ if (knobs[CCOLAMD_DENSE_COL] >= 0) octave_stdout << "knobs(3): " << User_knobs(2) << ", cols with > max (16," - << knobs[CCOLAMD_DENSE_COL] << "*sqrt (size(A)))" + << knobs[CCOLAMD_DENSE_COL] << "* sqrt (size(A)))" << " entries removed\n"; else octave_stdout << "knobs(3): " << User_knobs(2) @@ -446,7 +446,7 @@ octave_stdout << "knobs(1): " << User_knobs(0) << ", rows/cols with > max (16," << knobs[CCOLAMD_DENSE_ROW] - << "*sqrt (columns(A)))" + << "* sqrt (columns(A)))" << " entries removed\n"; else octave_stdout << "knobs(1): " << User_knobs(0) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/cellfun.cc --- a/libinterp/corefcn/cellfun.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/cellfun.cc Thu Dec 01 20:05:44 2022 -0800 @@ -2081,7 +2081,7 @@ OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, ridx, nd, 0); Array ra_idx - (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon); + (dim_vector (1, std::max (nd, a.ndims ())), idx_vector::colon); for (octave_idx_type j = 0; j < retval.numel (); j++) { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/chol.cc --- a/libinterp/corefcn/chol.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/chol.cc Thu Dec 01 20:05:44 2022 -0800 @@ -780,21 +780,21 @@ %! R = chol (single (A)); %! R1 = cholupdate (R, single (u)); %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (R1'*R1 - R'*R - single (u*u'), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - R'*R - single (u*u'), Inf) < 1e1* eps ("single")); %! %! R1 = cholupdate (R1, single (u), "-"); %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (R1 - R, Inf) < 2e1*eps ("single")); +%! assert (norm (R1 - R, Inf) < 2e1* eps ("single")); %!test %! R = chol (single (Ac)); %! R1 = cholupdate (R, single (uc)); %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (R1'*R1 - R'*R - single (uc*uc'), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - R'*R - single (uc*uc'), Inf) < 1e1* eps ("single")); %! %! R1 = cholupdate (R1, single (uc), "-"); %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (R1 - R, Inf) < 2e1*eps ("single")); +%! assert (norm (R1 - R, Inf) < 2e1* eps ("single")); */ DEFUN (cholinsert, args, nargout, @@ -962,7 +962,7 @@ %! A1 = R1'*R1; %! %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (A1(p,p) - A, Inf) < 1e1*eps ("single")); +%! assert (norm (A1(p,p) - A, Inf) < 1e1* eps ("single")); %!test %! u2 = single ([ 0.35080 + 0.04298i; @@ -978,7 +978,7 @@ %! A1 = R1'*R1; %! %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (A1(p,p) - single (Ac), Inf) < 2e1*eps ("single")); +%! assert (norm (A1(p,p) - single (Ac), Inf) < 2e1* eps ("single")); %!test %! cu = chol (triu (A), "upper"); @@ -1165,7 +1165,7 @@ %! R1 = choldelete (R, j); %! %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1* eps ("single")); %!test %! R = chol (single (Ac)); @@ -1174,7 +1174,7 @@ %! R1 = choldelete (R,j); %! %! assert (norm (triu (R1)-R1, Inf), single (0)); -%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1* eps ("single")); */ DEFUN (cholshift, args, , @@ -1310,13 +1310,13 @@ %! R1 = cholshift (R, i, j); %! %! assert (norm (triu (R1)-R1, Inf), 0); -%! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1* eps ("single")); %! %! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4]; %! R1 = cholshift (R, i, j); %! %! assert (norm (triu (R1)-R1, Inf), 0); -%! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - single (A(p,p)), Inf) < 1e1* eps ("single")); %!test %! R = chol (single (Ac)); @@ -1325,13 +1325,13 @@ %! R1 = cholshift (R, i, j); %! %! assert (norm (triu (R1)-R1, Inf), 0); -%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1* eps ("single")); %! %! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4]; %! R1 = cholshift (R, i, j); %! %! assert (norm (triu (R1)-R1, Inf), 0); -%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1*eps ("single")); +%! assert (norm (R1'*R1 - single (Ac(p,p)), Inf) < 1e1* eps ("single")); */ OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/colamd.cc --- a/libinterp/corefcn/colamd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/colamd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -313,7 +313,7 @@ if (knobs[COLAMD_DENSE_ROW] >= 0) octave_stdout << "knobs(1): " << User_knobs (0) << ", rows with > max (16," - << knobs[COLAMD_DENSE_ROW] << "*sqrt (columns(A)))" + << knobs[COLAMD_DENSE_ROW] << "* sqrt (columns(A)))" << " entries removed\n"; else octave_stdout << "knobs(1): " << User_knobs (0) @@ -322,7 +322,7 @@ if (knobs[COLAMD_DENSE_COL] >= 0) octave_stdout << "knobs(2): " << User_knobs (1) << ", cols with > max (16," - << knobs[COLAMD_DENSE_COL] << "*sqrt (size(A)))" + << knobs[COLAMD_DENSE_COL] << "* sqrt (size(A)))" << " entries removed\n"; else octave_stdout << "knobs(2): " << User_knobs (1) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/dasrt.cc --- a/libinterp/corefcn/dasrt.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/dasrt.cc Thu Dec 01 20:05:44 2022 -0800 @@ -466,9 +466,11 @@ ColumnVector state = args(argp++).xvector_value ("dasrt: initial state X_0 must be a vector"); - ColumnVector stateprime = args(argp++).xvector_value ("dasrt: initial derivatives XDOT_0 must be a vector"); + ColumnVector stateprime = args( + argp++).xvector_value ("dasrt: initial derivatives XDOT_0 must be a vector"); - ColumnVector out_times = args(argp++).xvector_value ("dasrt: output time variable T must be a vector"); + ColumnVector out_times = args( + argp++).xvector_value ("dasrt: output time variable T must be a vector"); double tzero = out_times (0); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/data.cc Thu Dec 01 20:05:44 2022 -0800 @@ -96,7 +96,7 @@ print_usage (); int dim = (nargin == 1 ? -1 - : args(1).xint_value ("all: DIM must be an integer")-1); + : args(1).xint_value ("all: DIM must be an integer")-1); if (dim < -1) error ("all: invalid dimension argument = %d", dim + 1); @@ -161,7 +161,7 @@ print_usage (); int dim = (nargin == 1 ? -1 - : args(1).xint_value ("any: DIM must be an integer")-1); + : args(1).xint_value ("any: DIM must be an integer")-1); if (dim < -1) error ("any: invalid dimension argument = %d", dim + 1); @@ -2048,8 +2048,8 @@ ## Test concatenation with all zero matrices %!test %! warning ("off", "Octave:num-to-str", "local"); -%! assert (horzcat ("", 65*ones (1,10)), "AAAAAAAAAA"); -%! assert (horzcat (65*ones (1,10), ""), "AAAAAAAAAA"); +%! assert (horzcat ("", 65* ones (1,10)), "AAAAAAAAAA"); +%! assert (horzcat (65* ones (1,10), ""), "AAAAAAAAAA"); %!assert (class (horzcat (int64 (1), int64 (1))), "int64") %!assert (class (horzcat (int64 (1), int32 (1))), "int64") @@ -3566,7 +3566,7 @@ for (octave_idx_type i = im_val.cidx (j); i < im_val.cidx (j + 1); i++) result.data (im_val.ridx (i) + off) - += Complex (0, im_val.data (i)); + += Complex (0, im_val.data (i)); } } retval = octave_value (new octave_sparse_complex_matrix (result)); @@ -3589,7 +3589,7 @@ for (octave_idx_type i = re_val.cidx (j); i < re_val.cidx (j + 1); i++) result.data (re_val.ridx (i) + off) - += re_val.data (i); + += re_val.data (i); } } retval = octave_value (new octave_sparse_complex_matrix (result)); @@ -6272,7 +6272,7 @@ %!assert (norm (x,0), single (5)) %!assert (norm (x,1), single (20)) %!assert (norm (x,2), single (10)) -%!assert (norm (x,3), single (8.24257059961711), -4*eps ("single")) +%!assert (norm (x,3), single (8.24257059961711), -4* eps ("single")) %!assert (norm (x,Inf), single (7)) %!assert (norm (x,-Inf), single (1)) %!assert (norm (x,"inf"), single (7)) @@ -6280,7 +6280,7 @@ %!assert (norm (x,"fro"), single (10), -eps ("single")) %!assert (norm (x), single (10)) %!assert (norm (single ([1e38, 1])), single (1e38)) -%!assert (norm (single ([3+4i, 3-4i, sqrt(31)])), single (9), -4*eps ("single")) +%!assert (norm (single ([3+4i, 3-4i, sqrt(31)])), single (9), -4* eps ("single")) %!shared m %! m = single (magic (4)); %!assert (norm (m,1), single (34)) @@ -8431,17 +8431,17 @@ MAKE_INT_BRANCH(int8) else MAKE_INT_BRANCH(int16) - else MAKE_INT_BRANCH(int32) - else MAKE_INT_BRANCH(int64) - else MAKE_INT_BRANCH(uint8) - else MAKE_INT_BRANCH(uint16) - else MAKE_INT_BRANCH(uint32) - else MAKE_INT_BRANCH(uint64) + else MAKE_INT_BRANCH(int32) + else MAKE_INT_BRANCH(int64) + else MAKE_INT_BRANCH(uint8) + else MAKE_INT_BRANCH(uint16) + else MAKE_INT_BRANCH(uint32) + else MAKE_INT_BRANCH(uint64) #undef MAKE_INT_BRANCH - else - panic_impossible (); + else + panic_impossible (); } else if (args(0).is_single_type ()) { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/debug.cc --- a/libinterp/corefcn/debug.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/debug.cc Thu Dec 01 20:05:44 2022 -0800 @@ -190,7 +190,7 @@ if (symbol_name != "") { retmap = bptab.add_breakpoints_in_function (symbol_name, class_name, - lines, condition); + lines, condition); retval = bp_lines_to_ov (retmap); } } @@ -395,17 +395,17 @@ } else { -/* - if (tw.in_debug_repl ()) - { - octave_user_code *dbg_fcn = tw.get_user_code (); - if (dbg_fcn) - { - symbol_name = dbg_fcn->name (); - fcn_list(0) = symbol_name; - } - } -*/ + /* + if (tw.in_debug_repl ()) + { + octave_user_code *dbg_fcn = tw.get_user_code (); + if (dbg_fcn) + { + symbol_name = dbg_fcn->name (); + fcn_list(0) = symbol_name; + } + } + */ bp_list = bptab.get_breakpoint_list (fcn_list); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/defaults.cc --- a/libinterp/corefcn/defaults.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/defaults.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,401 +51,401 @@ OCTAVE_BEGIN_NAMESPACE(config) - // Variables that name directories or files are substituted into source - // files with "${prefix}/" stripped from the beginning of the string. +// Variables that name directories or files are substituted into source +// files with "${prefix}/" stripped from the beginning of the string. - // All configure variables of this form should be specified as absolute - // directory names. The only ones that should not be absolute here are - // ones that have had "${prefix}/" or "${exec_prefix} stripped. +// All configure variables of this form should be specified as absolute +// directory names. The only ones that should not be absolute here are +// ones that have had "${prefix}/" or "${exec_prefix} stripped. - static std::string - prepend_home_dir (const std::string& hd, const std::string& s) - { - std::string retval = s; +static std::string +prepend_home_dir (const std::string& hd, const std::string& s) +{ + std::string retval = s; - char dir_sep_char = sys::file_ops::dir_sep_char (); + char dir_sep_char = sys::file_ops::dir_sep_char (); - if (! sys::env::absolute_pathname (retval)) - retval = hd + dir_sep_char + s; + if (! sys::env::absolute_pathname (retval)) + retval = hd + dir_sep_char + s; - if (dir_sep_char != '/') - std::replace (retval.begin (), retval.end (), '/', dir_sep_char); + if (dir_sep_char != '/') + std::replace (retval.begin (), retval.end (), '/', dir_sep_char); - return retval; - } + return retval; +} - static std::string get_octave_home (void) - { - std::string op = OCTAVE_PREFIX; +static std::string get_octave_home (void) +{ + std::string op = OCTAVE_PREFIX; - std::string oh = sys::env::getenv ("OCTAVE_HOME"); + std::string oh = sys::env::getenv ("OCTAVE_HOME"); - // If OCTAVE_HOME is set in the environment, use that. Otherwise, - // default to ${prefix} from configure. + // If OCTAVE_HOME is set in the environment, use that. Otherwise, + // default to ${prefix} from configure. - return oh.empty () ? op : oh; - } + return oh.empty () ? op : oh; +} - static std::string get_octave_exec_home (void) - { - std::string op = OCTAVE_PREFIX; - std::string oep = OCTAVE_EXEC_PREFIX; +static std::string get_octave_exec_home (void) +{ + std::string op = OCTAVE_PREFIX; + std::string oep = OCTAVE_EXEC_PREFIX; - std::string oh = sys::env::getenv ("OCTAVE_HOME"); - std::string oeh = sys::env::getenv ("OCTAVE_EXEC_HOME"); + std::string oh = sys::env::getenv ("OCTAVE_HOME"); + std::string oeh = sys::env::getenv ("OCTAVE_EXEC_HOME"); - // If OCTAVE_EXEC_HOME is set in the environment, use that. - // Otherwise, if ${prefix} and ${exec_prefix} from configure are set - // to the same value, use OCTAVE_HOME from the environment if it is set. - // Otherwise, default to ${exec_prefix} from configure. + // If OCTAVE_EXEC_HOME is set in the environment, use that. + // Otherwise, if ${prefix} and ${exec_prefix} from configure are set + // to the same value, use OCTAVE_HOME from the environment if it is set. + // Otherwise, default to ${exec_prefix} from configure. - if (! oeh.empty ()) - return oeh; + if (! oeh.empty ()) + return oeh; - if (op == oep && ! oh.empty ()) - return oh; + if (op == oep && ! oh.empty ()) + return oh; - return oep; - } + return oep; +} - static std::string get_local_site_defaults_file (void) - { - std::string lsf = sys::env::getenv ("OCTAVE_SITE_INITFILE"); +static std::string get_local_site_defaults_file (void) +{ + std::string lsf = sys::env::getenv ("OCTAVE_SITE_INITFILE"); - return lsf.empty () ? local_startupfile_dir () + "/octaverc" : lsf; - } + return lsf.empty () ? local_startupfile_dir () + "/octaverc" : lsf; +} - static std::string get_site_defaults_file (void) - { - std::string sf = sys::env::getenv ("OCTAVE_VERSION_INITFILE"); +static std::string get_site_defaults_file (void) +{ + std::string sf = sys::env::getenv ("OCTAVE_VERSION_INITFILE"); - return sf.empty () ? startupfile_dir () + "/octaverc" : sf; - } + return sf.empty () ? startupfile_dir () + "/octaverc" : sf; +} - std::string prepend_octave_home (const std::string& s) - { - return prepend_home_dir (octave_home (), s); - } +std::string prepend_octave_home (const std::string& s) +{ + return prepend_home_dir (octave_home (), s); +} - std::string prepend_octave_exec_home (const std::string& s) - { - return prepend_home_dir (octave_exec_home (), s); - } +std::string prepend_octave_exec_home (const std::string& s) +{ + return prepend_home_dir (octave_exec_home (), s); +} - std::string canonical_host_type (void) - { - static const std::string s_canonical_host_type - = OCTAVE_CANONICAL_HOST_TYPE; +std::string canonical_host_type (void) +{ + static const std::string s_canonical_host_type + = OCTAVE_CANONICAL_HOST_TYPE; - return s_canonical_host_type; - } + return s_canonical_host_type; +} - std::string release (void) - { - static const std::string s_octave_release = OCTAVE_RELEASE; +std::string release (void) +{ + static const std::string s_octave_release = OCTAVE_RELEASE; - return s_octave_release; - } + return s_octave_release; +} - std::string default_pager (void) - { - static const std::string s_default_pager = OCTAVE_DEFAULT_PAGER; +std::string default_pager (void) +{ + static const std::string s_default_pager = OCTAVE_DEFAULT_PAGER; - return s_default_pager; - } + return s_default_pager; +} - std::string octave_home (void) - { - static const std::string s_octave_home = get_octave_home (); +std::string octave_home (void) +{ + static const std::string s_octave_home = get_octave_home (); - return s_octave_home; - } + return s_octave_home; +} - std::string octave_exec_home (void) - { - static const std::string s_octave_exec_home = get_octave_exec_home (); +std::string octave_exec_home (void) +{ + static const std::string s_octave_exec_home = get_octave_exec_home (); - return s_octave_exec_home; - } + return s_octave_exec_home; +} - std::string bin_dir (void) - { - static const std::string s_bin_dir - = prepend_octave_exec_home (OCTAVE_BINDIR); +std::string bin_dir (void) +{ + static const std::string s_bin_dir + = prepend_octave_exec_home (OCTAVE_BINDIR); - return s_bin_dir; - } + return s_bin_dir; +} - std::string data_dir (void) - { - static const std::string s_data_dir - = prepend_octave_home (OCTAVE_DATADIR); +std::string data_dir (void) +{ + static const std::string s_data_dir + = prepend_octave_home (OCTAVE_DATADIR); - return s_data_dir; - } + return s_data_dir; +} - std::string dataroot_dir (void) - { - static const std::string s_dataroot_dir - = prepend_octave_home (OCTAVE_DATAROOTDIR); +std::string dataroot_dir (void) +{ + static const std::string s_dataroot_dir + = prepend_octave_home (OCTAVE_DATAROOTDIR); - return s_dataroot_dir; - } + return s_dataroot_dir; +} - std::string include_dir (void) - { - static const std::string s_include_dir - = prepend_octave_home (OCTAVE_INCLUDEDIR); +std::string include_dir (void) +{ + static const std::string s_include_dir + = prepend_octave_home (OCTAVE_INCLUDEDIR); - return s_include_dir; - } + return s_include_dir; +} - std::string lib_dir (void) - { - static const std::string s_lib_dir - = prepend_octave_exec_home (OCTAVE_LIBDIR); +std::string lib_dir (void) +{ + static const std::string s_lib_dir + = prepend_octave_exec_home (OCTAVE_LIBDIR); - return s_lib_dir; - } + return s_lib_dir; +} - std::string libexec_dir (void) - { - static const std::string s_libexec_dir - = prepend_octave_exec_home (OCTAVE_LIBEXECDIR); +std::string libexec_dir (void) +{ + static const std::string s_libexec_dir + = prepend_octave_exec_home (OCTAVE_LIBEXECDIR); - return s_libexec_dir; - } + return s_libexec_dir; +} - std::string arch_lib_dir (void) - { - static const std::string s_arch_lib_dir - = prepend_octave_exec_home (OCTAVE_ARCHLIBDIR); +std::string arch_lib_dir (void) +{ + static const std::string s_arch_lib_dir + = prepend_octave_exec_home (OCTAVE_ARCHLIBDIR); - return s_arch_lib_dir; - } + return s_arch_lib_dir; +} - std::string info_dir (void) - { - static const std::string s_info_dir - = prepend_octave_exec_home (OCTAVE_INFODIR); +std::string info_dir (void) +{ + static const std::string s_info_dir + = prepend_octave_exec_home (OCTAVE_INFODIR); - return s_info_dir; - } + return s_info_dir; +} - std::string local_ver_arch_lib_dir (void) - { - static const std::string s_local_ver_arch_lib_dir - = prepend_octave_exec_home (OCTAVE_LOCALVERARCHLIBDIR); +std::string local_ver_arch_lib_dir (void) +{ + static const std::string s_local_ver_arch_lib_dir + = prepend_octave_exec_home (OCTAVE_LOCALVERARCHLIBDIR); - return s_local_ver_arch_lib_dir; - } + return s_local_ver_arch_lib_dir; +} - std::string local_api_arch_lib_dir (void) - { - static const std::string s_local_api_arch_lib_dir - = prepend_octave_exec_home (OCTAVE_LOCALAPIARCHLIBDIR); +std::string local_api_arch_lib_dir (void) +{ + static const std::string s_local_api_arch_lib_dir + = prepend_octave_exec_home (OCTAVE_LOCALAPIARCHLIBDIR); - return s_local_api_arch_lib_dir; - } + return s_local_api_arch_lib_dir; +} - std::string local_arch_lib_dir (void) - { - static const std::string s_local_arch_lib_dir - = prepend_octave_exec_home (OCTAVE_LOCALARCHLIBDIR); +std::string local_arch_lib_dir (void) +{ + static const std::string s_local_arch_lib_dir + = prepend_octave_exec_home (OCTAVE_LOCALARCHLIBDIR); - return s_local_arch_lib_dir; - } + return s_local_arch_lib_dir; +} - std::string local_ver_oct_file_dir (void) - { - static const std::string s_local_ver_oct_file_dir - = prepend_octave_exec_home (OCTAVE_LOCALVEROCTFILEDIR); +std::string local_ver_oct_file_dir (void) +{ + static const std::string s_local_ver_oct_file_dir + = prepend_octave_exec_home (OCTAVE_LOCALVEROCTFILEDIR); - return s_local_ver_oct_file_dir; - } + return s_local_ver_oct_file_dir; +} - std::string local_api_oct_file_dir (void) - { - static const std::string s_local_api_oct_file_dir - = prepend_octave_exec_home (OCTAVE_LOCALAPIOCTFILEDIR); +std::string local_api_oct_file_dir (void) +{ + static const std::string s_local_api_oct_file_dir + = prepend_octave_exec_home (OCTAVE_LOCALAPIOCTFILEDIR); - return s_local_api_oct_file_dir; - } + return s_local_api_oct_file_dir; +} - std::string local_oct_file_dir (void) - { - static const std::string s_local_oct_file_dir - = prepend_octave_exec_home (OCTAVE_LOCALOCTFILEDIR); +std::string local_oct_file_dir (void) +{ + static const std::string s_local_oct_file_dir + = prepend_octave_exec_home (OCTAVE_LOCALOCTFILEDIR); - return s_local_oct_file_dir; - } + return s_local_oct_file_dir; +} - std::string oct_file_dir (void) - { - static const std::string s_oct_file_dir - = prepend_octave_exec_home (OCTAVE_OCTFILEDIR); +std::string oct_file_dir (void) +{ + static const std::string s_oct_file_dir + = prepend_octave_exec_home (OCTAVE_OCTFILEDIR); - return s_oct_file_dir; - } + return s_oct_file_dir; +} - std::string local_ver_fcn_file_dir (void) - { - static const std::string s_local_ver_fcn_file_dir - = prepend_octave_home (OCTAVE_LOCALVERFCNFILEDIR); +std::string local_ver_fcn_file_dir (void) +{ + static const std::string s_local_ver_fcn_file_dir + = prepend_octave_home (OCTAVE_LOCALVERFCNFILEDIR); - return s_local_ver_fcn_file_dir; - } + return s_local_ver_fcn_file_dir; +} - std::string local_api_fcn_file_dir (void) - { - static const std::string s_local_api_fcn_file_dir - = prepend_octave_home (OCTAVE_LOCALAPIFCNFILEDIR); +std::string local_api_fcn_file_dir (void) +{ + static const std::string s_local_api_fcn_file_dir + = prepend_octave_home (OCTAVE_LOCALAPIFCNFILEDIR); - return s_local_api_fcn_file_dir; - } + return s_local_api_fcn_file_dir; +} - std::string local_fcn_file_dir (void) - { - static const std::string s_local_fcn_file_dir - = prepend_octave_home (OCTAVE_LOCALFCNFILEDIR); +std::string local_fcn_file_dir (void) +{ + static const std::string s_local_fcn_file_dir + = prepend_octave_home (OCTAVE_LOCALFCNFILEDIR); - return s_local_fcn_file_dir; - } + return s_local_fcn_file_dir; +} - std::string fcn_file_dir (void) - { - static const std::string s_fcn_file_dir - = prepend_octave_home (OCTAVE_FCNFILEDIR); +std::string fcn_file_dir (void) +{ + static const std::string s_fcn_file_dir + = prepend_octave_home (OCTAVE_FCNFILEDIR); - return s_fcn_file_dir; - } + return s_fcn_file_dir; +} - std::string oct_data_dir (void) - { - static const std::string s_oct_data_dir - = prepend_octave_home (OCTAVE_OCTDATADIR); +std::string oct_data_dir (void) +{ + static const std::string s_oct_data_dir + = prepend_octave_home (OCTAVE_OCTDATADIR); - return s_oct_data_dir; - } + return s_oct_data_dir; +} - std::string oct_doc_dir (void) - { - static const std::string s_oct_doc_dir - = prepend_octave_home (OCTAVE_OCTDOCDIR); +std::string oct_doc_dir (void) +{ + static const std::string s_oct_doc_dir + = prepend_octave_home (OCTAVE_OCTDOCDIR); - return s_oct_doc_dir; - } + return s_oct_doc_dir; +} - std::string oct_etc_dir (void) - { - static const std::string s_oct_etc_dir - = prepend_octave_home (OCTAVE_OCTETCDIR); +std::string oct_etc_dir (void) +{ + static const std::string s_oct_etc_dir + = prepend_octave_home (OCTAVE_OCTETCDIR); - return s_oct_etc_dir; - } + return s_oct_etc_dir; +} - std::string oct_fonts_dir (void) - { - static const std::string s_oct_fonts_dir - = prepend_octave_home (OCTAVE_OCTFONTSDIR); +std::string oct_fonts_dir (void) +{ + static const std::string s_oct_fonts_dir + = prepend_octave_home (OCTAVE_OCTFONTSDIR); - return s_oct_fonts_dir; - } + return s_oct_fonts_dir; +} - std::string oct_include_dir (void) - { - static const std::string s_oct_include_dir - = prepend_octave_home (OCTAVE_OCTINCLUDEDIR); +std::string oct_include_dir (void) +{ + static const std::string s_oct_include_dir + = prepend_octave_home (OCTAVE_OCTINCLUDEDIR); - return s_oct_include_dir; - } + return s_oct_include_dir; +} - std::string oct_lib_dir (void) - { - static const std::string s_oct_lib_dir - = prepend_octave_exec_home (OCTAVE_OCTLIBDIR); +std::string oct_lib_dir (void) +{ + static const std::string s_oct_lib_dir + = prepend_octave_exec_home (OCTAVE_OCTLIBDIR); - return s_oct_lib_dir; - } + return s_oct_lib_dir; +} - std::string oct_locale_dir (void) - { - static const std::string s_oct_locale_dir - = prepend_octave_home (OCTAVE_OCTLOCALEDIR); +std::string oct_locale_dir (void) +{ + static const std::string s_oct_locale_dir + = prepend_octave_home (OCTAVE_OCTLOCALEDIR); - return s_oct_locale_dir; - } + return s_oct_locale_dir; +} - std::string oct_tests_dir (void) - { - static const std::string s_oct_tests_dir - = prepend_octave_home (OCTAVE_OCTTESTSDIR); +std::string oct_tests_dir (void) +{ + static const std::string s_oct_tests_dir + = prepend_octave_home (OCTAVE_OCTTESTSDIR); - return s_oct_tests_dir; - } + return s_oct_tests_dir; +} - std::string man_dir (void) - { - static const std::string s_man_dir - = prepend_octave_home (OCTAVE_MANDIR); +std::string man_dir (void) +{ + static const std::string s_man_dir + = prepend_octave_home (OCTAVE_MANDIR); - return s_man_dir; - } + return s_man_dir; +} - std::string man1_dir (void) - { - static const std::string s_man1_dir - = prepend_octave_home (OCTAVE_MAN1DIR); +std::string man1_dir (void) +{ + static const std::string s_man1_dir + = prepend_octave_home (OCTAVE_MAN1DIR); - return s_man1_dir; - } + return s_man1_dir; +} - std::string man1_ext (void) - { - static const std::string s_man1_ext = OCTAVE_MAN1EXT; +std::string man1_ext (void) +{ + static const std::string s_man1_ext = OCTAVE_MAN1EXT; - return s_man1_ext; - } + return s_man1_ext; +} - std::string image_dir (void) - { - static const std::string s_image_dir - = prepend_octave_home (OCTAVE_IMAGEDIR); +std::string image_dir (void) +{ + static const std::string s_image_dir + = prepend_octave_home (OCTAVE_IMAGEDIR); - return s_image_dir; - } + return s_image_dir; +} - std::string local_startupfile_dir (void) - { - static const std::string s_local_startupfile_dir - = prepend_octave_home (OCTAVE_LOCALSTARTUPFILEDIR); +std::string local_startupfile_dir (void) +{ + static const std::string s_local_startupfile_dir + = prepend_octave_home (OCTAVE_LOCALSTARTUPFILEDIR); - return s_local_startupfile_dir; - } + return s_local_startupfile_dir; +} - std::string startupfile_dir (void) - { - static const std::string s_startupfile_dir - = prepend_octave_home (OCTAVE_STARTUPFILEDIR); +std::string startupfile_dir (void) +{ + static const std::string s_startupfile_dir + = prepend_octave_home (OCTAVE_STARTUPFILEDIR); - return s_startupfile_dir; - } + return s_startupfile_dir; +} - std::string local_site_defaults_file (void) - { - static const std::string s_local_site_defaults_file - = get_local_site_defaults_file (); +std::string local_site_defaults_file (void) +{ + static const std::string s_local_site_defaults_file + = get_local_site_defaults_file (); - return s_local_site_defaults_file; - } + return s_local_site_defaults_file; +} - std::string site_defaults_file (void) - { - static const std::string s_site_defaults_file - = get_site_defaults_file (); +std::string site_defaults_file (void) +{ + static const std::string s_site_defaults_file + = get_site_defaults_file (); - return s_site_defaults_file; - } + return s_site_defaults_file; +} OCTAVE_END_NAMESPACE(config) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/defaults.h --- a/libinterp/corefcn/defaults.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/defaults.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,71 +36,71 @@ OCTAVE_BEGIN_NAMESPACE(config) - extern OCTINTERP_API std::string - prepend_octave_home (const std::string& s); +extern OCTINTERP_API std::string +prepend_octave_home (const std::string& s); - extern OCTINTERP_API std::string - prepend_octave_exec_home (const std::string& s); +extern OCTINTERP_API std::string +prepend_octave_exec_home (const std::string& s); - // These could be defined as pure constants, but we'll use - // functions to be consistent with the values that require - // initialization. +// These could be defined as pure constants, but we'll use +// functions to be consistent with the values that require +// initialization. - extern OCTINTERP_API std::string canonical_host_type (void); - extern OCTINTERP_API std::string release (void); - extern OCTINTERP_API std::string default_pager (void); +extern OCTINTERP_API std::string canonical_host_type (void); +extern OCTINTERP_API std::string release (void); +extern OCTINTERP_API std::string default_pager (void); - // These require initialization, so can't be defined as pure - // constants. We use functions to access these values so that - // they can't be modified by users. +// These require initialization, so can't be defined as pure +// constants. We use functions to access these values so that +// they can't be modified by users. - extern OCTINTERP_API std::string octave_home (void); - extern OCTINTERP_API std::string octave_exec_home (void); +extern OCTINTERP_API std::string octave_home (void); +extern OCTINTERP_API std::string octave_exec_home (void); - extern OCTINTERP_API std::string bin_dir (void); - extern OCTINTERP_API std::string data_dir (void); - extern OCTINTERP_API std::string dataroot_dir (void); - extern OCTINTERP_API std::string include_dir (void); - extern OCTINTERP_API std::string lib_dir (void); - extern OCTINTERP_API std::string libexec_dir (void); +extern OCTINTERP_API std::string bin_dir (void); +extern OCTINTERP_API std::string data_dir (void); +extern OCTINTERP_API std::string dataroot_dir (void); +extern OCTINTERP_API std::string include_dir (void); +extern OCTINTERP_API std::string lib_dir (void); +extern OCTINTERP_API std::string libexec_dir (void); - extern OCTINTERP_API std::string local_ver_arch_lib_dir (void); - extern OCTINTERP_API std::string local_api_arch_lib_dir (void); - extern OCTINTERP_API std::string local_arch_lib_dir (void); - extern OCTINTERP_API std::string arch_lib_dir (void); +extern OCTINTERP_API std::string local_ver_arch_lib_dir (void); +extern OCTINTERP_API std::string local_api_arch_lib_dir (void); +extern OCTINTERP_API std::string local_arch_lib_dir (void); +extern OCTINTERP_API std::string arch_lib_dir (void); - extern OCTINTERP_API std::string local_ver_oct_file_dir (void); - extern OCTINTERP_API std::string local_api_oct_file_dir (void); - extern OCTINTERP_API std::string local_oct_file_dir (void); - extern OCTINTERP_API std::string oct_file_dir (void); +extern OCTINTERP_API std::string local_ver_oct_file_dir (void); +extern OCTINTERP_API std::string local_api_oct_file_dir (void); +extern OCTINTERP_API std::string local_oct_file_dir (void); +extern OCTINTERP_API std::string oct_file_dir (void); - extern OCTINTERP_API std::string local_ver_fcn_file_dir (void); - extern OCTINTERP_API std::string local_api_fcn_file_dir (void); - extern OCTINTERP_API std::string local_fcn_file_dir (void); - extern OCTINTERP_API std::string fcn_file_dir (void); +extern OCTINTERP_API std::string local_ver_fcn_file_dir (void); +extern OCTINTERP_API std::string local_api_fcn_file_dir (void); +extern OCTINTERP_API std::string local_fcn_file_dir (void); +extern OCTINTERP_API std::string fcn_file_dir (void); - extern OCTINTERP_API std::string oct_data_dir (void); - extern OCTINTERP_API std::string oct_doc_dir (void); - extern OCTINTERP_API std::string oct_etc_dir (void); - extern OCTINTERP_API std::string oct_fonts_dir (void); - extern OCTINTERP_API std::string oct_include_dir (void); - extern OCTINTERP_API std::string oct_lib_dir (void); - extern OCTINTERP_API std::string oct_locale_dir (void); - extern OCTINTERP_API std::string oct_tests_dir (void); +extern OCTINTERP_API std::string oct_data_dir (void); +extern OCTINTERP_API std::string oct_doc_dir (void); +extern OCTINTERP_API std::string oct_etc_dir (void); +extern OCTINTERP_API std::string oct_fonts_dir (void); +extern OCTINTERP_API std::string oct_include_dir (void); +extern OCTINTERP_API std::string oct_lib_dir (void); +extern OCTINTERP_API std::string oct_locale_dir (void); +extern OCTINTERP_API std::string oct_tests_dir (void); - extern OCTINTERP_API std::string info_dir (void); +extern OCTINTERP_API std::string info_dir (void); - extern OCTINTERP_API std::string man_dir (void); - extern OCTINTERP_API std::string man1_dir (void); - extern OCTINTERP_API std::string man1_ext (void); +extern OCTINTERP_API std::string man_dir (void); +extern OCTINTERP_API std::string man1_dir (void); +extern OCTINTERP_API std::string man1_ext (void); - extern OCTINTERP_API std::string image_dir (void); +extern OCTINTERP_API std::string image_dir (void); - extern OCTINTERP_API std::string local_startupfile_dir (void); - extern OCTINTERP_API std::string startupfile_dir (void); +extern OCTINTERP_API std::string local_startupfile_dir (void); +extern OCTINTERP_API std::string startupfile_dir (void); - extern OCTINTERP_API std::string local_site_defaults_file (void); - extern OCTINTERP_API std::string site_defaults_file (void); +extern OCTINTERP_API std::string local_site_defaults_file (void); +extern OCTINTERP_API std::string site_defaults_file (void); OCTAVE_END_NAMESPACE(config) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/det.cc --- a/libinterp/corefcn/det.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/det.cc Thu Dec 01 20:05:44 2022 -0800 @@ -186,7 +186,7 @@ MAYBE_CAST (rep, octave_matrix); MatrixType mtype = (rep ? rep -> matrix_type () - : MatrixType ()); + : MatrixType ()); DET det = m.determinant (mtype, info, rcond); retval(0) = (info == -1 ? 0.0 : det.value ()); retval(1) = rcond; @@ -213,7 +213,7 @@ MAYBE_CAST (rep, octave_complex_matrix); MatrixType mtype = (rep ? rep -> matrix_type () - : MatrixType ()); + : MatrixType ()); ComplexDET det = m.determinant (mtype, info, rcond); retval(0) = (info == -1 ? Complex (0.0) : det.value ()); retval(1) = rcond; @@ -230,7 +230,7 @@ /* %!assert (det ([1, 2; 3, 4]), -2, 10*eps) -%!assert (det (single ([1, 2; 3, 4])), single (-2), 10*eps ("single")) +%!assert (det (single ([1, 2; 3, 4])), single (-2), 10* eps ("single")) %!assert (det (eye (2000)), 1) %!error det () %!error det (1, 2) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/display.cc --- a/libinterp/corefcn/display.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/display.cc Thu Dec 01 20:05:44 2022 -0800 @@ -39,19 +39,19 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void display_info::initialize (void) - { - int avail = 0; +void display_info::initialize (void) +{ + int avail = 0; - const char *msg - = octave_get_display_info (nullptr, &m_ht, &m_wd, &m_dp, - &m_rx, &m_ry, &avail); + const char *msg + = octave_get_display_info (nullptr, &m_ht, &m_wd, &m_dp, + &m_rx, &m_ry, &avail); - m_dpy_avail = avail; + m_dpy_avail = avail; - if (msg) - m_msg = msg; - } + if (msg) + m_msg = msg; +} DEFMETHOD (have_window_system, interp, , , doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/display.h --- a/libinterp/corefcn/display.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/display.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,58 +34,58 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class display_info - { - public: +class display_info +{ +public: - // Create object with default values. To be useful, you must call - // initialize to find the actual system parameters for the given - // display. + // Create object with default values. To be useful, you must call + // initialize to find the actual system parameters for the given + // display. - display_info (void) - : m_rx (72), m_ry (72), m_ht (1), m_wd (1), m_dp (0), - m_dpy_avail (false), m_msg () - { } + display_info (void) + : m_rx (72), m_ry (72), m_ht (1), m_wd (1), m_dp (0), + m_dpy_avail (false), m_msg () + { } - ~display_info (void) = default; + ~display_info (void) = default; - display_info (const display_info&) = default; + display_info (const display_info&) = default; - display_info& operator = (const display_info&) = default; + display_info& operator = (const display_info&) = default; - void initialize (void); + void initialize (void); - double x_dpi (void) const { return m_rx; } + double x_dpi (void) const { return m_rx; } - double y_dpi (void) const { return m_ry; } + double y_dpi (void) const { return m_ry; } - int height (void) const { return m_ht; } + int height (void) const { return m_ht; } - int width (void) const { return m_wd; } + int width (void) const { return m_wd; } - int depth (void) const { return m_dp; } + int depth (void) const { return m_dp; } - bool display_available (void) const { return m_dpy_avail; } + bool display_available (void) const { return m_dpy_avail; } - std::string message (void) const { return m_msg; } + std::string message (void) const { return m_msg; } - private: +private: - // X- and Y- Resolution of the display in dots (pixels) per inch. - double m_rx; - double m_ry; + // X- and Y- Resolution of the display in dots (pixels) per inch. + double m_rx; + double m_ry; - // Height, width, and depth of the display. - int m_ht; - int m_wd; - int m_dp; + // Height, width, and depth of the display. + int m_ht; + int m_wd; + int m_dp; - bool m_dpy_avail; + bool m_dpy_avail; - // Message associated with any initiailization failure. Set if - // m_dpy_avail is false. - std::string m_msg; - }; + // Message associated with any initiailization failure. Set if + // m_dpy_avail is false. + std::string m_msg; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/dlmread.cc --- a/libinterp/corefcn/dlmread.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/dlmread.cc Thu Dec 01 20:05:44 2022 -0800 @@ -341,7 +341,7 @@ std::string old_locale (prev_locale ? prev_locale : ""); std::setlocale (LC_ALL, "C"); unwind_action act - ([old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); + ([old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); std::string line; diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/dynamic-ld.cc --- a/libinterp/corefcn/dynamic-ld.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/dynamic-ld.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,274 +51,274 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - dynamic_loader::shlibs_list::append (const dynamic_library& shl) - { - m_lib_list.push_back (shl); - } +void +dynamic_loader::shlibs_list::append (const dynamic_library& shl) +{ + m_lib_list.push_back (shl); +} - std::list - dynamic_loader::shlibs_list::remove (dynamic_library& shl) - { - std::list removed_fcns; +std::list +dynamic_loader::shlibs_list::remove (dynamic_library& shl) +{ + std::list removed_fcns; - for (auto p = m_lib_list.begin (); p != m_lib_list.end (); p++) - { - if (*p == shl) - { - m_lib_list.erase (p); + for (auto p = m_lib_list.begin (); p != m_lib_list.end (); p++) + { + if (*p == shl) + { + m_lib_list.erase (p); - removed_fcns = shl.close (); + removed_fcns = shl.close (); - break; - } - } + break; + } + } - return removed_fcns; - } + return removed_fcns; +} - dynamic_library - dynamic_loader::shlibs_list::find_file (const std::string& file_name) const - { - dynamic_library retval; +dynamic_library +dynamic_loader::shlibs_list::find_file (const std::string& file_name) const +{ + dynamic_library retval; - for (const auto& lib : m_lib_list) - { - if (lib.file_name () == file_name) - { - retval = lib; - break; - } - } + for (const auto& lib : m_lib_list) + { + if (lib.file_name () == file_name) + { + retval = lib; + break; + } + } - return retval; - } + return retval; +} - void - dynamic_loader::shlibs_list::display (void) const - { - std::cerr << "current shared libraries:" << std::endl; - for (const auto& lib : m_lib_list) - std::cerr << " " << lib.file_name () << std::endl; - } +void +dynamic_loader::shlibs_list::display (void) const +{ + std::cerr << "current shared libraries:" << std::endl; + for (const auto& lib : m_lib_list) + std::cerr << " " << lib.file_name () << std::endl; +} - void - dynamic_loader::clear_function (const std::string& fcn_name) - { - warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ()); +void +dynamic_loader::clear_function (const std::string& fcn_name) +{ + warning_with_id ("Octave:reload-forces-clear", " %s", fcn_name.c_str ()); - // FIXME: is there a way to avoid this? Can we manage the list of - // functions that are loaded in the symbol table completely outside - // of the dynamic_loader class? + // FIXME: is there a way to avoid this? Can we manage the list of + // functions that are loaded in the symbol table completely outside + // of the dynamic_loader class? - symbol_table& symtab = m_interpreter.get_symbol_table (); + symbol_table& symtab = m_interpreter.get_symbol_table (); - symtab.clear_dld_function (fcn_name); - } + symtab.clear_dld_function (fcn_name); +} - void - dynamic_loader::clear (dynamic_library& oct_file) - { - if (oct_file.number_of_functions_loaded () > 1) - { - warning_with_id ("Octave:reload-forces-clear", - "reloading %s clears the following functions:", - oct_file.file_name ().c_str ()); +void +dynamic_loader::clear (dynamic_library& oct_file) +{ + if (oct_file.number_of_functions_loaded () > 1) + { + warning_with_id ("Octave:reload-forces-clear", + "reloading %s clears the following functions:", + oct_file.file_name ().c_str ()); - std::list removed_fcns = m_loaded_shlibs.remove (oct_file); + std::list removed_fcns = m_loaded_shlibs.remove (oct_file); - for (const auto& fcn_name : removed_fcns) - clear_function (fcn_name); - } - else - { - std::list removed_fcns = m_loaded_shlibs.remove (oct_file); + for (const auto& fcn_name : removed_fcns) + clear_function (fcn_name); + } + else + { + std::list removed_fcns = m_loaded_shlibs.remove (oct_file); - // FIXME: is there a way to avoid this? Can we manage the list - // of functions that are loaded in the symbol table completely - // outside of the dynamic_loader class? + // FIXME: is there a way to avoid this? Can we manage the list + // of functions that are loaded in the symbol table completely + // outside of the dynamic_loader class? - symbol_table& symtab = m_interpreter.get_symbol_table (); + symbol_table& symtab = m_interpreter.get_symbol_table (); - for (const auto& fcn_name : removed_fcns) - symtab.clear_dld_function (fcn_name); - } - } + for (const auto& fcn_name : removed_fcns) + symtab.clear_dld_function (fcn_name); + } +} - octave_function * - dynamic_loader::load_oct (const std::string& fcn_name, - const std::string& file_name, - bool relative) - { - octave_function *retval = nullptr; +octave_function * +dynamic_loader::load_oct (const std::string& fcn_name, + const std::string& file_name, + bool relative) +{ + octave_function *retval = nullptr; - unwind_protect_var restore_var (m_doing_load, true); + unwind_protect_var restore_var (m_doing_load, true); - dynamic_library oct_file = m_loaded_shlibs.find_file (file_name); + dynamic_library oct_file = m_loaded_shlibs.find_file (file_name); - if (oct_file && oct_file.is_out_of_date ()) - clear (oct_file); + if (oct_file && oct_file.is_out_of_date ()) + clear (oct_file); - if (! oct_file) - { - oct_file.open (file_name); + if (! oct_file) + { + oct_file.open (file_name); - if (oct_file) - m_loaded_shlibs.append (oct_file); - } + if (oct_file) + m_loaded_shlibs.append (oct_file); + } - if (! oct_file) - error ("%s is not a valid shared library", file_name.c_str ()); + if (! oct_file) + error ("%s is not a valid shared library", file_name.c_str ()); - void *function = oct_file.search (fcn_name, name_mangler); + void *function = oct_file.search (fcn_name, name_mangler); - if (! function) - { - // FIXME: can we determine this C mangling scheme - // automatically at run time or configure time? + if (! function) + { + // FIXME: can we determine this C mangling scheme + // automatically at run time or configure time? - function = oct_file.search (fcn_name, name_uscore_mangler); - } + function = oct_file.search (fcn_name, name_uscore_mangler); + } - if (function) - { - octave_dld_fcn_getter f - = reinterpret_cast (function); + if (function) + { + octave_dld_fcn_getter f + = reinterpret_cast (function); - retval = f (oct_file, relative); + retval = f (oct_file, relative); - if (! retval) - error ("failed to install .oct file function '%s'", - fcn_name.c_str ()); - } + if (! retval) + error ("failed to install .oct file function '%s'", + fcn_name.c_str ()); + } - return retval; - } + 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". +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; + have_fmex = false; - void *function = mex_file.search (fcn_name, mex_mangler); + 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? + 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); + function = mex_file.search (fcn_name, mex_uscore_mangler); - if (! function) - { - function = mex_file.search (fcn_name, mex_f77_mangler); + if (! function) + { + function = mex_file.search (fcn_name, mex_f77_mangler); - if (function) - have_fmex = true; - } - } + if (function) + have_fmex = true; + } + } - return function; - } + return function; +} - octave_function * - dynamic_loader::load_mex (const std::string& fcn_name, - const std::string& file_name, - bool /*relative*/) - { - unwind_protect_var restore_var (m_doing_load, true); +octave_function * +dynamic_loader::load_mex (const std::string& fcn_name, + const std::string& file_name, + bool /*relative*/) +{ + unwind_protect_var restore_var (m_doing_load, true); - dynamic_library mex_file = m_loaded_shlibs.find_file (file_name); + dynamic_library mex_file = m_loaded_shlibs.find_file (file_name); - if (mex_file && mex_file.is_out_of_date ()) - clear (mex_file); + if (mex_file && mex_file.is_out_of_date ()) + clear (mex_file); - if (! mex_file) - { - mex_file.open (file_name); + if (! mex_file) + { + mex_file.open (file_name); - if (mex_file) - m_loaded_shlibs.append (mex_file); - } + if (mex_file) + m_loaded_shlibs.append (mex_file); + } - if (! mex_file) - error ("%s is not a valid shared library", file_name.c_str ()); + if (! mex_file) + error ("%s is not a valid shared library", file_name.c_str ()); - bool have_fmex = false; + bool have_fmex = false; - void *function = try_load_mex (mex_file, fcn_name, have_fmex); + 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 ()); + if (! function) + error ("failed to install .mex file function '%s'", fcn_name.c_str ()); - void *symbol = mex_file.search ("__mx_has_interleaved_complex__"); + void *symbol = mex_file.search ("__mx_has_interleaved_complex__"); - bool interleaved = symbol != nullptr; + bool interleaved = symbol != nullptr; - return new octave_mex_function (function, interleaved, have_fmex, - mex_file, fcn_name); - } + return new octave_mex_function (function, interleaved, have_fmex, + mex_file, fcn_name); +} - bool - dynamic_loader::remove_oct (const std::string& fcn_name, - dynamic_library& shl) - { - bool retval = false; +bool +dynamic_loader::remove_oct (const std::string& fcn_name, + dynamic_library& shl) +{ + bool retval = false; - // We don't need to do anything if this is called because we are in - // the process of reloading a .oct file that has changed. + // We don't need to do anything if this is called because we are in + // the process of reloading a .oct file that has changed. - if (! m_doing_load) - { - retval = shl.remove (fcn_name); + if (! m_doing_load) + { + retval = shl.remove (fcn_name); - if (shl.number_of_functions_loaded () == 0) - m_loaded_shlibs.remove (shl); - } + if (shl.number_of_functions_loaded () == 0) + m_loaded_shlibs.remove (shl); + } - return retval; - } + return retval; +} - bool - dynamic_loader::remove_mex (const std::string& fcn_name, - dynamic_library& shl) - { - // Use the same procedure as for oct files. - return remove_oct (fcn_name, shl); - } +bool +dynamic_loader::remove_mex (const std::string& fcn_name, + dynamic_library& shl) +{ + // Use the same procedure as for oct files. + return remove_oct (fcn_name, shl); +} - std::string - dynamic_loader::name_mangler (const std::string& name) - { - return 'G' + name; - } +std::string +dynamic_loader::name_mangler (const std::string& name) +{ + return 'G' + name; +} - std::string - dynamic_loader::name_uscore_mangler (const std::string& name) - { - return "_G" + name; - } +std::string +dynamic_loader::name_uscore_mangler (const std::string& name) +{ + return "_G" + name; +} - std::string - dynamic_loader::mex_mangler (const std::string&) - { - return "mexFunction"; - } +std::string +dynamic_loader::mex_mangler (const std::string&) +{ + return "mexFunction"; +} - std::string - dynamic_loader::mex_uscore_mangler (const std::string&) - { - return "_mexFunction"; - } +std::string +dynamic_loader::mex_uscore_mangler (const std::string&) +{ + return "_mexFunction"; +} - std::string - dynamic_loader::mex_f77_mangler (const std::string&) - { - return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION)); - } +std::string +dynamic_loader::mex_f77_mangler (const std::string&) +{ + return STRINGIFY (F77_FUNC (mexfunction, MEXFUNCTION)); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/dynamic-ld.h --- a/libinterp/corefcn/dynamic-ld.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/dynamic-ld.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,101 +37,101 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; + +class +dynamic_loader +{ +private: class - dynamic_loader + shlibs_list { - private: - - class - shlibs_list - { - public: - - typedef std::list::iterator iterator; - typedef std::list::const_iterator const_iterator; - - shlibs_list (void) : m_lib_list () { } - - // No copying! - - shlibs_list (const shlibs_list&) = delete; - - shlibs_list& operator = (const shlibs_list&) = delete; - - ~shlibs_list (void) = default; - - void append (const dynamic_library& shl); - - std::list remove (dynamic_library& shl); - - dynamic_library find_file (const std::string& file_name) const; - - void display (void) const; - - private: - - // List of libraries we have loaded. - std::list m_lib_list; - }; - - public: - dynamic_loader (interpreter& interp) - : m_interpreter (interp), m_loaded_shlibs (), m_doing_load (false) - { } + typedef std::list::iterator iterator; + typedef std::list::const_iterator const_iterator; + + shlibs_list (void) : m_lib_list () { } // No copying! - dynamic_loader (const dynamic_loader&) = delete; - - dynamic_loader& operator = (const dynamic_loader&) = delete; + shlibs_list (const shlibs_list&) = delete; - virtual ~dynamic_loader (void) = default; + shlibs_list& operator = (const shlibs_list&) = delete; - octave_function * - load_oct (const std::string& fcn_name, - const std::string& file_name = "", - bool relative = false); + ~shlibs_list (void) = default; - octave_function * - load_mex (const std::string& fcn_name, - const std::string& file_name = "", - bool relative = false); + void append (const dynamic_library& shl); + + std::list remove (dynamic_library& shl); - bool remove_oct (const std::string& fcn_name, - dynamic_library& shl); + dynamic_library find_file (const std::string& file_name) const; - bool remove_mex (const std::string& fcn_name, - dynamic_library& shl); + void display (void) const; private: - void clear_function (const std::string& fcn_name); + // List of libraries we have loaded. + std::list m_lib_list; + }; + - void clear (dynamic_library& oct_file); +public: - interpreter& m_interpreter; + dynamic_loader (interpreter& interp) + : m_interpreter (interp), m_loaded_shlibs (), m_doing_load (false) + { } + + // No copying! - shlibs_list m_loaded_shlibs; + dynamic_loader (const dynamic_loader&) = delete; + + dynamic_loader& operator = (const dynamic_loader&) = delete; + + virtual ~dynamic_loader (void) = default; - bool m_doing_load; + octave_function * + load_oct (const std::string& fcn_name, + const std::string& file_name = "", + bool relative = false); - static std::string name_mangler (const std::string& name); + octave_function * + load_mex (const std::string& fcn_name, + const std::string& file_name = "", + bool relative = false); - static std::string name_uscore_mangler (const std::string& name); + bool remove_oct (const std::string& fcn_name, + dynamic_library& shl); + + bool remove_mex (const std::string& fcn_name, + dynamic_library& shl); + +private: - static std::string mex_mangler (const std::string& name); + void clear_function (const std::string& fcn_name); + + void clear (dynamic_library& oct_file); - static std::string mex_uscore_mangler (const std::string& name); + interpreter& m_interpreter; + + shlibs_list m_loaded_shlibs; - static std::string mex_f77_mangler (const std::string& name); + bool m_doing_load; + + static std::string name_mangler (const std::string& name); + + static std::string name_uscore_mangler (const std::string& name); + + static std::string mex_mangler (const std::string& name); - static void * try_load_mex (dynamic_library& mex_file, - const std::string& fcn_name, bool& have_fmex); - }; + 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); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ellipj.cc --- a/libinterp/corefcn/ellipj.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ellipj.cc Thu Dec 01 20:05:44 2022 -0800 @@ -211,7 +211,7 @@ for (octave_idx_type j = 0; j < mc; j++) for (octave_idx_type i = 0; i < ur; i++) - math::ellipj (pu[i], pm[j], sn(i,j), cn(i,j), dn(i,j), err(i,j)); + math::ellipj (pu[i], pm[j], sn(i, j), cn(i, j), dn(i, j), err(i, j)); return ovl (sn, cn, dn, err); } @@ -259,7 +259,7 @@ for (octave_idx_type j = 0; j < mc; j++) for (octave_idx_type i = 0; i < ur; i++) - math::ellipj (pu[i], pm[j], sn(i,j), cn(i,j), dn(i,j), err(i,j)); + math::ellipj (pu[i], pm[j], sn(i, j), cn(i, j), dn(i, j), err(i, j)); return ovl (sn, cn, dn, err); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/environment.cc --- a/libinterp/corefcn/environment.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/environment.cc Thu Dec 01 20:05:44 2022 -0800 @@ -43,115 +43,115 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static void append_to_shell_path (const std::string& exec_path) - { - // FIXME: should there be a way to remove a previous setting from - // PATH? +static void append_to_shell_path (const std::string& exec_path) +{ + // FIXME: should there be a way to remove a previous setting from + // PATH? - if (exec_path.empty ()) - return; + if (exec_path.empty ()) + return; - // FIXME: should we really be modifying PATH in the environment? + // FIXME: should we really be modifying PATH in the environment? - std::string shell_path = sys::env::getenv ("PATH"); + std::string shell_path = sys::env::getenv ("PATH"); - if (shell_path.empty ()) - sys::env::putenv ("PATH", exec_path); - else - { - // If PATH doesn't already have exec_path, append it. - // FIXME: should we search for the elements individually, and - // only append those that are missing? + if (shell_path.empty ()) + sys::env::putenv ("PATH", exec_path); + else + { + // If PATH doesn't already have exec_path, append it. + // FIXME: should we search for the elements individually, and + // only append those that are missing? - std::string path_sep = directory_path::path_sep_str (); + std::string path_sep = directory_path::path_sep_str (); - if (shell_path.find (exec_path) == std::string::npos) - sys::env::putenv ("PATH", shell_path + path_sep + exec_path); - } - } + if (shell_path.find (exec_path) == std::string::npos) + sys::env::putenv ("PATH", shell_path + path_sep + exec_path); + } +} - octave_value - environment::editor (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_editor, args, nargout, "EDITOR", false); - } +octave_value +environment::editor (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_editor, args, nargout, "EDITOR", false); +} - octave_value - environment::exec_path (const octave_value_list& args, int nargout) - { - octave_value retval - = set_internal_variable (m_exec_path, args, nargout, "EXEC_PATH", false); +octave_value +environment::exec_path (const octave_value_list& args, int nargout) +{ + octave_value retval + = set_internal_variable (m_exec_path, args, nargout, "EXEC_PATH", false); - append_to_shell_path (m_exec_path); + append_to_shell_path (m_exec_path); - return retval; - } + return retval; +} - std::string environment::exec_path (const std::string& path) - { - std::string old_val = set (m_exec_path, path); +std::string environment::exec_path (const std::string& path) +{ + std::string old_val = set (m_exec_path, path); - append_to_shell_path (m_exec_path); + append_to_shell_path (m_exec_path); - return old_val; - } + return old_val; +} - octave_value - environment::image_path (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_image_path, args, nargout, "IMAGE_PATH", - false); - } +octave_value +environment::image_path (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_image_path, args, nargout, "IMAGE_PATH", + false); +} - std::string environment::init_editor (void) - { - std::string retval = "emacs"; +std::string environment::init_editor (void) +{ + std::string retval = "emacs"; - std::string env_editor = sys::env::getenv ("EDITOR"); + std::string env_editor = sys::env::getenv ("EDITOR"); - if (! env_editor.empty ()) - retval = env_editor; + if (! env_editor.empty ()) + retval = env_editor; - return retval; - } + return retval; +} - std::string environment::init_exec_path (void) - { - std::string exec_path = sys::env::getenv ("OCTAVE_EXEC_PATH"); +std::string environment::init_exec_path (void) +{ + std::string exec_path = sys::env::getenv ("OCTAVE_EXEC_PATH"); - std::string path_sep = directory_path::path_sep_str (); + std::string path_sep = directory_path::path_sep_str (); - if (exec_path.empty ()) - exec_path = (config::local_ver_arch_lib_dir () + path_sep - + config::local_api_arch_lib_dir () + path_sep - + config::local_arch_lib_dir () + path_sep - + config::arch_lib_dir () + path_sep - + config::bin_dir ()); + if (exec_path.empty ()) + exec_path = (config::local_ver_arch_lib_dir () + path_sep + + config::local_api_arch_lib_dir () + path_sep + + config::local_arch_lib_dir () + path_sep + + config::arch_lib_dir () + path_sep + + config::bin_dir ()); - append_to_shell_path (exec_path); + append_to_shell_path (exec_path); - return exec_path; - } + return exec_path; +} - std::string environment::init_image_path (void) - { - std::string image_path = "."; +std::string environment::init_image_path (void) +{ + std::string image_path = "."; - std::string path_sep = directory_path::path_sep_str (); + std::string path_sep = directory_path::path_sep_str (); - std::string env_path = sys::env::getenv ("OCTAVE_IMAGE_PATH"); + std::string env_path = sys::env::getenv ("OCTAVE_IMAGE_PATH"); - if (! env_path.empty ()) - image_path += path_sep + env_path; + if (! env_path.empty ()) + image_path += path_sep + env_path; - std::string gen_path = genpath (config::image_dir (), ""); + std::string gen_path = genpath (config::image_dir (), ""); - if (! gen_path.empty ()) - image_path += path_sep + gen_path; + if (! gen_path.empty ()) + image_path += path_sep + gen_path; - return image_path; - } + return image_path; +} DEFMETHOD (EDITOR, interp, args, nargout, doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/environment.h --- a/libinterp/corefcn/environment.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/environment.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,61 +35,61 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class environment - { - public: +class environment +{ +public: - environment (void) - : m_editor (init_editor ()), - m_exec_path (init_exec_path ()), - m_image_path (init_image_path ()) - { } + environment (void) + : m_editor (init_editor ()), + m_exec_path (init_exec_path ()), + m_image_path (init_image_path ()) + { } - octave_value editor (const octave_value_list& args, int nargout); + octave_value editor (const octave_value_list& args, int nargout); - std::string editor (void) const { return m_editor; } + std::string editor (void) const { return m_editor; } - std::string editor (const std::string& ed) - { - return set (m_editor, ed); - } + std::string editor (const std::string& ed) + { + return set (m_editor, ed); + } - octave_value exec_path (const octave_value_list& args, int nargout); + octave_value exec_path (const octave_value_list& args, int nargout); - std::string exec_path (void) const { return m_exec_path; } + std::string exec_path (void) const { return m_exec_path; } - std::string exec_path (const std::string& path); + std::string exec_path (const std::string& path); - octave_value image_path (const octave_value_list& args, int nargout); + octave_value image_path (const octave_value_list& args, int nargout); - std::string image_path (void) const { return m_image_path; } + std::string image_path (void) const { return m_image_path; } - std::string image_path (const std::string& path) - { - return set (m_image_path, path); - } + std::string image_path (const std::string& path) + { + return set (m_image_path, path); + } - private: +private: - std::string m_editor; + std::string m_editor; - std::string m_exec_path; + std::string m_exec_path; - std::string m_image_path; + std::string m_image_path; - static std::string init_editor (void); + static std::string init_editor (void); - static std::string init_exec_path (void); + static std::string init_exec_path (void); - static std::string init_image_path (void); + static std::string init_image_path (void); - std::string set (std::string& var, const std::string& new_val) - { - std::string old_val = var; - var = new_val; - return old_val; - } - }; + std::string set (std::string& var, const std::string& new_val) + { + std::string old_val = var; + var = new_val; + return old_val; + } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/error.cc Thu Dec 01 20:05:44 2022 -0800 @@ -235,686 +235,686 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static octave_scalar_map - init_warning_options (const std::string& state) - { - octave_scalar_map initw; +static octave_scalar_map +init_warning_options (const std::string& state) +{ + octave_scalar_map initw; - initw.setfield ("identifier", "all"); - initw.setfield ("state", state); + initw.setfield ("identifier", "all"); + initw.setfield ("state", state); - return initw; - } + return initw; +} - static octave_map - init_error_stack (interpreter& interp) - { - tree_evaluator& tw = interp.get_evaluator (); +static octave_map +init_error_stack (interpreter& interp) +{ + tree_evaluator& tw = interp.get_evaluator (); - return tw.empty_backtrace (); - } + return tw.empty_backtrace (); +} - error_system::error_system (interpreter& interp) - : m_interpreter (interp), - m_debug_on_error (false), - m_debug_on_caught (false), - m_debug_on_warning (false), - m_discard_warning_messages (false), - m_beep_on_error (false), - m_backtrace_on_warning (true), - m_verbose_warning (false), - m_quiet_warning (false), - m_warning_options (init_warning_options ("on")), - m_last_error_message (), - m_last_warning_message (), - m_last_warning_id (), - m_last_error_id (), - m_last_error_stack (init_error_stack (interp)) - { - initialize_default_warning_state (); - } +error_system::error_system (interpreter& interp) + : m_interpreter (interp), + m_debug_on_error (false), + m_debug_on_caught (false), + m_debug_on_warning (false), + m_discard_warning_messages (false), + m_beep_on_error (false), + m_backtrace_on_warning (true), + m_verbose_warning (false), + m_quiet_warning (false), + m_warning_options (init_warning_options ("on")), + m_last_error_message (), + m_last_warning_message (), + m_last_warning_id (), + m_last_error_id (), + m_last_error_stack (init_error_stack (interp)) +{ + initialize_default_warning_state (); +} - octave_value - error_system::debug_on_error (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_debug_on_error, args, nargout, - "debug_on_error"); - } +octave_value +error_system::debug_on_error (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_debug_on_error, args, nargout, + "debug_on_error"); +} - octave_value - error_system::debug_on_caught (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_debug_on_caught, args, nargout, - "debug_on_caught"); - } +octave_value +error_system::debug_on_caught (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_debug_on_caught, args, nargout, + "debug_on_caught"); +} - octave_value - error_system::debug_on_warning (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_debug_on_warning, args, nargout, - "debug_on_warning"); - } +octave_value +error_system::debug_on_warning (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_debug_on_warning, args, nargout, + "debug_on_warning"); +} - octave_value - error_system::discard_warning_messages (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_discard_warning_messages, args, nargout, - "discard_warning_messages"); - } +octave_value +error_system::discard_warning_messages (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_discard_warning_messages, args, nargout, + "discard_warning_messages"); +} - octave_value - error_system::beep_on_error (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_beep_on_error, args, nargout, - "beep_on_error"); - } +octave_value +error_system::beep_on_error (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_beep_on_error, args, nargout, + "beep_on_error"); +} - octave_value - error_system::backtrace_on_warning (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_backtrace_on_warning, args, nargout, - "backtrace_on_warning"); - } +octave_value +error_system::backtrace_on_warning (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_backtrace_on_warning, args, nargout, + "backtrace_on_warning"); +} - octave_value - error_system::verbose_warning (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_verbose_warning, args, nargout, - "verbose_warning"); - } +octave_value +error_system::verbose_warning (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_verbose_warning, args, nargout, + "verbose_warning"); +} - octave_value - error_system::quiet_warning (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_quiet_warning, args, nargout, - "quiet_warning"); - } +octave_value +error_system::quiet_warning (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_quiet_warning, args, nargout, + "quiet_warning"); +} - octave_value - error_system::last_error_message (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_last_error_message, args, nargout, - "last_error_message"); - } +octave_value +error_system::last_error_message (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_last_error_message, args, nargout, + "last_error_message"); +} - octave_value - error_system::last_warning_message (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_last_warning_message, args, nargout, - "last_warning_message"); - } +octave_value +error_system::last_warning_message (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_last_warning_message, args, nargout, + "last_warning_message"); +} - octave_value - error_system::last_warning_id (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_last_warning_id, args, nargout, - "last_warning_id"); - } +octave_value +error_system::last_warning_id (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_last_warning_id, args, nargout, + "last_warning_id"); +} - octave_value - error_system::last_error_id (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_last_error_id, args, nargout, - "last_error_id"); - } +octave_value +error_system::last_error_id (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_last_error_id, args, nargout, + "last_error_id"); +} - // Use static fields for the best efficiency. - // NOTE: C++0x will allow these two to be merged into one. - static const char *bt_fieldnames[] = - { "file", "name", "line", "column", nullptr }; +// Use static fields for the best efficiency. +// NOTE: C++0x will allow these two to be merged into one. +static const char *bt_fieldnames[] = +{ "file", "name", "line", "column", nullptr }; - static const octave_fields bt_fields (bt_fieldnames); +static const octave_fields bt_fields (bt_fieldnames); - octave_map - error_system::make_stack_map (const std::list& frames) - { - std::size_t nframes = frames.size (); +octave_map +error_system::make_stack_map (const std::list& frames) +{ + std::size_t nframes = frames.size (); - octave_map retval (dim_vector (nframes, 1), bt_fields); + octave_map retval (dim_vector (nframes, 1), bt_fields); - Cell& file = retval.contents (0); - Cell& name = retval.contents (1); - Cell& line = retval.contents (2); - Cell& column = retval.contents (3); + Cell& file = retval.contents (0); + Cell& name = retval.contents (1); + Cell& line = retval.contents (2); + Cell& column = retval.contents (3); - octave_idx_type k = 0; + octave_idx_type k = 0; - for (const auto& frm : frames) - { - file(k) = frm.file_name (); - name(k) = frm.fcn_name (); - line(k) = frm.line (); - column(k) = frm.column (); + for (const auto& frm : frames) + { + file(k) = frm.file_name (); + name(k) = frm.fcn_name (); + line(k) = frm.line (); + column(k) = frm.column (); - k++; - } + k++; + } - return retval; - } + return retval; +} - std::list - error_system::make_stack_frame_list (const octave_map& stack) - { - std::list frames; +std::list +error_system::make_stack_frame_list (const octave_map& stack) +{ + std::list frames; - Cell file = stack.contents ("file"); - Cell name = stack.contents ("name"); - Cell line = stack.contents ("line"); - Cell column = stack.contents ("column"); + Cell file = stack.contents ("file"); + Cell name = stack.contents ("name"); + Cell line = stack.contents ("line"); + Cell column = stack.contents ("column"); - octave_idx_type nel = name.numel (); + octave_idx_type nel = name.numel (); - for (octave_idx_type i = 0; i < nel; i++) - frames.push_back (frame_info (file(i).string_value (), - name(i).string_value (), - line(i).int_value (), - column(i).int_value ())); + for (octave_idx_type i = 0; i < nel; i++) + frames.push_back (frame_info (file(i).string_value (), + name(i).string_value (), + line(i).int_value (), + column(i).int_value ())); - return frames; - } + return frames; +} - // For given warning ID, return 0 if warnings are disabled, 1 if - // enabled, and 2 if the given ID should be an error instead of a - // warning. +// For given warning ID, return 0 if warnings are disabled, 1 if +// enabled, and 2 if the given ID should be an error instead of a +// warning. - int error_system::warning_enabled (const std::string& id) - { - int retval = 0; +int error_system::warning_enabled (const std::string& id) +{ + int retval = 0; - int all_state = -1; - int id_state = -1; + int all_state = -1; + int id_state = -1; - octave_map opts = warning_options (); + octave_map opts = warning_options (); - octave_idx_type nel = opts.numel (); + octave_idx_type nel = opts.numel (); - if (nel > 0) - { - Cell identifier = opts.contents ("identifier"); - Cell state = opts.contents ("state"); + if (nel > 0) + { + Cell identifier = opts.contents ("identifier"); + Cell state = opts.contents ("state"); - bool all_found = false; - bool id_found = false; + bool all_found = false; + bool id_found = false; - for (octave_idx_type i = 0; i < nel; i++) - { - octave_value ov = identifier(i); - std::string ovs = ov.string_value (); + for (octave_idx_type i = 0; i < nel; i++) + { + octave_value ov = identifier(i); + std::string ovs = ov.string_value (); - if (! all_found && ovs == "all") - { - all_state = check_state (state(i).string_value ()); + if (! all_found && ovs == "all") + { + all_state = check_state (state(i).string_value ()); - if (all_state >= 0) - all_found = true; - } + if (all_state >= 0) + all_found = true; + } - if (! id_found && ovs == id) - { - id_state = check_state (state(i).string_value ()); + if (! id_found && ovs == id) + { + id_state = check_state (state(i).string_value ()); - if (id_state >= 0) - id_found = true; - } + if (id_state >= 0) + id_found = true; + } - if (all_found && id_found) - break; - } - } + if (all_found && id_found) + break; + } + } - // If "all" is not present, assume warnings are enabled. - if (all_state == -1) - all_state = 1; + // If "all" is not present, assume warnings are enabled. + if (all_state == -1) + all_state = 1; - if (all_state == 0) - { - if (id_state >= 0) - retval = id_state; - } - else if (all_state == 1) - { - if (id_state == 0 || id_state == 2) - retval = id_state; - else - retval = all_state; - } - else if (all_state == 2) - { - if (id_state == 0) - retval= id_state; - else - retval = all_state; - } + if (all_state == 0) + { + if (id_state >= 0) + retval = id_state; + } + else if (all_state == 1) + { + if (id_state == 0 || id_state == 2) + retval = id_state; + else + retval = all_state; + } + else if (all_state == 2) + { + if (id_state == 0) + retval= id_state; + else + retval = all_state; + } - return retval; - } + return retval; +} - void error_system::vusage (const char *id, const char *fmt, va_list args) - { - std::string str_id = id ? id : ""; - std::string message = format_message (fmt, args); +void error_system::vusage (const char *id, const char *fmt, va_list args) +{ + std::string str_id = id ? id : ""; + std::string message = format_message (fmt, args); - throw_error ("usage", str_id, message); - } + throw_error ("usage", str_id, message); +} - void error_system::vwarning (const char *name, const char *id, - const char *fmt, va_list args) - { - flush_stdout (); +void error_system::vwarning (const char *name, const char *id, + const char *fmt, va_list args) +{ + flush_stdout (); - std::string base_msg = format_message (fmt, args); - std::string msg_string; + std::string base_msg = format_message (fmt, args); + std::string msg_string; - if (name) - msg_string = std::string (name) + ": "; + if (name) + msg_string = std::string (name) + ": "; - msg_string += base_msg; + msg_string += base_msg; - bool fmt_suppresses_backtrace = false; - std::size_t fmt_len = (fmt ? strlen (fmt) : 0); - fmt_suppresses_backtrace = (fmt_len > 0 && fmt[fmt_len-1] == '\n'); + bool fmt_suppresses_backtrace = false; + std::size_t fmt_len = (fmt ? strlen (fmt) : 0); + fmt_suppresses_backtrace = (fmt_len > 0 && fmt[fmt_len-1] == '\n'); - if (! fmt_suppresses_backtrace) - msg_string += '\n'; + if (! fmt_suppresses_backtrace) + msg_string += '\n'; - last_warning_id (id); - last_warning_message (base_msg); + last_warning_id (id); + last_warning_message (base_msg); - if (discard_warning_messages ()) - return; + if (discard_warning_messages ()) + return; - tree_evaluator& tw = m_interpreter.get_evaluator (); + tree_evaluator& tw = m_interpreter.get_evaluator (); - bool in_user_code = tw.in_user_code (); + bool in_user_code = tw.in_user_code (); - if (! quiet_warning ()) - { - octave_diary << msg_string; - std::cerr << msg_string; + if (! quiet_warning ()) + { + octave_diary << msg_string; + std::cerr << msg_string; - if (! fmt_suppresses_backtrace && in_user_code - && backtrace_on_warning () - && ! discard_warning_messages ()) - { - std::string bt_msg = tw.backtrace_message (); + if (! fmt_suppresses_backtrace && in_user_code + && backtrace_on_warning () + && ! discard_warning_messages ()) + { + std::string bt_msg = tw.backtrace_message (); - if (! bt_msg.empty ()) - bt_msg = "warning: called from\n" + bt_msg; + if (! bt_msg.empty ()) + bt_msg = "warning: called from\n" + bt_msg; - octave_diary << bt_msg << std::endl; - std::cerr << bt_msg << std::endl; - } - } + octave_diary << bt_msg << std::endl; + std::cerr << bt_msg << std::endl; + } + } - bp_table& bptab = tw.get_bp_table (); + bp_table& bptab = tw.get_bp_table (); - if ((m_interpreter.interactive () - || application::forced_interactive ()) - && debug_on_warning () && in_user_code && bptab.debug_on_warn (id)) - { - unwind_protect_var restore_var (m_debug_on_warning, false); + if ((m_interpreter.interactive () + || application::forced_interactive ()) + && debug_on_warning () && in_user_code && bptab.debug_on_warn (id)) + { + unwind_protect_var restore_var (m_debug_on_warning, false); - tw.enter_debugger (); - } - } + tw.enter_debugger (); + } +} - void error_system::error_1 (execution_exception& ee, const char *id, - const char *fmt, va_list args) - { - ee.set_identifier (id); - ee.set_message (format_message (fmt, args)); +void error_system::error_1 (execution_exception& ee, const char *id, + const char *fmt, va_list args) +{ + ee.set_identifier (id); + ee.set_message (format_message (fmt, args)); - throw_error (ee); - } + throw_error (ee); +} - void error_system::error_1 (const char *id, const char *fmt, - va_list args) - { - std::string message = format_message (fmt, args); +void error_system::error_1 (const char *id, const char *fmt, + va_list args) +{ + std::string message = format_message (fmt, args); - std::list stack_info; + std::list stack_info; - throw_error ("error", id, message); - } + throw_error ("error", id, message); +} - void error_system::vwarning (const char *id, const char *fmt, va_list args) - { - int warn_opt = warning_enabled (id); +void error_system::vwarning (const char *id, const char *fmt, va_list args) +{ + int warn_opt = warning_enabled (id); - if (warn_opt == 2) - { - // Handle this warning as an error. + if (warn_opt == 2) + { + // Handle this warning as an error. - error_1 (id, fmt, args); - } - else if (warn_opt == 1) - vwarning ("warning", id, fmt, args); - } + error_1 (id, fmt, args); + } + else if (warn_opt == 1) + vwarning ("warning", id, fmt, args); +} - void error_system::rethrow_error (const std::string& id, - const std::string& msg, - const octave_map& stack) - { - std::list stack_info; +void error_system::rethrow_error (const std::string& id, + const std::string& msg, + const octave_map& stack) +{ + std::list stack_info; - execution_exception ee ("error", id, msg, stack_info); + execution_exception ee ("error", id, msg, stack_info); - if (! stack.isempty ()) - { - if (! (stack.contains ("file") && stack.contains ("name") - && stack.contains ("line"))) - error ("rethrow: STACK struct must contain the fields 'file', 'name', and 'line'"); + if (! stack.isempty ()) + { + if (! (stack.contains ("file") && stack.contains ("name") + && stack.contains ("line"))) + error ("rethrow: STACK struct must contain the fields 'file', 'name', and 'line'"); - if (! stack.contains ("column")) - { - octave_map new_stack = stack; + if (! stack.contains ("column")) + { + octave_map new_stack = stack; - new_stack.setfield ("column", Cell (octave_value (-1))); + new_stack.setfield ("column", Cell (octave_value (-1))); - ee.set_stack_info (make_stack_frame_list (new_stack)); - } - else - ee.set_stack_info (make_stack_frame_list (stack)); - } + ee.set_stack_info (make_stack_frame_list (new_stack)); + } + else + ee.set_stack_info (make_stack_frame_list (stack)); + } - throw_error (ee); - } + throw_error (ee); +} - void error_system::vpanic (const char *fmt, va_list args) - { - // Is there any point in trying to write the panic message to the - // diary? +void error_system::vpanic (const char *fmt, va_list args) +{ + // Is there any point in trying to write the panic message to the + // diary? - std::cerr << "panic: " << format_message (fmt, args) << std::endl; + std::cerr << "panic: " << format_message (fmt, args) << std::endl; - abort (); - } + abort (); +} - void error_system::panic (const char *fmt, ...) - { - va_list args; - va_start (args, fmt); - vpanic (fmt, args); - va_end (args); - } +void error_system::panic (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + vpanic (fmt, args); + va_end (args); +} - octave_scalar_map error_system::warning_query (const std::string& id_arg) - { - octave_scalar_map retval; +octave_scalar_map error_system::warning_query (const std::string& id_arg) +{ + octave_scalar_map retval; - std::string id = id_arg; + std::string id = id_arg; - if (id == "last") - id = last_warning_id (); + if (id == "last") + id = last_warning_id (); - octave_map opts = warning_options (); + octave_map opts = warning_options (); - Cell ident = opts.contents ("identifier"); - Cell state = opts.contents ("state"); + Cell ident = opts.contents ("identifier"); + Cell state = opts.contents ("state"); - octave_idx_type nel = ident.numel (); + octave_idx_type nel = ident.numel (); - panic_if (nel == 0); + panic_if (nel == 0); - bool found = false; + bool found = false; - std::string val; + std::string val; - for (octave_idx_type i = 0; i < nel; i++) - { - if (ident(i).string_value () == id) - { - val = state(i).string_value (); - found = true; - break; - } - } + for (octave_idx_type i = 0; i < nel; i++) + { + if (ident(i).string_value () == id) + { + val = state(i).string_value (); + found = true; + break; + } + } - if (! found) - { - for (octave_idx_type i = 0; i < nel; i++) - { - if (ident(i).string_value () == "all") - { - val = state(i).string_value (); - found = true; - break; - } - } - } + if (! found) + { + for (octave_idx_type i = 0; i < nel; i++) + { + if (ident(i).string_value () == "all") + { + val = state(i).string_value (); + found = true; + break; + } + } + } - // The warning state "all" is always supposed to remain in the list, - // so we should always find a state, either explicitly or by using the - // state for "all". - panic_unless (found); + // The warning state "all" is always supposed to remain in the list, + // so we should always find a state, either explicitly or by using the + // state for "all". + panic_unless (found); - retval.assign ("identifier", id); - retval.assign ("state", val); + retval.assign ("identifier", id); + retval.assign ("state", val); - return retval; - } + return retval; +} - std::string error_system::default_warning_state (void) - { - std::string retval = "on"; +std::string error_system::default_warning_state (void) +{ + std::string retval = "on"; - octave_map opts = warning_options (); + octave_map opts = warning_options (); - Cell ident = opts.contents ("identifier"); - Cell state = opts.contents ("state"); + Cell ident = opts.contents ("identifier"); + Cell state = opts.contents ("state"); - octave_idx_type nel = ident.numel (); + octave_idx_type nel = ident.numel (); - for (octave_idx_type i = 0; i < nel; i++) - { - if (ident(i).string_value () == "all") - { - retval = state(i).string_value (); - break; - } - } + for (octave_idx_type i = 0; i < nel; i++) + { + if (ident(i).string_value () == "all") + { + retval = state(i).string_value (); + break; + } + } - return retval; - } + return retval; +} - void error_system::display_warning_options (std::ostream& os) - { - octave_map opts = warning_options (); +void error_system::display_warning_options (std::ostream& os) +{ + octave_map opts = warning_options (); - Cell ident = opts.contents ("identifier"); - Cell state = opts.contents ("state"); + Cell ident = opts.contents ("identifier"); + Cell state = opts.contents ("state"); - octave_idx_type nel = ident.numel (); + octave_idx_type nel = ident.numel (); - std::string all_state = default_warning_state (); + std::string all_state = default_warning_state (); - if (all_state == "on") - os << "By default, warnings are enabled."; - else if (all_state == "off") - os << "By default, warnings are disabled."; - else if (all_state == "error") - os << "By default, warnings are treated as errors."; - else - panic_impossible (); + if (all_state == "on") + os << "By default, warnings are enabled."; + else if (all_state == "off") + os << "By default, warnings are disabled."; + else if (all_state == "error") + os << "By default, warnings are treated as errors."; + else + panic_impossible (); - if (nel > 1) - { - os << "\n"; - os << "Non-default warning states are:\n\n"; - os << " State Warning ID\n"; - } + if (nel > 1) + { + 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++) - { - std::string tid = ident(i).string_value (); - std::string tst = state(i).string_value (); + for (octave_idx_type i = 1; i < nel; i++) + { + std::string tid = ident(i).string_value (); + std::string tst = state(i).string_value (); - os << std::setw (7) << tst << " " << tid << "\n"; - } + os << std::setw (7) << tst << " " << tid << "\n"; + } - os << std::endl; - } + os << std::endl; +} - void error_system::set_warning_option (const std::string& state, - const std::string& ident) - { - std::string all_state = default_warning_state (); +void error_system::set_warning_option (const std::string& state, + const std::string& ident) +{ + std::string all_state = default_warning_state (); - if (state != "on" && state != "off" && state != "error") - error ("invalid warning state: %s", state.c_str ()); + if (state != "on" && state != "off" && state != "error") + error ("invalid warning state: %s", state.c_str ()); - octave_map opts = warning_options (); + octave_map opts = warning_options (); - Cell tid = opts.contents ("identifier"); - Cell tst = opts.contents ("state"); + Cell tid = opts.contents ("identifier"); + Cell tst = opts.contents ("state"); - octave_idx_type nel = tid.numel (); + octave_idx_type nel = tid.numel (); - for (octave_idx_type i = 0; i < nel; i++) - { - if (tid(i).string_value () == ident) - { - // We found it in the current list of options. If the state - // for "all" is same as arg1, we can simply remove the item - // from the list. + for (octave_idx_type i = 0; i < nel; i++) + { + if (tid(i).string_value () == ident) + { + // We found it in the current list of options. If the state + // for "all" is same as arg1, we can simply remove the item + // from the list. - if (state == all_state && ident != "all") - { - for (i = i + 1; i < nel; i++) - { - tid(i-1) = tid(i); - tst(i-1) = tst(i); - } + if (state == all_state && ident != "all") + { + for (i = i + 1; i < nel; i++) + { + tid(i-1) = tid(i); + tst(i-1) = tst(i); + } - tid.resize (dim_vector (1, nel-1)); - tst.resize (dim_vector (1, nel-1)); - } - else - tst(i) = state; + tid.resize (dim_vector (1, nel-1)); + tst.resize (dim_vector (1, nel-1)); + } + else + tst(i) = state; - opts.clear (); + opts.clear (); - opts.assign ("identifier", tid); - opts.assign ("state", tst); + opts.assign ("identifier", tid); + opts.assign ("state", tst); - warning_options (opts); + warning_options (opts); - return; - } - } + return; + } + } - // The option wasn't already in the list. Append it. + // The option wasn't already in the list. Append it. - tid.resize (dim_vector (1, nel+1)); - tst.resize (dim_vector (1, nel+1)); + tid.resize (dim_vector (1, nel+1)); + tst.resize (dim_vector (1, nel+1)); - tid(nel) = ident; - tst(nel) = state; + tid(nel) = ident; + tst(nel) = state; - opts.clear (); + opts.clear (); - opts.assign ("identifier", tid); - opts.assign ("state", tst); + opts.assign ("identifier", tid); + opts.assign ("state", tst); - warning_options (opts); - } + warning_options (opts); +} - void error_system::disable_warning (const std::string& id) - { - set_warning_option ("off", id); - } +void error_system::disable_warning (const std::string& id) +{ + set_warning_option ("off", id); +} - void error_system::initialize_default_warning_state (void) - { - warning_options (init_warning_options ("on")); +void error_system::initialize_default_warning_state (void) +{ + warning_options (init_warning_options ("on")); - // Most people will want to have the following disabled. + // Most people will want to have the following disabled. - disable_warning ("Octave:array-as-logical"); - disable_warning ("Octave:array-to-scalar"); - disable_warning ("Octave:array-to-vector"); - disable_warning ("Octave:imag-to-real"); - disable_warning ("Octave:language-extension"); - disable_warning ("Octave:missing-semicolon"); - disable_warning ("Octave:neg-dim-as-zero"); - disable_warning ("Octave:separator-insert"); - disable_warning ("Octave:single-quote-string"); - disable_warning ("Octave:str-to-num"); - disable_warning ("Octave:mixed-string-concat"); - disable_warning ("Octave:variable-switch-label"); - } + disable_warning ("Octave:array-as-logical"); + disable_warning ("Octave:array-to-scalar"); + disable_warning ("Octave:array-to-vector"); + disable_warning ("Octave:imag-to-real"); + disable_warning ("Octave:language-extension"); + disable_warning ("Octave:missing-semicolon"); + disable_warning ("Octave:neg-dim-as-zero"); + disable_warning ("Octave:separator-insert"); + disable_warning ("Octave:single-quote-string"); + disable_warning ("Octave:str-to-num"); + disable_warning ("Octave:mixed-string-concat"); + disable_warning ("Octave:variable-switch-label"); +} - void error_system::interpreter_try (unwind_protect& frame) - { - frame.protect_var (m_debug_on_error); - m_debug_on_error = false; +void error_system::interpreter_try (unwind_protect& frame) +{ + frame.protect_var (m_debug_on_error); + m_debug_on_error = false; - frame.protect_var (m_debug_on_warning); - m_debug_on_warning = false; + frame.protect_var (m_debug_on_warning); + m_debug_on_warning = false; - // Leave debug_on_caught as it was, so errors in try/catch are still - // caught. - } + // Leave debug_on_caught as it was, so errors in try/catch are still + // caught. +} - void error_system::throw_error (const std::string& err_type, - const std::string& id, - const std::string& message, - const std::list& stack_info_arg) - { - std::list stack_info = stack_info_arg; +void error_system::throw_error (const std::string& err_type, + const std::string& id, + const std::string& message, + const std::list& stack_info_arg) +{ + std::list stack_info = stack_info_arg; - if (stack_info.empty ()) - { - tree_evaluator& tw = m_interpreter.get_evaluator (); + if (stack_info.empty ()) + { + tree_evaluator& tw = m_interpreter.get_evaluator (); - stack_info = tw.backtrace_info (); + stack_info = tw.backtrace_info (); - // Print the error message only if it is different from the - // previous one; makes the output more concise and readable. + // Print the error message only if it is different from the + // previous one; makes the output more concise and readable. - stack_info.unique (); - } + stack_info.unique (); + } - execution_exception ex (err_type, id, message, stack_info); + execution_exception ex (err_type, id, message, stack_info); - throw_error (ex); - } + throw_error (ex); +} - void error_system::throw_error (execution_exception& ex) - { - throw ex; - } +void error_system::throw_error (execution_exception& ex) +{ + throw ex; +} - void error_system::save_exception (const execution_exception& ee) - { - last_error_id (ee.identifier ()); - std::string message = ee.message (); - std::string xmsg - = (message.size () > 0 && message.back () == '\n' - ? message.substr (0, message.size () - 1) : message); - last_error_message (xmsg); - last_error_stack (make_stack_map (ee.stack_info ())); - } +void error_system::save_exception (const execution_exception& ee) +{ + last_error_id (ee.identifier ()); + std::string message = ee.message (); + std::string xmsg + = (message.size () > 0 && message.back () == '\n' + ? message.substr (0, message.size () - 1) : message); + last_error_message (xmsg); + last_error_stack (make_stack_map (ee.stack_info ())); +} - void error_system::display_exception (const execution_exception& ee) const - { - // FIXME: How should we handle beep_on_error? +void error_system::display_exception (const execution_exception& ee) const +{ + // FIXME: How should we handle beep_on_error? - ee.display (octave_diary); + ee.display (octave_diary); - // FIXME: Handle display using an event manager message so that the - // GUI or other client can receive error messages without needing to - // capture them from std::cerr or some other stream. + // FIXME: Handle display using an event manager message so that the + // GUI or other client can receive error messages without needing to + // capture them from std::cerr or some other stream. - event_manager& evmgr = m_interpreter.get_event_manager (); + event_manager& evmgr = m_interpreter.get_event_manager (); - evmgr.display_exception (ee, m_beep_on_error); - } + evmgr.display_exception (ee, m_beep_on_error); +} OCTAVE_END_NAMESPACE(octave) @@ -1683,8 +1683,8 @@ octave_scalar_map tmp = es.warning_query (arg2); octave_stdout << '"' << arg2 << R"(" warning state is ")" << - tmp.getfield ("state").string_value () << - "\"\n"; + tmp.getfield ("state").string_value () << + "\"\n"; } } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/error.h --- a/libinterp/corefcn/error.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/error.h Thu Dec 01 20:05:44 2022 -0800 @@ -42,358 +42,358 @@ class execution_exception; - class error_system - { - public: +class error_system +{ +public: - OCTINTERP_API error_system (interpreter& interp); + OCTINTERP_API error_system (interpreter& interp); - error_system (const error_system&) = delete; + error_system (const error_system&) = delete; - error_system& operator = (const error_system&) = delete; + error_system& operator = (const error_system&) = delete; - ~error_system (void) = default; + ~error_system (void) = default; - OCTINTERP_API octave_value - debug_on_error (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + debug_on_error (const octave_value_list& args, int nargout); - void set_debug_on_error (bool flag) { m_debug_on_error = flag; } + void set_debug_on_error (bool flag) { m_debug_on_error = flag; } - bool debug_on_error (void) const { return m_debug_on_error; } + bool debug_on_error (void) const { return m_debug_on_error; } - bool debug_on_error (bool flag) - { - bool val = m_debug_on_error; - m_debug_on_error = flag; - return val; - } + bool debug_on_error (bool flag) + { + bool val = m_debug_on_error; + m_debug_on_error = flag; + return val; + } - OCTINTERP_API octave_value - debug_on_caught (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + debug_on_caught (const octave_value_list& args, int nargout); - void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; } + void set_debug_on_caught (bool flag) { m_debug_on_caught = flag; } - bool debug_on_caught (void) const { return m_debug_on_caught; } + bool debug_on_caught (void) const { return m_debug_on_caught; } - bool debug_on_caught (bool flag) - { - bool val = m_debug_on_caught; - m_debug_on_caught = flag; - return val; - } + bool debug_on_caught (bool flag) + { + bool val = m_debug_on_caught; + m_debug_on_caught = flag; + return val; + } - OCTINTERP_API octave_value - debug_on_warning (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + debug_on_warning (const octave_value_list& args, int nargout); - void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; } + void set_debug_on_warning (bool flag) { m_debug_on_warning = flag; } - bool debug_on_warning (void) const { return m_debug_on_warning; } + bool debug_on_warning (void) const { return m_debug_on_warning; } - bool debug_on_warning (bool flag) - { - bool val = m_debug_on_warning; - m_debug_on_warning = flag; - return val; - } + bool debug_on_warning (bool flag) + { + bool val = m_debug_on_warning; + m_debug_on_warning = flag; + return val; + } - OCTINTERP_API octave_value - discard_warning_messages (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + discard_warning_messages (const octave_value_list& args, int nargout); - void set_discard_warning_messages (bool flag) - { - m_discard_warning_messages = flag; - } + void set_discard_warning_messages (bool flag) + { + m_discard_warning_messages = flag; + } - bool discard_warning_messages (void) const - { - return m_discard_warning_messages; - } + bool discard_warning_messages (void) const + { + return m_discard_warning_messages; + } - bool discard_warning_messages (bool flag) - { - bool val = m_discard_warning_messages; - m_discard_warning_messages = flag; - return val; - } + bool discard_warning_messages (bool flag) + { + bool val = m_discard_warning_messages; + m_discard_warning_messages = flag; + return val; + } - OCTINTERP_API octave_value - beep_on_error (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + beep_on_error (const octave_value_list& args, int nargout); - void set_beep_on_error (bool flag) { m_beep_on_error = flag; } + void set_beep_on_error (bool flag) { m_beep_on_error = flag; } - bool beep_on_error (void) const { return m_beep_on_error; } + bool beep_on_error (void) const { return m_beep_on_error; } - bool beep_on_error (bool flag) - { - bool val = m_beep_on_error; - m_beep_on_error = flag; - return val; - } + bool beep_on_error (bool flag) + { + bool val = m_beep_on_error; + m_beep_on_error = flag; + return val; + } - OCTINTERP_API octave_value - backtrace_on_warning (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + backtrace_on_warning (const octave_value_list& args, int nargout); - void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; } + void set_backtrace_on_warning (bool flag) { m_backtrace_on_warning = flag; } - bool backtrace_on_warning (void) const { return m_backtrace_on_warning; } + bool backtrace_on_warning (void) const { return m_backtrace_on_warning; } - bool backtrace_on_warning (bool flag) - { - bool val = m_backtrace_on_warning; - m_backtrace_on_warning = flag; - return val; - } + bool backtrace_on_warning (bool flag) + { + bool val = m_backtrace_on_warning; + m_backtrace_on_warning = flag; + return val; + } - OCTINTERP_API octave_value - verbose_warning (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + verbose_warning (const octave_value_list& args, int nargout); - void set_verbose_warning (bool flag) { m_verbose_warning = flag; } + void set_verbose_warning (bool flag) { m_verbose_warning = flag; } - bool verbose_warning (void) const { return m_verbose_warning; } + bool verbose_warning (void) const { return m_verbose_warning; } - bool verbose_warning (bool flag) - { - bool val = m_verbose_warning; - m_verbose_warning = flag; - return val; - } + bool verbose_warning (bool flag) + { + bool val = m_verbose_warning; + m_verbose_warning = flag; + return val; + } - OCTINTERP_API octave_value - quiet_warning (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + quiet_warning (const octave_value_list& args, int nargout); - void set_quiet_warning (bool flag) { m_quiet_warning = flag; } + void set_quiet_warning (bool flag) { m_quiet_warning = flag; } - bool quiet_warning (void) const { return m_quiet_warning; } + bool quiet_warning (void) const { return m_quiet_warning; } - bool quiet_warning (bool flag) - { - bool val = m_quiet_warning; - m_quiet_warning = flag; - return val; - } + bool quiet_warning (bool flag) + { + bool val = m_quiet_warning; + m_quiet_warning = flag; + return val; + } - octave_map warning_options (void) const { return m_warning_options; } + octave_map warning_options (void) const { return m_warning_options; } - void set_warning_options (const octave_map& val) - { m_warning_options = val; } + void set_warning_options (const octave_map& val) + { m_warning_options = val; } - octave_map warning_options (const octave_map& new_val) - { - octave_map val = m_warning_options; - m_warning_options = new_val; - return val; - } + octave_map warning_options (const octave_map& new_val) + { + octave_map val = m_warning_options; + m_warning_options = new_val; + return val; + } - OCTINTERP_API octave_value - last_error_message (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + last_error_message (const octave_value_list& args, int nargout); - void set_last_error_message (const std::string& val) - { m_last_error_message = val; } + void set_last_error_message (const std::string& val) + { m_last_error_message = val; } - std::string last_error_message (void) const { return m_last_error_message; } + std::string last_error_message (void) const { return m_last_error_message; } - std::string last_error_message (const std::string& s) - { - std::string val = m_last_error_message; - m_last_error_message = s; - return val; - } + std::string last_error_message (const std::string& s) + { + std::string val = m_last_error_message; + m_last_error_message = s; + return val; + } - OCTINTERP_API octave_value - last_warning_message (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + last_warning_message (const octave_value_list& args, int nargout); - void set_last_warning_message (const std::string& val) - { m_last_warning_message = val; } + void set_last_warning_message (const std::string& val) + { m_last_warning_message = val; } - std::string last_warning_message (void) const - { return m_last_warning_message; } + std::string last_warning_message (void) const + { return m_last_warning_message; } - std::string last_warning_message (const std::string& s) - { - std::string val = m_last_warning_message; - m_last_warning_message = s; - return val; - } + std::string last_warning_message (const std::string& s) + { + std::string val = m_last_warning_message; + m_last_warning_message = s; + return val; + } - OCTINTERP_API octave_value - last_warning_id (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + last_warning_id (const octave_value_list& args, int nargout); - void set_last_warning_id (const std::string& val) - { m_last_warning_id = val; } + void set_last_warning_id (const std::string& val) + { m_last_warning_id = val; } - std::string last_warning_id (void) const { return m_last_warning_id; } + std::string last_warning_id (void) const { return m_last_warning_id; } - std::string last_warning_id (const std::string& s) - { - std::string val = m_last_warning_id; - m_last_warning_id = s; - return val; - } + std::string last_warning_id (const std::string& s) + { + std::string val = m_last_warning_id; + m_last_warning_id = s; + return val; + } - OCTINTERP_API octave_value - last_error_id (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + last_error_id (const octave_value_list& args, int nargout); - void set_last_error_id (const std::string& val) { m_last_error_id = val; } + void set_last_error_id (const std::string& val) { m_last_error_id = val; } - std::string last_error_id (void) const { return m_last_error_id; } + std::string last_error_id (void) const { return m_last_error_id; } - std::string last_error_id (const std::string& s) - { - std::string val = m_last_error_id; - m_last_error_id = s; - return val; - } + std::string last_error_id (const std::string& s) + { + std::string val = m_last_error_id; + m_last_error_id = s; + return val; + } - void set_last_error_stack (const octave_map& val) - { - m_last_error_stack = val; - } + void set_last_error_stack (const octave_map& val) + { + m_last_error_stack = val; + } - octave_map last_error_stack (void) const { return m_last_error_stack; } + octave_map last_error_stack (void) const { return m_last_error_stack; } - octave_map last_error_stack (const octave_map& new_val) - { - octave_map val = m_last_error_stack; - m_last_error_stack = new_val; - return val; - } + octave_map last_error_stack (const octave_map& new_val) + { + octave_map val = m_last_error_stack; + m_last_error_stack = new_val; + return val; + } - static OCTINTERP_API octave_map - make_stack_map (const std::list& frames); + static OCTINTERP_API octave_map + make_stack_map (const std::list& frames); - static OCTINTERP_API std::list - make_stack_frame_list (const octave_map& stack); + static OCTINTERP_API std::list + make_stack_frame_list (const octave_map& stack); - //! For given warning ID, return 0 if warnings are disabled, 1 if - //! enabled, and 2 if the given ID should be an error instead of a - //! warning. + //! For given warning ID, return 0 if warnings are disabled, 1 if + //! enabled, and 2 if the given ID should be an error instead of a + //! warning. - OCTINTERP_API int warning_enabled (const std::string& id); + OCTINTERP_API int warning_enabled (const std::string& id); - OCTINTERP_API void - verror (bool save_last_error, std::ostream& os, const char *name, - const char *id, const char *fmt, va_list args, - bool with_cfn = false); + OCTINTERP_API void + verror (bool save_last_error, std::ostream& os, const char *name, + const char *id, const char *fmt, va_list args, + bool with_cfn = false); - OCTINTERP_API void - vwarning (const char *name, const char *id, const char *fmt, - va_list args); + OCTINTERP_API void + vwarning (const char *name, const char *id, const char *fmt, + va_list args); - OCTAVE_NORETURN - OCTINTERP_API void - error_1 (execution_exception& ee, const char *id, const char *fmt, - va_list args); + OCTAVE_NORETURN + OCTINTERP_API void + error_1 (execution_exception& ee, const char *id, const char *fmt, + va_list args); - OCTAVE_NORETURN - OCTINTERP_API void error_1 (const char *id, const char *fmt, va_list args); + OCTAVE_NORETURN + OCTINTERP_API void error_1 (const char *id, const char *fmt, va_list args); - OCTAVE_NORETURN - OCTINTERP_API void vusage (const char *id, const char *fmt, va_list args); + OCTAVE_NORETURN + OCTINTERP_API void vusage (const char *id, const char *fmt, va_list args); - OCTINTERP_API void vwarning (const char *id, const char *fmt, va_list args); + OCTINTERP_API void vwarning (const char *id, const char *fmt, va_list args); - OCTAVE_NORETURN - OCTINTERP_API void - rethrow_error (const std::string& id, const std::string& msg, - const octave_map& stack); + OCTAVE_NORETURN + OCTINTERP_API void + rethrow_error (const std::string& id, const std::string& msg, + const octave_map& stack); - OCTAVE_NORETURN - OCTINTERP_API void vpanic (const char *fmt, va_list args); + OCTAVE_NORETURN + OCTINTERP_API void vpanic (const char *fmt, va_list args); - OCTAVE_NORETURN - OCTINTERP_API void panic (const char *fmt, ...); + OCTAVE_NORETURN + OCTINTERP_API void panic (const char *fmt, ...); - OCTINTERP_API octave_scalar_map warning_query (const std::string& id_arg); + OCTINTERP_API octave_scalar_map warning_query (const std::string& id_arg); - OCTINTERP_API std::string default_warning_state (void); + OCTINTERP_API std::string default_warning_state (void); - OCTINTERP_API void display_warning_options (std::ostream& os); + OCTINTERP_API void display_warning_options (std::ostream& os); - OCTINTERP_API void - set_warning_option (const std::string& state, const std::string& id); + OCTINTERP_API void + set_warning_option (const std::string& state, const std::string& id); - OCTINTERP_API void disable_warning (const std::string& id); + OCTINTERP_API void disable_warning (const std::string& id); - OCTINTERP_API void initialize_default_warning_state (void); + OCTINTERP_API void initialize_default_warning_state (void); - OCTINTERP_API void interpreter_try (unwind_protect& frame); + OCTINTERP_API void interpreter_try (unwind_protect& frame); - // Throw execution_exception or, if debug_on_error is TRUE, enter - // debugger. If stack_info is empty, use current call stack. + // Throw execution_exception or, if debug_on_error is TRUE, enter + // debugger. If stack_info is empty, use current call stack. - OCTAVE_NORETURN - OCTINTERP_API void - throw_error (const std::string& err_type, - const std::string& id, - const std::string& message, - const std::list& stack_info - = std::list ()); + OCTAVE_NORETURN + OCTINTERP_API void + throw_error (const std::string& err_type, + const std::string& id, + const std::string& message, + const std::list& stack_info + = std::list ()); - OCTAVE_NORETURN - OCTINTERP_API void throw_error (execution_exception& ee); + OCTAVE_NORETURN + OCTINTERP_API void throw_error (execution_exception& ee); - OCTINTERP_API void save_exception (const execution_exception& ee); + OCTINTERP_API void save_exception (const execution_exception& ee); - OCTINTERP_API void display_exception (const execution_exception& ee) const; + OCTINTERP_API void display_exception (const execution_exception& ee) const; - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - //! TRUE means that Octave will try to enter the debugger when an error - //! is encountered. This will also inhibit printing of the normal - //! traceback message (you will only see the top-level error message). + //! TRUE means that Octave will try to enter the debugger when an error + //! is encountered. This will also inhibit printing of the normal + //! traceback message (you will only see the top-level error message). - bool m_debug_on_error; + bool m_debug_on_error; - //! TRUE means that Octave will try to enter the debugger when an error - //! is encountered within the 'try' section of a 'try' / 'catch' block. + //! TRUE means that Octave will try to enter the debugger when an error + //! is encountered within the 'try' section of a 'try' / 'catch' block. - bool m_debug_on_caught; + bool m_debug_on_caught; - //! TRUE means that Octave will try to enter the debugger when a warning - //! is encountered. + //! TRUE means that Octave will try to enter the debugger when a warning + //! is encountered. - bool m_debug_on_warning; + bool m_debug_on_warning; - //! TRUE means warning messages are turned off. + //! TRUE means warning messages are turned off. - bool m_discard_warning_messages; + bool m_discard_warning_messages; - //! TRUE means that Octave will try to beep obnoxiously before - //! printing error messages. - bool m_beep_on_error; + //! TRUE means that Octave will try to beep obnoxiously before + //! printing error messages. + bool m_beep_on_error; - //! TRUE means that Octave will try to display a stack trace when a - //! warning is encountered. - bool m_backtrace_on_warning; + //! TRUE means that Octave will try to display a stack trace when a + //! warning is encountered. + bool m_backtrace_on_warning; - //! TRUE means that Octave will print a verbose warning. Currently - //! unused. - bool m_verbose_warning; + //! TRUE means that Octave will print a verbose warning. Currently + //! unused. + bool m_verbose_warning; - //! TRUE means that Octave will print no warnings, but lastwarn will - //! be updated - bool m_quiet_warning; + //! TRUE means that Octave will print no warnings, but lastwarn will + //! be updated + bool m_quiet_warning; - //! A structure containing (most of) the current state of warnings. - octave_map m_warning_options; + //! A structure containing (most of) the current state of warnings. + octave_map m_warning_options; - //! The text of the last error message. - std::string m_last_error_message; + //! The text of the last error message. + std::string m_last_error_message; - //! The text of the last warning message. - std::string m_last_warning_message; + //! The text of the last warning message. + std::string m_last_warning_message; - //! The last warning message id. - std::string m_last_warning_id; + //! The last warning message id. + std::string m_last_warning_id; - //! The last error message id. - std::string m_last_error_id; + //! The last error message id. + std::string m_last_error_id; - //! The last file in which an error occurred. - octave_map m_last_error_stack; - }; + //! The last file in which an error occurred. + octave_map m_last_error_stack; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/errwarn.h --- a/libinterp/corefcn/errwarn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/errwarn.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,7 +35,7 @@ class octave_value; OCTAVE_BEGIN_NAMESPACE(octave) - class execution_exception; +class execution_exception; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/event-manager.cc --- a/libinterp/corefcn/event-manager.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/event-manager.cc Thu Dec 01 20:05:44 2022 -0800 @@ -46,148 +46,148 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static int readline_event_hook (void) - { - event_manager& evmgr = __get_event_manager__ (); +static int readline_event_hook (void) +{ + event_manager& evmgr = __get_event_manager__ (); - evmgr.process_events (); + evmgr.process_events (); - return 0; - } + return 0; +} - void interpreter_events::display_exception (const execution_exception& ee, - bool beep) - { - if (beep) - std::cerr << "\a"; +void interpreter_events::display_exception (const execution_exception& ee, + bool beep) +{ + if (beep) + std::cerr << "\a"; - ee.display (std::cerr); - } + ee.display (std::cerr); +} - event_manager::event_manager (interpreter& interp) - : m_event_queue_mutex (new mutex ()), m_gui_event_queue (), - m_debugging (false), m_link_enabled (true), - m_interpreter (interp), m_instance (new interpreter_events ()), - m_qt_event_handlers () - { - push_event_queue (); - command_editor::add_event_hook (readline_event_hook); - } +event_manager::event_manager (interpreter& interp) + : m_event_queue_mutex (new mutex ()), m_gui_event_queue (), + m_debugging (false), m_link_enabled (true), + m_interpreter (interp), m_instance (new interpreter_events ()), + m_qt_event_handlers () +{ + push_event_queue (); + command_editor::add_event_hook (readline_event_hook); +} - event_manager::~event_manager (void) - { - delete m_event_queue_mutex; - } +event_manager::~event_manager (void) +{ + delete m_event_queue_mutex; +} - // Programming Note: It is possible to disable the link without deleting - // the connection. This allows it to be temporarily disabled. But if - // the link is removed, we also set the link_enabled flag to false - // because if there is no link, it can't be enabled. Also, access to - // instance is only protected by a check on the link_enabled flag. +// Programming Note: It is possible to disable the link without deleting +// the connection. This allows it to be temporarily disabled. But if +// the link is removed, we also set the link_enabled flag to false +// because if there is no link, it can't be enabled. Also, access to +// instance is only protected by a check on the link_enabled flag. - void - event_manager::connect_link (const std::shared_ptr& obj) - { - if (! obj) - disable (); +void +event_manager::connect_link (const std::shared_ptr& obj) +{ + if (! obj) + disable (); - m_instance = obj; - } + m_instance = obj; +} - bool event_manager::enable (void) - { - bool retval = m_link_enabled; +bool event_manager::enable (void) +{ + bool retval = m_link_enabled; - if (m_instance) - m_link_enabled = true; - else - warning ("event_manager: must have connected link to enable"); + if (m_instance) + m_link_enabled = true; + else + warning ("event_manager: must have connected link to enable"); - return retval; - } + return retval; +} - void event_manager::process_events (bool disable_flag) - { - if (enabled ()) - { - if (disable_flag) - disable (); +void event_manager::process_events (bool disable_flag) +{ + if (enabled ()) + { + if (disable_flag) + disable (); - m_event_queue_mutex->lock (); - std::shared_ptr evq = m_gui_event_queue.top (); - m_event_queue_mutex->unlock (); + m_event_queue_mutex->lock (); + std::shared_ptr evq = m_gui_event_queue.top (); + m_event_queue_mutex->unlock (); - evq->run (); - } - } + evq->run (); + } +} - void event_manager::discard_events (void) - { - if (enabled ()) - { - m_event_queue_mutex->lock (); - std::shared_ptr evq = m_gui_event_queue.top (); - m_event_queue_mutex->unlock (); +void event_manager::discard_events (void) +{ + if (enabled ()) + { + m_event_queue_mutex->lock (); + std::shared_ptr evq = m_gui_event_queue.top (); + m_event_queue_mutex->unlock (); - evq->discard (); - } - } + evq->discard (); + } +} - void event_manager::push_event_queue (void) - { - std::shared_ptr evq (new event_queue ()); - m_gui_event_queue.push (evq); - } +void event_manager::push_event_queue (void) +{ + std::shared_ptr evq (new event_queue ()); + m_gui_event_queue.push (evq); +} - void event_manager::pop_event_queue (void) - { - // FIXME: Should we worry about the possibility of events remaining - // in the queue when we pop back to the previous queue? If so, then - // we will probably want to push them on to the front of the - // previous queue so they will be executed before any other events - // that were in the previous queue. This case could happen if - // graphics callback functions were added to the event queue during a - // debug session just after a dbcont command was added but before it - // executed and brought us here, for example. +void event_manager::pop_event_queue (void) +{ + // FIXME: Should we worry about the possibility of events remaining + // in the queue when we pop back to the previous queue? If so, then + // we will probably want to push them on to the front of the + // previous queue so they will be executed before any other events + // that were in the previous queue. This case could happen if + // graphics callback functions were added to the event queue during a + // debug session just after a dbcont command was added but before it + // executed and brought us here, for example. - std::shared_ptr evq = m_gui_event_queue.top (); - m_gui_event_queue.pop (); - } + std::shared_ptr evq = m_gui_event_queue.top (); + m_gui_event_queue.pop (); +} - void event_manager::post_event (const fcn_callback& fcn) - { - if (enabled ()) - { - std::shared_ptr evq = m_gui_event_queue.top (); - evq->add (fcn); - } - } +void event_manager::post_event (const fcn_callback& fcn) +{ + if (enabled ()) + { + std::shared_ptr evq = m_gui_event_queue.top (); + evq->add (fcn); + } +} - void event_manager::post_event (const meth_callback& meth) - { - if (enabled ()) - { - std::shared_ptr evq = m_gui_event_queue.top (); - evq->add (std::bind (meth, std::ref (m_interpreter))); - } - } +void event_manager::post_event (const meth_callback& meth) +{ + if (enabled ()) + { + std::shared_ptr evq = m_gui_event_queue.top (); + evq->add (std::bind (meth, std::ref (m_interpreter))); + } +} - void event_manager::set_workspace (void) - { - if (enabled ()) - { - tree_evaluator& tw = m_interpreter.get_evaluator (); +void event_manager::set_workspace (void) +{ + if (enabled ()) + { + tree_evaluator& tw = m_interpreter.get_evaluator (); - m_instance->set_workspace (tw.at_top_level (), m_debugging, + m_instance->set_workspace (tw.at_top_level (), m_debugging, tw.get_symbol_info (), true); - } - } + } +} - void event_manager::set_history (void) - { - if (enabled ()) - m_instance->set_history (command_history::list ()); - } +void event_manager::set_history (void) +{ + if (enabled ()) + m_instance->set_history (command_history::list ()); +} // FIXME: Should the following function be __event_manager_desktop__ // with the desktop function implemented in a .m file, similar to the diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/event-manager.h --- a/libinterp/corefcn/event-manager.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/event-manager.h Thu Dec 01 20:05:44 2022 -0800 @@ -44,755 +44,755 @@ OCTAVE_BEGIN_NAMESPACE(octave) - typedef std::function fcn_callback; - typedef std::function meth_callback; +typedef std::function fcn_callback; +typedef std::function meth_callback; - class execution_exception; - class symbol_info_list; +class execution_exception; +class symbol_info_list; - // The methods in this class provide a way to pass signals to the GUI - // thread. A GUI that wishes to act on these events should derive - // from this class and perform actions in a thread-safe way. In - // Octave's Qt-based GUI, for example, these functions are all - // implemented as wrappers around Qt signals that trigger actions in - // the GUI. The Qt signal/slot mechanism ensures that the actions are - // properly queued for execution when the objects corresponding to the - // signal and slot belong to different threads. - // - // These functions should not be called directly. Instead all - // requests from the interpreter for GUI actions should be done - // through the event_manager class. That class checks to ensure that - // the GUI is connected and enabled before calling these virtual - // functions. +// The methods in this class provide a way to pass signals to the GUI +// thread. A GUI that wishes to act on these events should derive +// from this class and perform actions in a thread-safe way. In +// Octave's Qt-based GUI, for example, these functions are all +// implemented as wrappers around Qt signals that trigger actions in +// the GUI. The Qt signal/slot mechanism ensures that the actions are +// properly queued for execution when the objects corresponding to the +// signal and slot belong to different threads. +// +// These functions should not be called directly. Instead all +// requests from the interpreter for GUI actions should be done +// through the event_manager class. That class checks to ensure that +// the GUI is connected and enabled before calling these virtual +// functions. - // FIXME: it would be nice if instead of requiring the GUI to derive - // from this class, it could subscribe to individual events, possibly - // multiple times. In that way, it would be more flexible and - // decentralized, similar to the Qt signal/slot connection mechanism - // and would allow the GUI to connect multiple signals to a single - // action or multiple actions to a single signal. +// FIXME: it would be nice if instead of requiring the GUI to derive +// from this class, it could subscribe to individual events, possibly +// multiple times. In that way, it would be more flexible and +// decentralized, similar to the Qt signal/slot connection mechanism +// and would allow the GUI to connect multiple signals to a single +// action or multiple actions to a single signal. - // FIXME: audit this list of functions and determine whether they are - // all necessary and whether there might be better names for them. +// FIXME: audit this list of functions and determine whether they are +// all necessary and whether there might be better names for them. - class OCTINTERP_API interpreter_events - { - public: +class OCTINTERP_API interpreter_events +{ +public: - interpreter_events (void) = default; + interpreter_events (void) = default; - interpreter_events (const interpreter_events&) = default; + interpreter_events (const interpreter_events&) = default; - interpreter_events& operator = (const interpreter_events&) = default; + interpreter_events& operator = (const interpreter_events&) = default; - virtual ~interpreter_events (void) = default; + virtual ~interpreter_events (void) = default; - // Note: START_GUI and CLOSE_GUI currently only work with the new - // experimental terminal widget. + // Note: START_GUI and CLOSE_GUI currently only work with the new + // experimental terminal widget. - // Set GUI_APP to true when starting Octave as a gui application - // (invoked with the --gui option) and false when starting the GUI - // from the Octave prompt when Octave is already running as a - // command line application. + // Set GUI_APP to true when starting Octave as a gui application + // (invoked with the --gui option) and false when starting the GUI + // from the Octave prompt when Octave is already running as a + // command line application. - virtual void start_gui (bool /*gui_app*/ = false) { } - virtual void close_gui (void) { } + virtual void start_gui (bool /*gui_app*/ = false) { } + virtual void close_gui (void) { } - // Dialogs. + // Dialogs. - virtual bool have_dialogs (void) const { return false; } + virtual bool have_dialogs (void) const { return false; } - typedef std::list> filter_list; + typedef std::list> filter_list; - virtual std::list - file_dialog (const filter_list& /*filter*/, - const std::string& /*title*/, - const std::string& /*filename*/, - const std::string& /*dirname*/, - const std::string& /*multimode*/) - { - return std::list (); - } + virtual std::list + file_dialog (const filter_list& /*filter*/, + const std::string& /*title*/, + const std::string& /*filename*/, + const std::string& /*dirname*/, + const std::string& /*multimode*/) + { + return std::list (); + } - virtual std::list - input_dialog (const std::list& /*prompt*/, - const std::string& /*title*/, - const std::list& /*nr*/, - const std::list& /*nc*/, - const std::list& /*defaults*/) - { - return std::list (); - } + virtual std::list + input_dialog (const std::list& /*prompt*/, + const std::string& /*title*/, + const std::list& /*nr*/, + const std::list& /*nc*/, + const std::list& /*defaults*/) + { + return std::list (); + } - virtual std::pair, int> - list_dialog (const std::list& /*list*/, - const std::string& /*mode*/, int /*width*/, int /*height*/, - const std::list& /*initial_value*/, - const std::string& /*name*/, - const std::list& /*prompt*/, - const std::string& /*ok_string*/, - const std::string& /*cancel_string*/) - { - return std::pair, int> (); - } + virtual std::pair, int> + list_dialog (const std::list& /*list*/, + const std::string& /*mode*/, int /*width*/, int /*height*/, + const std::list& /*initial_value*/, + const std::string& /*name*/, + const std::list& /*prompt*/, + const std::string& /*ok_string*/, + const std::string& /*cancel_string*/) + { + return std::pair, int> (); + } - virtual std::string - question_dialog (const std::string& /*msg*/, const std::string& /*title*/, - const std::string& /*btn1*/, const std::string& /*btn2*/, - const std::string& /*btn3*/, const std::string& /*btndef*/) - { - return ""; - } + virtual std::string + question_dialog (const std::string& /*msg*/, const std::string& /*title*/, + const std::string& /*btn1*/, const std::string& /*btn2*/, + const std::string& /*btn3*/, const std::string& /*btndef*/) + { + return ""; + } - virtual void update_path_dialog (void) { } + virtual void update_path_dialog (void) { } - virtual void show_preferences (void) { } + virtual void show_preferences (void) { } - virtual void apply_preferences (void) { } + virtual void apply_preferences (void) { } - virtual void show_terminal_window (void) { } + virtual void show_terminal_window (void) { } - virtual bool show_documentation (const std::string& /*file*/) - { - return false; - } + virtual bool show_documentation (const std::string& /*file*/) + { + return false; + } - virtual void show_file_browser (void) { } + virtual void show_file_browser (void) { } - virtual void show_command_history (void) { } + virtual void show_command_history (void) { } - virtual void show_workspace (void) { } + virtual void show_workspace (void) { } - virtual void show_community_news (int /*serial*/) { } - virtual void show_release_notes (void) { } + virtual void show_community_news (int /*serial*/) { } + virtual void show_release_notes (void) { } - virtual bool edit_file (const std::string& /*file*/) { return false; } + virtual bool edit_file (const std::string& /*file*/) { return false; } - virtual void - edit_variable (const std::string& /*name*/, const octave_value& /*val*/) - { } + virtual void + edit_variable (const std::string& /*name*/, const octave_value& /*val*/) + { } - // Other requests for user interaction, usually some kind of - // confirmation before another action. Could these be reformulated - // using the question_dialog action? + // Other requests for user interaction, usually some kind of + // confirmation before another action. Could these be reformulated + // using the question_dialog action? - virtual bool confirm_shutdown (void) { return true; } + virtual bool confirm_shutdown (void) { return true; } - virtual bool prompt_new_edit_file (const std::string& /*file*/) - { - return false; - } + virtual bool prompt_new_edit_file (const std::string& /*file*/) + { + return false; + } - virtual int - debug_cd_or_addpath_error (const std::string& /*file*/, - const std::string& /*dir*/, - bool /*addpath_option*/) - { - return -1; - } + virtual int + debug_cd_or_addpath_error (const std::string& /*file*/, + const std::string& /*dir*/, + bool /*addpath_option*/) + { + return -1; + } - // Requests for information normally stored in the GUI. + // Requests for information normally stored in the GUI. - virtual uint8NDArray get_named_icon (const std::string& /*icon_name*/) - { - return uint8NDArray (); - } + virtual uint8NDArray get_named_icon (const std::string& /*icon_name*/) + { + return uint8NDArray (); + } - virtual std::string gui_preference (const std::string& /*key*/, - const std::string& /*value*/) - { - return ""; - } + virtual std::string gui_preference (const std::string& /*key*/, + const std::string& /*value*/) + { + return ""; + } - // Requests for GUI action that do not require user interaction. - // These are different from other notifications in that they are not - // associated with changes in the interpreter state (like a change - // in the current working directory or command history). + // Requests for GUI action that do not require user interaction. + // These are different from other notifications in that they are not + // associated with changes in the interpreter state (like a change + // in the current working directory or command history). - virtual bool copy_image_to_clipboard (const std::string& /*file*/) - { - return false; - } + virtual bool copy_image_to_clipboard (const std::string& /*file*/) + { + return false; + } - virtual void focus_window (const std::string /*win_name*/) - { } + virtual void focus_window (const std::string /*win_name*/) + { } - virtual void - execute_command_in_terminal (const std::string& /*command*/) { } + virtual void + execute_command_in_terminal (const std::string& /*command*/) { } - virtual void register_documentation (const std::string& /*file*/) { } + virtual void register_documentation (const std::string& /*file*/) { } - virtual void unregister_documentation (const std::string& /*file*/) { } + virtual void unregister_documentation (const std::string& /*file*/) { } - virtual void interpreter_output (const std::string& /*msg*/) { } + virtual void interpreter_output (const std::string& /*msg*/) { } - virtual void display_exception (const execution_exception& ee, bool beep); + virtual void display_exception (const execution_exception& ee, bool beep); - virtual void gui_status_update (const std::string& /*feature*/, - const std::string& /*status*/) { } + virtual void gui_status_update (const std::string& /*feature*/, + const std::string& /*status*/) { } - virtual void update_gui_lexer (void) { } + virtual void update_gui_lexer (void) { } - // Notifications of events in the interpreter that a GUI will - // normally wish to respond to. + // Notifications of events in the interpreter that a GUI will + // normally wish to respond to. - virtual void directory_changed (const std::string& /*dir*/) { } + virtual void directory_changed (const std::string& /*dir*/) { } - virtual void - file_remove (const std::string& /*old_nm*/, const std::string& /*new_nm*/) - { } + virtual void + file_remove (const std::string& /*old_nm*/, const std::string& /*new_nm*/) + { } - virtual void file_renamed (bool) { } + virtual void file_renamed (bool) { } - virtual void - set_workspace (bool /*top_level*/, bool /*debug*/, - const symbol_info_list& /*syminfo*/, - bool /*update_variable_editor*/) - { } + virtual void + set_workspace (bool /*top_level*/, bool /*debug*/, + const symbol_info_list& /*syminfo*/, + bool /*update_variable_editor*/) + { } - virtual void clear_workspace (void) { } + virtual void clear_workspace (void) { } - virtual void update_prompt (const std::string& /*prompt*/) { } + virtual void update_prompt (const std::string& /*prompt*/) { } - virtual void set_history (const string_vector& /*hist*/) { } + virtual void set_history (const string_vector& /*hist*/) { } - virtual void append_history (const std::string& /*hist_entry*/) { } + virtual void append_history (const std::string& /*hist_entry*/) { } - virtual void clear_history (void) { } + virtual void clear_history (void) { } - virtual void pre_input_event (void) { } + virtual void pre_input_event (void) { } - virtual void post_input_event (void) { } + virtual void post_input_event (void) { } - virtual void - enter_debugger_event (const std::string& /*fcn_name*/, - const std::string& /*fcn_file_name*/, - int /*line*/) - { } + virtual void + enter_debugger_event (const std::string& /*fcn_name*/, + const std::string& /*fcn_file_name*/, + int /*line*/) + { } - virtual void - execute_in_debugger_event (const std::string& /*file*/, int /*line*/) { } + virtual void + execute_in_debugger_event (const std::string& /*file*/, int /*line*/) { } - virtual void exit_debugger_event (void) { } + virtual void exit_debugger_event (void) { } - virtual void - update_breakpoint (bool /*insert*/, const std::string& /*file*/, - int /*line*/, const std::string& /*cond*/) - { } + virtual void + update_breakpoint (bool /*insert*/, const std::string& /*file*/, + int /*line*/, const std::string& /*cond*/) + { } - virtual void interpreter_interrupted (void) { } - }; + virtual void interpreter_interrupted (void) { } +}; - //! Provides threadsafe access to octave. - //! - //! This class provides thread-safe communication between the - //! interpreter and a GUI. +//! Provides threadsafe access to octave. +//! +//! This class provides thread-safe communication between the +//! interpreter and a GUI. - class - OCTINTERP_API - event_manager - { - public: +class +OCTINTERP_API +event_manager +{ +public: - OCTINTERP_API event_manager (interpreter& interp); + OCTINTERP_API event_manager (interpreter& interp); - // No copying! + // No copying! - event_manager (const event_manager&) = delete; + event_manager (const event_manager&) = delete; - event_manager& - operator = (const event_manager&) = delete; + event_manager& + operator = (const event_manager&) = delete; - virtual ~event_manager (void); + virtual ~event_manager (void); - // OBJ should be an object of a class that is derived from the base - // class interpreter_events, or nullptr to disconnect and delete the - // previous link. + // OBJ should be an object of a class that is derived from the base + // class interpreter_events, or nullptr to disconnect and delete the + // previous link. - OCTINTERP_API void - connect_link (const std::shared_ptr& obj); + OCTINTERP_API void + connect_link (const std::shared_ptr& obj); - OCTINTERP_API bool enable (void); + OCTINTERP_API bool enable (void); - bool disable (void) - { - bool retval = m_link_enabled; - m_link_enabled = false; - return retval; - } + bool disable (void) + { + bool retval = m_link_enabled; + m_link_enabled = false; + return retval; + } - bool enabled (void) const - { - return m_link_enabled; - } + bool enabled (void) const + { + return m_link_enabled; + } - // Make the Qt actions available for others. This is a temporary - // solution to allow Qt actions like opening the documentation - // browser when the primary interpreter_events object is not the one - // defined for the Qt GUI. - void - install_qt_event_handlers (const std::shared_ptr& obj) - { - m_qt_event_handlers = obj; - } + // Make the Qt actions available for others. This is a temporary + // solution to allow Qt actions like opening the documentation + // browser when the primary interpreter_events object is not the one + // defined for the Qt GUI. + void + install_qt_event_handlers (const std::shared_ptr& obj) + { + m_qt_event_handlers = obj; + } - std::shared_ptr - qt_event_handlers (void) const { return m_qt_event_handlers; } + std::shared_ptr + qt_event_handlers (void) const { return m_qt_event_handlers; } - // If disable is TRUE, then no additional events will be processed - // other than exit. + // If disable is TRUE, then no additional events will be processed + // other than exit. - OCTINTERP_API void process_events (bool disable = false); + OCTINTERP_API void process_events (bool disable = false); - OCTINTERP_API void discard_events (void); + OCTINTERP_API void discard_events (void); - // The post_event and post_exception functions provide a thread-safe - // way for the GUI to queue interpreter functions for execution. - // The queued functions are executed when the interpreter is - // otherwise idle. + // The post_event and post_exception functions provide a thread-safe + // way for the GUI to queue interpreter functions for execution. + // The queued functions are executed when the interpreter is + // otherwise idle. - void push_event_queue (void); - void pop_event_queue (void); + void push_event_queue (void); + void pop_event_queue (void); - OCTINTERP_API void post_event (const fcn_callback& fcn); - OCTINTERP_API void post_event (const meth_callback& meth); + OCTINTERP_API void post_event (const fcn_callback& fcn); + OCTINTERP_API void post_event (const meth_callback& meth); - // The following functions correspond to the virtual fuunctions in - // the interpreter_events class. They provide a way for the - // interpreter to notify the GUI that some event has occurred - // (directory or workspace changed, for example) or to request the - // GUI to perform some action (display a dialog, for example). + // The following functions correspond to the virtual fuunctions in + // the interpreter_events class. They provide a way for the + // interpreter to notify the GUI that some event has occurred + // (directory or workspace changed, for example) or to request the + // GUI to perform some action (display a dialog, for example). - // Please keep this list of declarations in the same order as the - // ones above in the interpreter_events class. + // Please keep this list of declarations in the same order as the + // ones above in the interpreter_events class. - // Note: START_GUI and CLOSE_GUI currently only work with the new - // experimental terminal object. + // Note: START_GUI and CLOSE_GUI currently only work with the new + // experimental terminal object. - void start_gui (bool gui_app = false) - { - if (enabled ()) - m_instance->start_gui (gui_app); - } + void start_gui (bool gui_app = false) + { + if (enabled ()) + m_instance->start_gui (gui_app); + } - void close_gui (void) - { - if (enabled ()) - m_instance->close_gui (); - } + void close_gui (void) + { + if (enabled ()) + m_instance->close_gui (); + } - // Dialogs + // Dialogs - bool have_dialogs (void) const - { - return m_qt_event_handlers && m_qt_event_handlers->have_dialogs (); - } + bool have_dialogs (void) const + { + return m_qt_event_handlers && m_qt_event_handlers->have_dialogs (); + } - typedef std::list> filter_list; + typedef std::list> filter_list; - std::list - file_dialog (const filter_list& filter, const std::string& title, - const std::string& filename, const std::string& dirname, - const std::string& multimode) - { - return (enabled () && have_dialogs () - ? m_instance->file_dialog (filter, title, filename, dirname, - multimode) - : std::list ()); - } + std::list + file_dialog (const filter_list& filter, const std::string& title, + const std::string& filename, const std::string& dirname, + const std::string& multimode) + { + return (enabled () && have_dialogs () + ? m_instance->file_dialog (filter, title, filename, dirname, + multimode) + : std::list ()); + } - std::list - input_dialog (const std::list& prompt, - const std::string& title, - const std::list& nr, - const std::list& nc, - const std::list& defaults) - { - return (enabled () && have_dialogs () - ? m_instance->input_dialog (prompt, title, nr, nc, defaults) - : std::list ()); - } + std::list + input_dialog (const std::list& prompt, + const std::string& title, + const std::list& nr, + const std::list& nc, + const std::list& defaults) + { + return (enabled () && have_dialogs () + ? m_instance->input_dialog (prompt, title, nr, nc, defaults) + : std::list ()); + } - std::pair, int> - list_dialog (const std::list& list, - const std::string& mode, - int width, int height, - const std::list& initial_value, - const std::string& name, - const std::list& prompt, - const std::string& ok_string, - const std::string& cancel_string) - { - return (enabled () && have_dialogs () - ? m_instance->list_dialog (list, mode, width, height, - initial_value, name, prompt, - ok_string, cancel_string) - : std::pair, int> ()); - } + std::pair, int> + list_dialog (const std::list& list, + const std::string& mode, + int width, int height, + const std::list& initial_value, + const std::string& name, + const std::list& prompt, + const std::string& ok_string, + const std::string& cancel_string) + { + return (enabled () && have_dialogs () + ? m_instance->list_dialog (list, mode, width, height, + initial_value, name, prompt, + ok_string, cancel_string) + : std::pair, int> ()); + } - std::string - question_dialog (const std::string& msg, const std::string& title, - const std::string& btn1, const std::string& btn2, - const std::string& btn3, const std::string& btndef) - { - return (enabled () && have_dialogs () - ? m_instance->question_dialog (msg, title, btn1, - btn2, btn3, btndef) - : ""); - } + std::string + question_dialog (const std::string& msg, const std::string& title, + const std::string& btn1, const std::string& btn2, + const std::string& btn3, const std::string& btndef) + { + return (enabled () && have_dialogs () + ? m_instance->question_dialog (msg, title, btn1, + btn2, btn3, btndef) + : ""); + } - void update_path_dialog (void) - { - if (application::is_gui_running () && enabled ()) - m_instance->update_path_dialog (); - } + void update_path_dialog (void) + { + if (application::is_gui_running () && enabled ()) + m_instance->update_path_dialog (); + } - bool show_preferences (void) - { - if (enabled ()) - { - m_instance->show_preferences (); - return true; - } - else - return false; - } + bool show_preferences (void) + { + if (enabled ()) + { + m_instance->show_preferences (); + return true; + } + else + return false; + } - bool apply_preferences (void) - { - if (enabled ()) - { - m_instance->apply_preferences (); - return true; - } - else - return false; - } + bool apply_preferences (void) + { + if (enabled ()) + { + m_instance->apply_preferences (); + return true; + } + else + return false; + } - void show_terminal_window (void) - { - if (enabled ()) - m_instance->show_terminal_window (); - } + void show_terminal_window (void) + { + if (enabled ()) + m_instance->show_terminal_window (); + } - bool show_documentation (const std::string& file) - { - return enabled () ? m_instance->show_documentation (file) : false; - } + bool show_documentation (const std::string& file) + { + return enabled () ? m_instance->show_documentation (file) : false; + } - void show_file_browser (void) - { - if (enabled ()) - m_instance->show_file_browser (); - } + void show_file_browser (void) + { + if (enabled ()) + m_instance->show_file_browser (); + } - void show_command_history (void) - { - if (enabled ()) - m_instance->show_command_history (); - } + void show_command_history (void) + { + if (enabled ()) + m_instance->show_command_history (); + } - void show_workspace (void) - { - if (enabled ()) - m_instance->show_workspace (); - } + void show_workspace (void) + { + if (enabled ()) + m_instance->show_workspace (); + } - void show_community_news (int serial = -1) - { - if (enabled ()) - m_instance->show_community_news (serial); - } + void show_community_news (int serial = -1) + { + if (enabled ()) + m_instance->show_community_news (serial); + } - void show_release_notes (void) - { - if (enabled ()) - m_instance->show_release_notes (); - } + void show_release_notes (void) + { + if (enabled ()) + m_instance->show_release_notes (); + } - bool edit_file (const std::string& file) - { - return enabled () ? m_instance->edit_file (file) : false; - } + bool edit_file (const std::string& file) + { + return enabled () ? m_instance->edit_file (file) : false; + } - bool edit_variable (const std::string& name, const octave_value& val) - { - if (enabled ()) - { - m_instance->edit_variable (name, val); - return true; - } - else - return false; - } + bool edit_variable (const std::string& name, const octave_value& val) + { + if (enabled ()) + { + m_instance->edit_variable (name, val); + return true; + } + else + return false; + } - bool confirm_shutdown (void) - { - bool retval = true; + bool confirm_shutdown (void) + { + bool retval = true; - if (enabled ()) - retval = m_instance->confirm_shutdown (); + if (enabled ()) + retval = m_instance->confirm_shutdown (); - return retval; - } + return retval; + } - bool prompt_new_edit_file (const std::string& file) - { - return enabled () ? m_instance->prompt_new_edit_file (file) : false; - } + bool prompt_new_edit_file (const std::string& file) + { + return enabled () ? m_instance->prompt_new_edit_file (file) : false; + } - int debug_cd_or_addpath_error (const std::string& file, - const std::string& dir, bool addpath_option) - { - return (enabled () - ? m_instance->debug_cd_or_addpath_error (file, dir, - addpath_option) - : 0); - } + int debug_cd_or_addpath_error (const std::string& file, + const std::string& dir, bool addpath_option) + { + return (enabled () + ? m_instance->debug_cd_or_addpath_error (file, dir, + addpath_option) + : 0); + } - uint8NDArray get_named_icon (const std::string& icon_name) - { - return (enabled () - ? m_instance->get_named_icon (icon_name) : uint8NDArray ()); - } + uint8NDArray get_named_icon (const std::string& icon_name) + { + return (enabled () + ? m_instance->get_named_icon (icon_name) : uint8NDArray ()); + } - std::string gui_preference (const std::string& key, - const std::string& value) - { - return enabled () ? m_instance->gui_preference (key, value) : ""; - } + std::string gui_preference (const std::string& key, + const std::string& value) + { + return enabled () ? m_instance->gui_preference (key, value) : ""; + } - bool copy_image_to_clipboard (const std::string& file) - { - return enabled () ? m_instance->copy_image_to_clipboard (file) : false; - } + bool copy_image_to_clipboard (const std::string& file) + { + return enabled () ? m_instance->copy_image_to_clipboard (file) : false; + } - virtual void focus_window (const std::string win_name) - { - if (enabled ()) - m_instance->focus_window (win_name); - } + virtual void focus_window (const std::string win_name) + { + if (enabled ()) + m_instance->focus_window (win_name); + } - // Preserves pending input. - void execute_command_in_terminal (const std::string& command) - { - if (enabled ()) - m_instance->execute_command_in_terminal (command); - } + // Preserves pending input. + void execute_command_in_terminal (const std::string& command) + { + if (enabled ()) + m_instance->execute_command_in_terminal (command); + } - bool register_documentation (const std::string& file) - { - if (enabled ()) - { - m_instance->register_documentation (file); - return true; - } - else - return false; - } + bool register_documentation (const std::string& file) + { + if (enabled ()) + { + m_instance->register_documentation (file); + return true; + } + else + return false; + } - bool unregister_documentation (const std::string& file) - { - if (enabled ()) - { - m_instance->unregister_documentation (file); - return true; - } - else - return false; - } + bool unregister_documentation (const std::string& file) + { + if (enabled ()) + { + m_instance->unregister_documentation (file); + return true; + } + else + return false; + } - bool interpreter_output (const std::string& msg) - { - if (enabled ()) - { - m_instance->interpreter_output (msg); - return true; - } - else - return false; - } + bool interpreter_output (const std::string& msg) + { + if (enabled ()) + { + m_instance->interpreter_output (msg); + return true; + } + else + return false; + } - bool display_exception (const execution_exception& ee, bool beep = false) - { - if (enabled ()) - { - m_instance->display_exception (ee, beep); - return true; - } - else - return false; - } + bool display_exception (const execution_exception& ee, bool beep = false) + { + if (enabled ()) + { + m_instance->display_exception (ee, beep); + return true; + } + else + return false; + } - bool gui_status_update (const std::string& feature, - const std::string& status) - { - if (enabled ()) - { - m_instance->gui_status_update (feature, status); - return true; - } - else - return false; - } + bool gui_status_update (const std::string& feature, + const std::string& status) + { + if (enabled ()) + { + m_instance->gui_status_update (feature, status); + return true; + } + else + return false; + } - bool update_gui_lexer (void) - { - if (enabled ()) - { - m_instance->update_gui_lexer (); - return true; - } - else - return false; - } + bool update_gui_lexer (void) + { + if (enabled ()) + { + m_instance->update_gui_lexer (); + return true; + } + else + return false; + } - void directory_changed (const std::string& dir) - { - if (enabled ()) - m_instance->directory_changed (dir); - } + void directory_changed (const std::string& dir) + { + if (enabled ()) + m_instance->directory_changed (dir); + } - // Methods for removing/renaming files which might be open in editor - void file_remove (const std::string& old_name, const std::string& new_name) - { - if (application::is_gui_running () && enabled ()) - m_instance->file_remove (old_name, new_name); - } + // Methods for removing/renaming files which might be open in editor + void file_remove (const std::string& old_name, const std::string& new_name) + { + if (application::is_gui_running () && enabled ()) + m_instance->file_remove (old_name, new_name); + } - void file_renamed (bool load_new) - { - if (application::is_gui_running () && enabled ()) - m_instance->file_renamed (load_new); - } + void file_renamed (bool load_new) + { + if (application::is_gui_running () && enabled ()) + m_instance->file_renamed (load_new); + } - OCTINTERP_API void set_workspace (void); + OCTINTERP_API void set_workspace (void); - void set_workspace (bool top_level, const symbol_info_list& syminfo, - bool update_variable_editor = true) - { - if (enabled ()) - m_instance->set_workspace (top_level, m_debugging, syminfo, - update_variable_editor); - } + void set_workspace (bool top_level, const symbol_info_list& syminfo, + bool update_variable_editor = true) + { + if (enabled ()) + m_instance->set_workspace (top_level, m_debugging, syminfo, + update_variable_editor); + } - void clear_workspace (void) - { - if (enabled ()) - m_instance->clear_workspace (); - } + void clear_workspace (void) + { + if (enabled ()) + m_instance->clear_workspace (); + } - void update_prompt (const std::string& prompt) - { - if (enabled ()) - m_instance->update_prompt (prompt); - } + void update_prompt (const std::string& prompt) + { + if (enabled ()) + m_instance->update_prompt (prompt); + } - OCTINTERP_API void set_history (void); + OCTINTERP_API void set_history (void); - void set_history (const string_vector& hist) - { - if (enabled ()) - m_instance->set_history (hist); - } + void set_history (const string_vector& hist) + { + if (enabled ()) + m_instance->set_history (hist); + } - void append_history (const std::string& hist_entry) - { - if (enabled ()) - m_instance->append_history (hist_entry); - } + void append_history (const std::string& hist_entry) + { + if (enabled ()) + m_instance->append_history (hist_entry); + } - void clear_history (void) - { - if (enabled ()) - m_instance->clear_history (); - } + void clear_history (void) + { + if (enabled ()) + m_instance->clear_history (); + } - void pre_input_event (void) - { - if (enabled ()) - m_instance->pre_input_event (); - } + void pre_input_event (void) + { + if (enabled ()) + m_instance->pre_input_event (); + } - void post_input_event (void) - { - if (enabled ()) - m_instance->post_input_event (); - } + void post_input_event (void) + { + if (enabled ()) + m_instance->post_input_event (); + } - void enter_debugger_event (const std::string& fcn_name, - const std::string& fcn_file_name, int line) - { - if (enabled ()) - { - m_debugging = true; + void enter_debugger_event (const std::string& fcn_name, + const std::string& fcn_file_name, int line) + { + if (enabled ()) + { + m_debugging = true; - m_instance->enter_debugger_event (fcn_name, fcn_file_name, line); - } - } + m_instance->enter_debugger_event (fcn_name, fcn_file_name, line); + } + } - void execute_in_debugger_event (const std::string& file, int line) - { - if (enabled ()) - m_instance->execute_in_debugger_event (file, line); - } + void execute_in_debugger_event (const std::string& file, int line) + { + if (enabled ()) + m_instance->execute_in_debugger_event (file, line); + } - void exit_debugger_event (void) - { - if (enabled () && m_debugging) - { - m_debugging = false; + void exit_debugger_event (void) + { + if (enabled () && m_debugging) + { + m_debugging = false; - m_instance->exit_debugger_event (); - } - } + m_instance->exit_debugger_event (); + } + } - void update_breakpoint (bool insert, const std::string& file, - int line, const std::string& cond = "") - { - if (enabled ()) - m_instance->update_breakpoint (insert, file, line, cond); - } + void update_breakpoint (bool insert, const std::string& file, + int line, const std::string& cond = "") + { + if (enabled ()) + m_instance->update_breakpoint (insert, file, line, cond); + } - void interpreter_interrupted (void) - { - if (enabled ()) - m_instance->interpreter_interrupted (); - } + void interpreter_interrupted (void) + { + if (enabled ()) + m_instance->interpreter_interrupted (); + } - protected: +protected: - // Semaphore to lock access to the event queue. - mutex *m_event_queue_mutex; + // Semaphore to lock access to the event queue. + mutex *m_event_queue_mutex; - // Event Queue. We use a stack so that we can handle evaluation in - // the debugger when we are executing in server mode. In server - // mode, code is evaluated from inside the event queue. So when the - // evaluator reaches a breakpoint, the queue is already locked and - // executing an event function. We can't just add a new command to the - // existing queue, so we need another one that can process new - // events generated at the debug prompt. When execution continues - // (dbcont or dbstep, for example) we pop the queue and return to - // the previous point of execution. + // Event Queue. We use a stack so that we can handle evaluation in + // the debugger when we are executing in server mode. In server + // mode, code is evaluated from inside the event queue. So when the + // evaluator reaches a breakpoint, the queue is already locked and + // executing an event function. We can't just add a new command to the + // existing queue, so we need another one that can process new + // events generated at the debug prompt. When execution continues + // (dbcont or dbstep, for example) we pop the queue and return to + // the previous point of execution. - std::stack> m_gui_event_queue; + std::stack> m_gui_event_queue; - bool m_debugging; - bool m_link_enabled; + bool m_debugging; + bool m_link_enabled; - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - // Using a shared_ptr to manage the link_events object ensures that it - // will be valid until it is no longer needed. + // Using a shared_ptr to manage the link_events object ensures that it + // will be valid until it is no longer needed. - std::shared_ptr m_instance; + std::shared_ptr m_instance; - std::shared_ptr m_qt_event_handlers; + std::shared_ptr m_qt_event_handlers; - }; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/event-queue.cc --- a/libinterp/corefcn/event-queue.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/event-queue.cc Thu Dec 01 20:05:44 2022 -0800 @@ -32,12 +32,12 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - event_queue_safe::warn_unhandled_exception (void) const - { - warning ("unhandled exception in event_queue_safe handler. " - "It is a bug in Octave for this to happen. " - "Please help improve Octave by reporting it."); - } +void +event_queue_safe::warn_unhandled_exception (void) const +{ + warning ("unhandled exception in event_queue_safe handler. " + "It is a bug in Octave for this to happen. " + "Please help improve Octave by reporting it."); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/event-queue.h --- a/libinterp/corefcn/event-queue.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/event-queue.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,96 +35,96 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - event_queue : public action_container - { - public: +class +event_queue : public action_container +{ +public: - event_queue (void) : m_fifo () { } + event_queue (void) : m_fifo () { } - // No copying! + // No copying! - event_queue (const event_queue&) = delete; + event_queue (const event_queue&) = delete; - event_queue& operator = (const event_queue&) = delete; + event_queue& operator = (const event_queue&) = delete; - // Destructor should not raise an exception, so all actions registered - // should be exception-safe. If you're not sure, see event_queue_safe. + // Destructor should not raise an exception, so all actions registered + // should be exception-safe. If you're not sure, see event_queue_safe. - ~event_queue (void) { run (); } + ~event_queue (void) { run (); } - void run_first (void) - { - if (! empty ()) - { - // No leak on exception! - std::unique_ptr ptr (m_fifo.front ()); - m_fifo.pop (); - ptr->run (); - } - } + void run_first (void) + { + if (! empty ()) + { + // No leak on exception! + std::unique_ptr ptr (m_fifo.front ()); + m_fifo.pop (); + ptr->run (); + } + } - void discard_first (void) - { - if (! empty ()) - { - elem *ptr = m_fifo.front (); - m_fifo.pop (); - delete ptr; - } - } + void discard_first (void) + { + if (! empty ()) + { + elem *ptr = m_fifo.front (); + m_fifo.pop (); + delete ptr; + } + } - std::size_t size (void) const { return m_fifo.size (); } + std::size_t size (void) const { return m_fifo.size (); } - protected: +protected: - void add_action (elem *new_elem) - { - m_fifo.push (new_elem); - } + void add_action (elem *new_elem) + { + m_fifo.push (new_elem); + } - //-------- + //-------- - std::queue m_fifo; - }; + std::queue m_fifo; +}; - // Like event_queue, but this one will guard against the - // possibility of seeing an exception (or interrupt) in the cleanup actions. - // Not that we can do much about it, but at least we won't crash. +// Like event_queue, but this one will guard against the +// possibility of seeing an exception (or interrupt) in the cleanup actions. +// Not that we can do much about it, but at least we won't crash. - class - event_queue_safe : public event_queue - { - public: +class +event_queue_safe : public event_queue +{ +public: - event_queue_safe (void) : event_queue () { } + event_queue_safe (void) : event_queue () { } - // No copying! + // No copying! - event_queue_safe (const event_queue_safe&) = delete; + event_queue_safe (const event_queue_safe&) = delete; - event_queue_safe& operator = (const event_queue_safe&) = delete; + event_queue_safe& operator = (const event_queue_safe&) = delete; - ~event_queue_safe (void) - { - while (! empty ()) - { - try - { - run_first (); - } - catch (...) // Yes, the black hole. Remember we're in a dtor. - { - warn_unhandled_exception (); - } - } - } + ~event_queue_safe (void) + { + while (! empty ()) + { + try + { + run_first (); + } + catch (...) // Yes, the black hole. Remember we're in a dtor. + { + warn_unhandled_exception (); + } + } + } - private: +private: - void warn_unhandled_exception (void) const; + void warn_unhandled_exception (void) const; - }; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/fcn-info.cc --- a/libinterp/corefcn/fcn-info.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/fcn-info.cc Thu Dec 01 20:05:44 2022 -0800 @@ -49,1089 +49,1090 @@ OCTAVE_BEGIN_NAMESPACE(octave) - octave_value - fcn_info::fcn_info_rep::load_private_function (const std::string& dir_name) - { - octave_value retval; - - load_path& lp = __get_load_path__ (); - - std::string file_name = lp.find_private_fcn (dir_name, name); - - if (file_name.empty ()) - return retval; +octave_value +fcn_info::fcn_info_rep::load_private_function (const std::string& dir_name) +{ + octave_value retval; - octave_value ov_fcn = load_fcn_from_file (file_name, dir_name); - - if (ov_fcn.is_undefined ()) - return retval; + load_path& lp = __get_load_path__ (); - octave_function *tmpfcn = ov_fcn.function_value (); + std::string file_name = lp.find_private_fcn (dir_name, name); - if (! tmpfcn) - return retval; - - std::string class_name; + if (file_name.empty ()) + return retval; - std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); - - if (pos != std::string::npos) - { - std::string tmp = dir_name.substr (pos+1); + octave_value ov_fcn = load_fcn_from_file (file_name, dir_name); - if (tmp[0] == '@') - class_name = tmp.substr (1); - } + if (ov_fcn.is_undefined ()) + return retval; - tmpfcn->mark_as_private_function (class_name); + octave_function *tmpfcn = ov_fcn.function_value (); - private_functions[sys::canonicalize_file_name (dir_name)] = ov_fcn; - - return ov_fcn; - } + if (! tmpfcn) + return retval; - octave_value - fcn_info::fcn_info_rep::load_class_constructor (void) - { - octave_value retval; + std::string class_name; - std::string dir_name; + std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); - load_path& lp = __get_load_path__ (); - - std::string file_name = lp.find_method (name, name, dir_name, package_name); + if (pos != std::string::npos) + { + std::string tmp = dir_name.substr (pos+1); - if (! file_name.empty ()) - { - octave_value ov_fcn - = load_fcn_from_file (file_name, dir_name, name, - package_name); + if (tmp[0] == '@') + class_name = tmp.substr (1); + } - if (ov_fcn.is_defined ()) - { - // Note: ov_fcn may be an octave_classdef_meta object instead - // of the actual constructor function. + tmpfcn->mark_as_private_function (class_name); - retval = ov_fcn; + private_functions[sys::canonicalize_file_name (dir_name)] = ov_fcn; - class_constructors[name] = retval; - class_methods[name] = retval; - } - } - else - { - // Classdef constructors can be defined anywhere in the path, not - // necessarily in @-folders. Look for a normal function and load it. - // If the loaded function is a classdef constructor, store it as such - // and restore function_on_path to its previous value. - - octave_value old_function_on_path = function_on_path; - - octave_value maybe_cdef_ctor = find_user_function (); + return ov_fcn; +} - if (maybe_cdef_ctor.is_defined ()) - { - octave_function *fcn = maybe_cdef_ctor.function_value (true); - - if (fcn && fcn->is_classdef_constructor ()) - { - retval = maybe_cdef_ctor; +octave_value +fcn_info::fcn_info_rep::load_class_constructor (void) +{ + octave_value retval; - class_constructors[name] = retval; - class_methods[name] = retval; + std::string dir_name; - function_on_path = old_function_on_path; - } - } - } + load_path& lp = __get_load_path__ (); + + std::string file_name = lp.find_method (name, name, dir_name, package_name); - return retval; - } - - octave_value - fcn_info::fcn_info_rep::load_class_method (const std::string& dispatch_type) - { - octave_value retval; + if (! file_name.empty ()) + { + octave_value ov_fcn + = load_fcn_from_file (file_name, dir_name, name, + package_name); - if (full_name () == dispatch_type) - retval = load_class_constructor (); - else - { - cdef_manager& cdm = __get_cdef_manager__ (); + if (ov_fcn.is_defined ()) + { + // Note: ov_fcn may be an octave_classdef_meta object instead + // of the actual constructor function. - retval = cdm.find_method_symbol (name, dispatch_type); - - if (! retval.is_defined ()) - { - std::string dir_name; - - load_path& lp = __get_load_path__ (); + retval = ov_fcn; - std::string file_name = lp.find_method (dispatch_type, name, - dir_name); - - if (! file_name.empty ()) - { - octave_value ov_fcn - = load_fcn_from_file (file_name, dir_name, - dispatch_type); - - if (ov_fcn.is_defined ()) - { - octave_function *tmpfcn = ov_fcn.function_value (); + class_constructors[name] = retval; + class_methods[name] = retval; + } + } + else + { + // Classdef constructors can be defined anywhere in the path, not + // necessarily in @-folders. Look for a normal function and load it. + // If the loaded function is a classdef constructor, store it as such + // and restore function_on_path to its previous value. - if (tmpfcn && tmpfcn->is_class_method (dispatch_type)) - { - retval = ov_fcn; - - class_methods[dispatch_type] = retval; - } - } - } - - if (retval.is_undefined ()) - { - // Search parent classes + octave_value old_function_on_path = function_on_path; - symbol_table& symtab = __get_symbol_table__ (); + octave_value maybe_cdef_ctor = find_user_function (); - const std::list& plist - = symtab.parent_classes (dispatch_type); - - auto it = plist.begin (); + if (maybe_cdef_ctor.is_defined ()) + { + octave_function *fcn = maybe_cdef_ctor.function_value (true); - while (it != plist.end ()) - { - retval = find_method (*it); + if (fcn && fcn->is_classdef_constructor ()) + { + retval = maybe_cdef_ctor; - if (retval.is_defined ()) - { - class_methods[dispatch_type] = retval; - break; - } - - it++; - } - } + class_constructors[name] = retval; + class_methods[name] = retval; - if (retval.is_undefined ()) - { - // Search for built-in functions that are declared to - // handle specific types. - - if (built_in_function.is_defined ()) - { - octave_function *fcn = built_in_function.function_value (); - - if (fcn && fcn->handles_dispatch_class (dispatch_type)) - { - retval = built_in_function; + function_on_path = old_function_on_path; + } + } + } - class_methods[dispatch_type] = retval; - } - } - } - } - } + return retval; +} - return retval; - } - - // :-) JWE, can you parse this? Returns a 2D array with second dimension equal - // to btyp_num_types (static constant). Only the leftmost dimension can be - // variable in C/C++. Typedefs are boring. +octave_value +fcn_info::fcn_info_rep::load_class_method (const std::string& dispatch_type) +{ + octave_value retval; - static builtin_type_t (*build_sup_table (void))[btyp_num_types] - { - static builtin_type_t sup_table[btyp_num_types][btyp_num_types]; - for (int i = 0; i < btyp_num_types; i++) - for (int j = 0; j < btyp_num_types; j++) + if (full_name () == dispatch_type) + retval = load_class_constructor (); + else + { + cdef_manager& cdm = __get_cdef_manager__ (); + + retval = cdm.find_method_symbol (name, dispatch_type); + + if (! retval.is_defined ()) { - builtin_type_t ityp = static_cast (i); - builtin_type_t jtyp = static_cast (j); - // FIXME: Is this really right? - bool use_j - = (jtyp == btyp_func_handle || ityp == btyp_bool - || (btyp_isarray (ityp) - && (! btyp_isarray (jtyp) - || (btyp_isinteger (jtyp) && ! btyp_isinteger (ityp)) - || ((ityp == btyp_double || ityp == btyp_complex - || ityp == btyp_char) - && (jtyp == btyp_float - || jtyp == btyp_float_complex))))); + std::string dir_name; + + load_path& lp = __get_load_path__ (); - sup_table[i][j] = (use_j ? jtyp : ityp); - } - - return sup_table; - } + std::string file_name = lp.find_method (dispatch_type, name, + dir_name); - std::string - get_dispatch_type (const octave_value_list& args, - builtin_type_t& builtin_type) - { - static builtin_type_t (*sup_table)[btyp_num_types] = build_sup_table (); - std::string dispatch_type; - - int n = args.length (); + if (! file_name.empty ()) + { + octave_value ov_fcn + = load_fcn_from_file (file_name, dir_name, + dispatch_type); - if (n > 0) - { - int i = 0; - builtin_type = args(0).builtin_type (); - if (builtin_type != btyp_unknown) - { - for (i = 1; i < n; i++) - { - builtin_type_t bti = args(i).builtin_type (); - if (bti != btyp_unknown) - builtin_type = sup_table[builtin_type][bti]; - else - { - builtin_type = btyp_unknown; - break; - } - } - } + if (ov_fcn.is_defined ()) + { + octave_function *tmpfcn = ov_fcn.function_value (); - if (builtin_type == btyp_unknown) - { - // There's a non-builtin class in the argument list. - dispatch_type = args(i).class_name (); + if (tmpfcn && tmpfcn->is_class_method (dispatch_type)) + { + retval = ov_fcn; - symbol_table& symtab = __get_symbol_table__ (); + class_methods[dispatch_type] = retval; + } + } + } - for (int j = i+1; j < n; j++) - { - octave_value arg = args(j); + if (retval.is_undefined ()) + { + // Search parent classes - if (arg.builtin_type () == btyp_unknown) - { - std::string cname = arg.class_name (); + symbol_table& symtab = __get_symbol_table__ (); - // Only switch to type of ARG if it is marked superior - // to the current DISPATCH_TYPE. - if (! symtab.is_superiorto (dispatch_type, cname) - && symtab.is_superiorto (cname, dispatch_type)) - dispatch_type = cname; - } - } - } - else - dispatch_type = btyp_class_name[builtin_type]; - } - else - builtin_type = btyp_unknown; + const std::list& plist + = symtab.parent_classes (dispatch_type); - return dispatch_type; - } + auto it = plist.begin (); - std::string - get_dispatch_type (const octave_value_list& args) - { - builtin_type_t builtin_type; - return get_dispatch_type (args, builtin_type); - } + while (it != plist.end ()) + { + retval = find_method (*it); - // Find function definition according to the following precedence list: - // - // nested functions (and subfunctions) - // local functions in the current file - // private function - // class method - // class constructor - // command-line function - // autoload function - // functions on the load_path (current directory is always first) - // package (FIXME: does this belong here?) - // built-in function + if (retval.is_defined ()) + { + class_methods[dispatch_type] = retval; + break; + } - octave_value - fcn_info::fcn_info_rep::find (const symbol_scope& scope, - const octave_value_list& args) - { - symbol_scope search_scope - = (scope - ? scope : __get_current_scope__ ()); + it++; + } + } - octave_value retval = xfind (search_scope, args); + if (retval.is_undefined ()) + { + // Search for built-in functions that are declared to + // handle specific types. + + if (built_in_function.is_defined ()) + { + octave_function *fcn = built_in_function.function_value (); - if (retval.is_undefined ()) - { - // It is possible that the user created a file on the fly since - // the last prompt or chdir, so try updating the load path and - // searching again. + if (fcn && fcn->handles_dispatch_class (dispatch_type)) + { + retval = built_in_function; - load_path& lp = __get_load_path__ (); - - lp.update (); - - retval = xfind (search_scope, args); - } + class_methods[dispatch_type] = retval; + } + } + } + } + } - return retval; - } - + return retval; +} - static void - split_name_with_package (const std::string& name, std::string& fname, - std::string& pname) - { - std::size_t pos = name.rfind ('.'); +// :-) JWE, can you parse this? Returns a 2D array with second dimension equal +// to btyp_num_types (static constant). Only the leftmost dimension can be +// variable in C/C++. Typedefs are boring. - fname.clear (); - pname.clear (); - - if (pos != std::string::npos) +static builtin_type_t (* build_sup_table (void))[btyp_num_types] +{ + static builtin_type_t sup_table[btyp_num_types][btyp_num_types]; + for (int i = 0; i < btyp_num_types; i++) + for (int j = 0; j < btyp_num_types; j++) { - fname = name.substr (pos + 1); - pname = name.substr (0, pos); - } - else - fname = name; - } - - // Check the load path to see if file that defined this is still - // visible. If the file is no longer visible, then erase the - // definition and move on. If the file is visible, then we also - // need to check to see whether the file has changed since the - // function was loaded/parsed. However, this check should only - // happen once per prompt (for files found from relative path - // elements, we also check if the working directory has changed - // since the last time the function was loaded/parsed). - // - // FIXME: perhaps this should be done for all loaded functions when - // the prompt is printed or the directory has changed, and then we - // would not check for it when finding symbol definitions. - - static inline bool - load_out_of_date_fcn (const std::string& file_name, - const std::string& dir_name_arg, - octave_value& function, - const std::string& dispatch_type = "", - const std::string& package_name = "") - { - bool retval = false; + builtin_type_t ityp = static_cast (i); + builtin_type_t jtyp = static_cast (j); + // FIXME: Is this really right? + bool use_j + = (jtyp == btyp_func_handle || ityp == btyp_bool + || (btyp_isarray (ityp) + && (! btyp_isarray (jtyp) + || (btyp_isinteger (jtyp) && ! btyp_isinteger (ityp)) + || ((ityp == btyp_double || ityp == btyp_complex + || ityp == btyp_char) + && (jtyp == btyp_float + || jtyp == btyp_float_complex))))); - std::string dir_name = dir_name_arg; - - if (dir_name.empty ()) - { - std::size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); - - dir_name = file_name.substr (0, pos); - } - - // FIXME: do the following job of determining private status and - // class membership in a separate function? - - std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); - - bool is_private_fcn - = pos != std::string::npos && dir_name.substr (pos+1) == "private"; - - if (is_private_fcn) - dir_name = dir_name.substr (0, pos); - - std::string class_name; - - pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); - - if (pos != std::string::npos) - { - std::string tmp = dir_name.substr (pos+1); - - if (tmp[0] == '@') - class_name = tmp.substr (1); + sup_table[i][j] = (use_j ? jtyp : ityp); } - octave_value ov_fcn - = load_fcn_from_file (file_name, dir_name, dispatch_type, - package_name); - - if (ov_fcn.is_defined ()) - { - retval = true; - - octave_function *fcn = ov_fcn.function_value (); - - if (is_private_fcn) - fcn->mark_as_private_function (class_name); - - function = ov_fcn; - } - else - function = octave_value (); - - return retval; - } - - static bool - out_of_date_check (octave_value& function, - const std::string& dispatch_type = "", - bool check_relative = true) - { - bool retval = false; - - octave_function *fcn = function.function_value (true); - - if (fcn) - { - // FIXME: we need to handle subfunctions properly here. - - if (! (fcn->is_subfunction () || fcn->is_anonymous_function ())) - { - std::string ff = fcn->fcn_file_name (); - - if (! ff.empty ()) - { - sys::time tc = fcn->time_checked (); - - bool relative = check_relative && fcn->is_relative (); - - if (tc <= Vlast_prompt_time - || (relative && tc < Vlast_chdir_time)) - { - bool clear_breakpoints = false; - std::string nm = fcn->name (); - std::string pack = fcn->package_name (); - std::string canonical_nm = fcn->canonical_name (); - - bool is_same_file = false; - - std::string file; - std::string dir_name; - - if (check_relative) - { - int nm_len = nm.length (); + return sup_table; +} - if (sys::env::absolute_pathname (nm) - && ((nm_len > 4 - && (nm.substr (nm_len-4) == ".oct" - || nm.substr (nm_len-4) == ".mex")) - || (nm_len > 2 - && nm.substr (nm_len-2) == ".m"))) - file = nm; - else - { - // We don't want to make this an absolute name, - // because load_fcn_file looks at the name to - // decide whether it came from a relative lookup. - - if (! dispatch_type.empty ()) - { - load_path& lp = __get_load_path__ (); - - file = lp.find_method (dispatch_type, nm, - dir_name, pack); - - if (file.empty ()) - { - std::string s_name; - std::string s_pack; - - symbol_table& symtab = __get_symbol_table__ (); - - const std::list& plist - = symtab.parent_classes (dispatch_type); - - std::list::const_iterator it - = plist.begin (); - - while (it != plist.end ()) - { - split_name_with_package (*it, s_name, - s_pack); +std::string +get_dispatch_type (const octave_value_list& args, + builtin_type_t& builtin_type) +{ + static builtin_type_t (*sup_table)[btyp_num_types] = build_sup_table (); + std::string dispatch_type; - file = lp.find_method (*it, nm, dir_name, - s_pack); - if (! file.empty ()) - { - pack = s_pack; - break; - } - - it++; - } - } - } - - // Maybe it's an autoload? - if (file.empty ()) - { - tree_evaluator& tw = __get_evaluator__ (); - - file = tw.lookup_autoload (nm); - } - - if (file.empty ()) - { - load_path& lp = __get_load_path__ (); - file = lp.find_fcn (nm, dir_name, pack); - } - } - - if (! file.empty ()) - is_same_file = same_file (file, ff); - } - else - { - is_same_file = true; - file = ff; - } - - if (file.empty ()) - { - // Can't see this function from current - // directory, so we should clear it. - - function = octave_value (); + int n = args.length (); - clear_breakpoints = true; - } - else if (is_same_file) - { - // Same file. If it is out of date, then reload it. - - sys::time ottp = fcn->time_parsed (); - OCTAVE_TIME_T tp = ottp.unix_time (); - - fcn->mark_fcn_file_up_to_date (sys::time ()); - - if (! (Vignore_function_time_stamp == 2 - || (Vignore_function_time_stamp - && fcn->is_system_fcn_file ()))) - { - sys::file_stat fs (ff); - - if (fs) - { - if (fs.is_newer (tp)) - { - retval = load_out_of_date_fcn (ff, dir_name, - function, - dispatch_type, - pack); - - clear_breakpoints = true; - } - } - else - { - function = octave_value (); - - clear_breakpoints = true; - } - } - } - else - { - // Not the same file, so load the new file in - // place of the old. - - retval = load_out_of_date_fcn (file, dir_name, function, - dispatch_type, pack); - - clear_breakpoints = true; - } - - // If the function has been replaced then clear any - // breakpoints associated with it - if (clear_breakpoints) - { - bp_table& bptab = __get_bp_table__ (); - - bptab.remove_all_breakpoints_from_function (canonical_nm, - true); - } - } - } - } - } - - return retval; - } - - octave_value - fcn_info::fcn_info_rep::find_scoped_function (const symbol_scope& search_scope) - { - if (search_scope) - { - // Subfunction. - - octave_value fcn = search_scope.find_subfunction (name); - - if (fcn.is_defined ()) - return fcn; + if (n > 0) + { + int i = 0; + builtin_type = args(0).builtin_type (); + if (builtin_type != btyp_unknown) + { + for (i = 1; i < n; i++) + { + builtin_type_t bti = args(i).builtin_type (); + if (bti != btyp_unknown) + builtin_type = sup_table[builtin_type][bti]; + else + { + builtin_type = btyp_unknown; + break; + } + } + } - // Local function. - - std::string fcn_file = search_scope.fcn_file_name (); - - // For anonymous functions we look at the parent scope so that if - // they were defined within class methods and use local functions - // (helper functions) we can still use those anonymous functions - - if (! fcn_file.empty ()) - { - auto r = local_functions.find (fcn_file); - - if (r != local_functions.end ()) - { - // We shouldn't need an out-of-date check here since - // local functions may ultimately be called only from - // a primary function or method defined in the same - // file. + if (builtin_type == btyp_unknown) + { + // There's a non-builtin class in the argument list. + dispatch_type = args(i).class_name (); - return r->second; - } - } - - // Private function. - - return find_private_function (search_scope.dir_name ()); - } - - return octave_value (); - } - - octave_value - fcn_info::fcn_info_rep::find_private_function (const std::string& dir_name) - { - if (! dir_name.empty ()) - { - auto q = private_functions.find (dir_name); + symbol_table& symtab = __get_symbol_table__ (); - if (q == private_functions.end ()) - { - octave_value val = load_private_function (dir_name); - - if (val.is_defined ()) - return val; - } - else - { - octave_value& fval = q->second; - - if (fval.is_defined ()) - out_of_date_check (fval, "", false); + for (int j = i+1; j < n; j++) + { + octave_value arg = args(j); - if (fval.is_defined ()) - return fval; - else - { - octave_value val = load_private_function (dir_name); - - if (val.is_defined ()) - return val; - } - } - } - - return octave_value (); - } - - octave_value - fcn_info::fcn_info_rep::find_method (const octave_value_list& args) - { - if (! args.empty ()) - { - std::string dispatch_type = get_dispatch_type (args); - - return find_method (dispatch_type); - } + if (arg.builtin_type () == btyp_unknown) + { + std::string cname = arg.class_name (); - return octave_value (); - } - - octave_value - fcn_info::fcn_info_rep::xfind (const symbol_scope& search_scope, - const octave_value_list& args) - { - // Subfunction, local function, or private function. - - octave_value fcn; - - fcn = find_scoped_function (search_scope); - - if (fcn.is_defined ()) - return fcn; - - // Class methods. - - fcn = find_method (args); - - if (fcn.is_defined ()) - return fcn; - - // Class constructors. The class name and function name are the same. - - auto q = class_constructors.find (name); - - if (q == class_constructors.end ()) - { - octave_value val = load_class_constructor (); - - if (val.is_defined ()) - return val; - } - else - { - octave_value& fval = q->second; - - if (fval.is_defined ()) - out_of_date_check (fval, name); - - if (fval.is_defined ()) - return fval; - else - { - octave_value val = load_class_constructor (); - - if (val.is_defined ()) - return val; - } - } - - // Command-line function. - - if (cmdline_function.is_defined ()) - return cmdline_function; - - // Autoload? - - fcn = find_autoload (); - - if (fcn.is_defined ()) - return fcn; - - // Function on the path. - - fcn = find_user_function (); - - if (fcn.is_defined ()) - return fcn; - - // Package + // Only switch to type of ARG if it is marked superior + // to the current DISPATCH_TYPE. + if (! symtab.is_superiorto (dispatch_type, cname) + && symtab.is_superiorto (cname, dispatch_type)) + dispatch_type = cname; + } + } + } + else + dispatch_type = btyp_class_name[builtin_type]; + } + else + builtin_type = btyp_unknown; - fcn = find_package (); - - if (fcn.is_defined ()) - return fcn; - - // Built-in function (might be undefined). - - return built_in_function; - } - - // Find the definition of NAME according to the following precedence - // list: - // - // built-in function - // function on the path - // autoload function - // command-line function - // private function - // subfunction - - // This function is used to implement the "builtin" function, which - // searches for "built-in" functions. In Matlab, "builtin" only - // returns functions that are actually built-in to the interpreter. - // But since the list of built-in functions is different in Octave and - // Matlab, we also search up the precedence list until we find - // something that matches. Note that we are only searching by name, - // so class methods and constructors are skipped. - - octave_value - fcn_info::fcn_info_rep::builtin_find (const symbol_scope& scope) - { - symbol_scope search_scope - = (scope - ? scope : __get_current_scope__ ()); - - octave_value retval = x_builtin_find (search_scope); + return dispatch_type; +} - if (! retval.is_defined ()) - { - // It is possible that the user created a file on the fly since - // the last prompt or chdir, so try updating the load path and - // searching again. - - load_path& lp = __get_load_path__ (); - - lp.update (); - - retval = x_builtin_find (search_scope); - } - - return retval; - } - - octave_value - fcn_info::fcn_info_rep::x_builtin_find (const symbol_scope& search_scope) - { - // Built-in function. - if (built_in_function.is_defined ()) - return built_in_function; - - // Function on the path. - - octave_value fcn = find_user_function (); - - if (fcn.is_defined ()) - return fcn; - - // Autoload? - - fcn = find_autoload (); - - if (fcn.is_defined ()) - return fcn; - - // Command-line function. +std::string +get_dispatch_type (const octave_value_list& args) +{ + builtin_type_t builtin_type; + return get_dispatch_type (args, builtin_type); +} - if (cmdline_function.is_defined ()) - return cmdline_function; - - // Private function, local function, or subfunction. - - if (search_scope) - { - // Private function. - - std::string dir_name = search_scope.dir_name (); - - if (! dir_name.empty ()) - { - auto q = private_functions.find (dir_name); - - if (q == private_functions.end ()) - { - octave_value val = load_private_function (dir_name); - - if (val.is_defined ()) - return val; - } - else - { - octave_value& fval = q->second; - - if (fval.is_defined ()) - out_of_date_check (fval); - - if (fval.is_defined ()) - return fval; - else - { - octave_value val = load_private_function (dir_name); - - if (val.is_defined ()) - return val; - } - } - } - - // Local function. - - std::string fcn_file = search_scope.fcn_file_name (); - - if (! fcn_file.empty ()) - { - auto r = local_functions.find (fcn_file); - - if (r != local_functions.end ()) - { - // We shouldn't need an out-of-date check here since local - // functions may ultimately be called only from a primary - // function or method defined in the same file. - - return r->second; - } - } - - // Subfunction. I think it only makes sense to check for - // subfunctions if we are currently executing a function defined - // from a .m file. - - octave_value val = search_scope.find_subfunction (name); - - if (val.is_defined ()) - return val; - } - - return octave_value (); - } +// Find function definition according to the following precedence list: +// +// nested functions (and subfunctions) +// local functions in the current file +// private function +// class method +// class constructor +// command-line function +// autoload function +// functions on the load_path (current directory is always first) +// package (FIXME: does this belong here?) +// built-in function - octave_value - fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type) - { - octave_value retval; - - auto q = class_methods.find (dispatch_type); - - if (q == class_methods.end ()) - { - octave_value val = load_class_method (dispatch_type); - - if (val.is_defined ()) - return val; - } - else - { - octave_value& fval = q->second; +octave_value +fcn_info::fcn_info_rep::find (const symbol_scope& scope, + const octave_value_list& args) +{ + symbol_scope search_scope + = (scope + ? scope : __get_current_scope__ ()); - if (fval.is_defined ()) - out_of_date_check (fval, dispatch_type); - - if (fval.is_defined ()) - return fval; - else - { - octave_value val = load_class_method (dispatch_type); - - if (val.is_defined ()) - return val; - } - } - - return retval; - } - - octave_value - fcn_info::fcn_info_rep::find_autoload (void) - { - // Autoloaded function. + octave_value retval = xfind (search_scope, args); - if (autoload_function.is_defined ()) - out_of_date_check (autoload_function); - - if (! autoload_function.is_defined ()) - { - tree_evaluator& tw = __get_evaluator__ (); - - std::string file_name = tw.lookup_autoload (name); + if (retval.is_undefined ()) + { + // It is possible that the user created a file on the fly since + // the last prompt or chdir, so try updating the load path and + // searching again. - if (! file_name.empty ()) - { - std::size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); - - std::string dir_name = file_name.substr (0, pos); - - octave_value ov_fcn - = load_fcn_from_file (file_name, dir_name, "", "", name, true); + load_path& lp = __get_load_path__ (); - if (ov_fcn.is_defined ()) - autoload_function = octave_value (ov_fcn); - } - } - - return autoload_function; - } + lp.update (); - octave_value - fcn_info::fcn_info_rep::find_user_function (void) - { - // Function on the path. + retval = xfind (search_scope, args); + } - if (function_on_path.is_defined ()) - out_of_date_check (function_on_path); - - if (function_on_path.is_undefined ()) - { - std::string dir_name; - - load_path& lp = __get_load_path__ (); + return retval; +} - std::string file_name = lp.find_fcn (name, dir_name, package_name); +static void +split_name_with_package (const std::string& name, std::string& fname, + std::string& pname) +{ + std::size_t pos = name.rfind ('.'); + + fname.clear (); + pname.clear (); + + if (pos != std::string::npos) + { + fname = name.substr (pos + 1); + pname = name.substr (0, pos); + } + else + fname = name; +} + +// Check the load path to see if file that defined this is still +// visible. If the file is no longer visible, then erase the +// definition and move on. If the file is visible, then we also +// need to check to see whether the file has changed since the +// function was loaded/parsed. However, this check should only +// happen once per prompt (for files found from relative path +// elements, we also check if the working directory has changed +// since the last time the function was loaded/parsed). +// +// FIXME: perhaps this should be done for all loaded functions when +// the prompt is printed or the directory has changed, and then we +// would not check for it when finding symbol definitions. + +static inline bool +load_out_of_date_fcn (const std::string& file_name, + const std::string& dir_name_arg, + octave_value& function, + const std::string& dispatch_type = "", + const std::string& package_name = "") +{ + bool retval = false; + + std::string dir_name = dir_name_arg; + + if (dir_name.empty ()) + { + std::size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); - if (! file_name.empty ()) - { - octave_value ov_fcn - = load_fcn_from_file (file_name, dir_name, "", package_name); + dir_name = file_name.substr (0, pos); + } + + // FIXME: do the following job of determining private status and + // class membership in a separate function? + + std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); + + bool is_private_fcn + = pos != std::string::npos && dir_name.substr (pos+1) == "private"; + + if (is_private_fcn) + dir_name = dir_name.substr (0, pos); + + std::string class_name; + + pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); + + if (pos != std::string::npos) + { + std::string tmp = dir_name.substr (pos+1); + + if (tmp[0] == '@') + class_name = tmp.substr (1); + } + + octave_value ov_fcn + = load_fcn_from_file (file_name, dir_name, dispatch_type, + package_name); + + if (ov_fcn.is_defined ()) + { + retval = true; + + octave_function *fcn = ov_fcn.function_value (); + + if (is_private_fcn) + fcn->mark_as_private_function (class_name); + + function = ov_fcn; + } + else + function = octave_value (); + + return retval; +} - if (ov_fcn.is_defined ()) - function_on_path = ov_fcn; - } - } +static bool +out_of_date_check (octave_value& function, + const std::string& dispatch_type = "", + bool check_relative = true) +{ + bool retval = false; + + octave_function *fcn = function.function_value (true); + + if (fcn) + { + // FIXME: we need to handle subfunctions properly here. + + if (! (fcn->is_subfunction () || fcn->is_anonymous_function ())) + { + std::string ff = fcn->fcn_file_name (); + + if (! ff.empty ()) + { + sys::time tc = fcn->time_checked (); + + bool relative = check_relative && fcn->is_relative (); + + if (tc <= Vlast_prompt_time + || (relative && tc < Vlast_chdir_time)) + { + bool clear_breakpoints = false; + std::string nm = fcn->name (); + std::string pack = fcn->package_name (); + std::string canonical_nm = fcn->canonical_name (); + + bool is_same_file = false; + + std::string file; + std::string dir_name; + + if (check_relative) + { + int nm_len = nm.length (); - return function_on_path; - } + if (sys::env::absolute_pathname (nm) + && ((nm_len > 4 + && (nm.substr (nm_len-4) == ".oct" + || nm.substr (nm_len-4) == ".mex")) + || (nm_len > 2 + && nm.substr (nm_len-2) == ".m"))) + file = nm; + else + { + // We don't want to make this an absolute name, + // because load_fcn_file looks at the name to + // decide whether it came from a relative lookup. + + if (! dispatch_type.empty ()) + { + load_path& lp = __get_load_path__ (); + + file = lp.find_method (dispatch_type, nm, + dir_name, pack); + + if (file.empty ()) + { + std::string s_name; + std::string s_pack; + + symbol_table& symtab = __get_symbol_table__ (); + + const std::list& plist + = symtab.parent_classes (dispatch_type); + + std::list::const_iterator it + = plist.begin (); + + while (it != plist.end ()) + { + split_name_with_package (*it, s_name, + s_pack); + + file = lp.find_method (*it, nm, dir_name, + s_pack); + if (! file.empty ()) + { + pack = s_pack; + break; + } + + it++; + } + } + } + + // Maybe it's an autoload? + if (file.empty ()) + { + tree_evaluator& tw = __get_evaluator__ (); - octave_value - fcn_info::fcn_info_rep::find_package (void) - { - // FIXME: implement correct way to check out of date package - //if (package.is_defined ()) - // out_of_date_check (package); + file = tw.lookup_autoload (nm); + } + + if (file.empty ()) + { + load_path& lp = __get_load_path__ (); + file = lp.find_fcn (nm, dir_name, pack); + } + } + + if (! file.empty ()) + is_same_file = same_file (file, ff); + } + else + { + is_same_file = true; + file = ff; + } + + if (file.empty ()) + { + // Can't see this function from current + // directory, so we should clear it. + + function = octave_value (); + + clear_breakpoints = true; + } + else if (is_same_file) + { + // Same file. If it is out of date, then reload it. + + sys::time ottp = fcn->time_parsed (); + OCTAVE_TIME_T tp = ottp.unix_time (); + + fcn->mark_fcn_file_up_to_date (sys::time ()); + + if (! (Vignore_function_time_stamp == 2 + || (Vignore_function_time_stamp + && fcn->is_system_fcn_file ()))) + { + sys::file_stat fs (ff); - if (package.is_undefined ()) - { - cdef_manager& cdm = __get_cdef_manager__ (); + if (fs) + { + if (fs.is_newer (tp)) + { + retval = load_out_of_date_fcn (ff, dir_name, + function, + dispatch_type, + pack); + + clear_breakpoints = true; + } + } + else + { + function = octave_value (); + + clear_breakpoints = true; + } + } + } + else + { + // Not the same file, so load the new file in + // place of the old. + + retval = load_out_of_date_fcn (file, dir_name, function, + dispatch_type, pack); + + clear_breakpoints = true; + } + + // If the function has been replaced then clear any + // breakpoints associated with it + if (clear_breakpoints) + { + bp_table& bptab = __get_bp_table__ (); + + bptab.remove_all_breakpoints_from_function (canonical_nm, + true); + } + } + } + } + } + + return retval; +} - package = cdm.find_package_symbol (full_name ()); - } +octave_value +fcn_info::fcn_info_rep::find_scoped_function (const symbol_scope& search_scope) +{ + if (search_scope) + { + // Subfunction. + + octave_value fcn = search_scope.find_subfunction (name); + + if (fcn.is_defined ()) + return fcn; + + // Local function. + + std::string fcn_file = search_scope.fcn_file_name (); + + // For anonymous functions we look at the parent scope so that if + // they were defined within class methods and use local functions + // (helper functions) we can still use those anonymous functions + + if (! fcn_file.empty ()) + { + auto r = local_functions.find (fcn_file); - return package; - } + if (r != local_functions.end ()) + { + // We shouldn't need an out-of-date check here since + // local functions may ultimately be called only from + // a primary function or method defined in the same + // file. + + return r->second; + } + } + + // Private function. + + return find_private_function (search_scope.dir_name ()); + } + + return octave_value (); +} + +octave_value +fcn_info::fcn_info_rep::find_private_function (const std::string& dir_name) +{ + if (! dir_name.empty ()) + { + auto q = private_functions.find (dir_name); - void - fcn_info::fcn_info_rep::install_built_in_dispatch (const std::string& klass) - { - if (built_in_function.is_defined ()) - { - octave_function *fcn = built_in_function.function_value (); + if (q == private_functions.end ()) + { + octave_value val = load_private_function (dir_name); + + if (val.is_defined ()) + return val; + } + else + { + octave_value& fval = q->second; + + if (fval.is_defined ()) + out_of_date_check (fval, "", false); + + if (fval.is_defined ()) + return fval; + else + { + octave_value val = load_private_function (dir_name); + + if (val.is_defined ()) + return val; + } + } + } + + return octave_value (); +} + +octave_value +fcn_info::fcn_info_rep::find_method (const octave_value_list& args) +{ + if (! args.empty ()) + { + std::string dispatch_type = get_dispatch_type (args); + + return find_method (dispatch_type); + } + + return octave_value (); +} + +octave_value +fcn_info::fcn_info_rep::xfind (const symbol_scope& search_scope, + const octave_value_list& args) +{ + // Subfunction, local function, or private function. + + octave_value fcn; - if (fcn) - { - if (fcn->handles_dispatch_class (klass)) - warning ("install_built_in_dispatch: '%s' already defined for class '%s'", - name.c_str (), klass.c_str ()); - else - fcn->push_dispatch_class (klass); - } - } - else - error ("install_built_in_dispatch: '%s' is not a built-in function", - name.c_str ()); - } + fcn = find_scoped_function (search_scope); + + if (fcn.is_defined ()) + return fcn; + + // Class methods. + + fcn = find_method (args); + + if (fcn.is_defined ()) + return fcn; + + // Class constructors. The class name and function name are the same. + + auto q = class_constructors.find (name); + + if (q == class_constructors.end ()) + { + octave_value val = load_class_constructor (); + + if (val.is_defined ()) + return val; + } + else + { + octave_value& fval = q->second; + + if (fval.is_defined ()) + out_of_date_check (fval, name); + + if (fval.is_defined ()) + return fval; + else + { + octave_value val = load_class_constructor (); + + if (val.is_defined ()) + return val; + } + } + + // Command-line function. + + if (cmdline_function.is_defined ()) + return cmdline_function; + + // Autoload? + + fcn = find_autoload (); + + if (fcn.is_defined ()) + return fcn; + + // Function on the path. + + fcn = find_user_function (); + + if (fcn.is_defined ()) + return fcn; + + // Package + + fcn = find_package (); + + if (fcn.is_defined ()) + return fcn; + + // Built-in function (might be undefined). + + return built_in_function; +} + +// Find the definition of NAME according to the following precedence +// list: +// +// built-in function +// function on the path +// autoload function +// command-line function +// private function +// subfunction + +// This function is used to implement the "builtin" function, which +// searches for "built-in" functions. In Matlab, "builtin" only +// returns functions that are actually built-in to the interpreter. +// But since the list of built-in functions is different in Octave and +// Matlab, we also search up the precedence list until we find +// something that matches. Note that we are only searching by name, +// so class methods and constructors are skipped. + +octave_value +fcn_info::fcn_info_rep::builtin_find (const symbol_scope& scope) +{ + symbol_scope search_scope + = (scope + ? scope : __get_current_scope__ ()); + + octave_value retval = x_builtin_find (search_scope); + + if (! retval.is_defined ()) + { + // It is possible that the user created a file on the fly since + // the last prompt or chdir, so try updating the load path and + // searching again. + + load_path& lp = __get_load_path__ (); + + lp.update (); + + retval = x_builtin_find (search_scope); + } + + return retval; +} + +octave_value +fcn_info::fcn_info_rep::x_builtin_find (const symbol_scope& search_scope) +{ + // Built-in function. + if (built_in_function.is_defined ()) + return built_in_function; + + // Function on the path. + + octave_value fcn = find_user_function (); + + if (fcn.is_defined ()) + return fcn; + + // Autoload? + + fcn = find_autoload (); + + if (fcn.is_defined ()) + return fcn; + + // Command-line function. + + if (cmdline_function.is_defined ()) + return cmdline_function; + + // Private function, local function, or subfunction. + + if (search_scope) + { + // Private function. + + std::string dir_name = search_scope.dir_name (); + + if (! dir_name.empty ()) + { + auto q = private_functions.find (dir_name); + + if (q == private_functions.end ()) + { + octave_value val = load_private_function (dir_name); + + if (val.is_defined ()) + return val; + } + else + { + octave_value& fval = q->second; + + if (fval.is_defined ()) + out_of_date_check (fval); + + if (fval.is_defined ()) + return fval; + else + { + octave_value val = load_private_function (dir_name); + + if (val.is_defined ()) + return val; + } + } + } + + // Local function. + + std::string fcn_file = search_scope.fcn_file_name (); + + if (! fcn_file.empty ()) + { + auto r = local_functions.find (fcn_file); - octave_value - fcn_info::fcn_info_rep::dump (void) const - { - std::map m - = {{ "name", full_name () }, - { "package", package.dump () }, - { "local_functions", dump_function_map (local_functions) }, - { "private_functions", dump_function_map (private_functions) }, - { "class_methods", dump_function_map (class_methods) }, - { "class_constructors", dump_function_map (class_constructors) }, - { "cmdline_function", cmdline_function.dump () }, - { "autoload_function", autoload_function.dump () }, - { "function_on_path", function_on_path.dump () }, - { "built_in_function", built_in_function.dump () }}; + if (r != local_functions.end ()) + { + // We shouldn't need an out-of-date check here since local + // functions may ultimately be called only from a primary + // function or method defined in the same file. + + return r->second; + } + } + + // Subfunction. I think it only makes sense to check for + // subfunctions if we are currently executing a function defined + // from a .m file. + + octave_value val = search_scope.find_subfunction (name); + + if (val.is_defined ()) + return val; + } + + return octave_value (); +} + +octave_value +fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type) +{ + octave_value retval; + + auto q = class_methods.find (dispatch_type); + + if (q == class_methods.end ()) + { + octave_value val = load_class_method (dispatch_type); + + if (val.is_defined ()) + return val; + } + else + { + octave_value& fval = q->second; + + if (fval.is_defined ()) + out_of_date_check (fval, dispatch_type); - return octave_value (m); - } + if (fval.is_defined ()) + return fval; + else + { + octave_value val = load_class_method (dispatch_type); + + if (val.is_defined ()) + return val; + } + } + + return retval; +} + +octave_value +fcn_info::fcn_info_rep::find_autoload (void) +{ + // Autoloaded function. + + if (autoload_function.is_defined ()) + out_of_date_check (autoload_function); + + if (! autoload_function.is_defined ()) + { + tree_evaluator& tw = __get_evaluator__ (); + + std::string file_name = tw.lookup_autoload (name); + + if (! file_name.empty ()) + { + std::size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); + + std::string dir_name = file_name.substr (0, pos); + + octave_value ov_fcn + = load_fcn_from_file (file_name, dir_name, "", "", name, true); + + if (ov_fcn.is_defined ()) + autoload_function = octave_value (ov_fcn); + } + } + + return autoload_function; +} + +octave_value +fcn_info::fcn_info_rep::find_user_function (void) +{ + // Function on the path. + + if (function_on_path.is_defined ()) + out_of_date_check (function_on_path); - octave_value - dump_function_map (const std::map& fcn_map) - { - if (fcn_map.empty ()) - return octave_value (Matrix ()); + if (function_on_path.is_undefined ()) + { + std::string dir_name; + + load_path& lp = __get_load_path__ (); + + + std::string file_name = lp.find_fcn (name, dir_name, package_name); + + if (! file_name.empty ()) + { + octave_value ov_fcn + = load_fcn_from_file (file_name, dir_name, "", package_name); + + if (ov_fcn.is_defined ()) + function_on_path = ov_fcn; + } + } + + return function_on_path; +} - std::map info_map; +octave_value +fcn_info::fcn_info_rep::find_package (void) +{ + // FIXME: implement correct way to check out of date package + //if (package.is_defined ()) + // out_of_date_check (package); + + if (package.is_undefined ()) + { + cdef_manager& cdm = __get_cdef_manager__ (); + + package = cdm.find_package_symbol (full_name ()); + } + + return package; +} + +void +fcn_info::fcn_info_rep::install_built_in_dispatch (const std::string& klass) +{ + if (built_in_function.is_defined ()) + { + octave_function *fcn = built_in_function.function_value (); - for (const auto& nm_fcn : fcn_map) - { - std::string nm = nm_fcn.first; - const octave_value& fcn = nm_fcn.second; - info_map[nm] = fcn.dump (); - } + if (fcn) + { + if (fcn->handles_dispatch_class (klass)) + warning ("install_built_in_dispatch: '%s' already defined for class '%s'", + name.c_str (), klass.c_str ()); + else + fcn->push_dispatch_class (klass); + } + } + else + error ("install_built_in_dispatch: '%s' is not a built-in function", + name.c_str ()); +} - return octave_value (info_map); - } +octave_value +fcn_info::fcn_info_rep::dump (void) const +{ + std::map m + = {{ "name", full_name () }, + { "package", package.dump () }, + { "local_functions", dump_function_map (local_functions) }, + { "private_functions", dump_function_map (private_functions) }, + { "class_methods", dump_function_map (class_methods) }, + { "class_constructors", dump_function_map (class_constructors) }, + { "cmdline_function", cmdline_function.dump () }, + { "autoload_function", autoload_function.dump () }, + { "function_on_path", function_on_path.dump () }, + { "built_in_function", built_in_function.dump () } + }; + + return octave_value (m); +} + +octave_value +dump_function_map (const std::map& fcn_map) +{ + if (fcn_map.empty ()) + return octave_value (Matrix ()); + + std::map info_map; + + for (const auto& nm_fcn : fcn_map) + { + std::string nm = nm_fcn.first; + const octave_value& fcn = nm_fcn.second; + info_map[nm] = fcn.dump (); + } + + return octave_value (info_map); +} DEFUN (ignore_function_time_stamp, args, nargout, doc: /* -*- texinfo -*- @@ -1182,7 +1183,8 @@ if (nargin == 1) { - std::string sval = args(0).xstring_value ("ignore_function_time_stamp: first argument must be a string"); + std::string sval = args( + 0).xstring_value ("ignore_function_time_stamp: first argument must be a string"); if (sval == "all") Vignore_function_time_stamp = 2; diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/fcn-info.h --- a/libinterp/corefcn/fcn-info.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/fcn-info.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,332 +39,332 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class fcn_info +class fcn_info +{ +public: + + typedef std::map::const_iterator + str_val_const_iterator; + typedef std::map::iterator str_val_iterator; + +private: + + class fcn_info_rep { public: - typedef std::map::const_iterator - str_val_const_iterator; - typedef std::map::iterator str_val_iterator; - - private: - - class fcn_info_rep + fcn_info_rep (const std::string& nm) + : name (nm), package_name (), local_functions (), + private_functions (), class_constructors (), class_methods (), + cmdline_function (), autoload_function (), function_on_path (), + built_in_function () { - public: - - fcn_info_rep (const std::string& nm) - : name (nm), package_name (), local_functions (), - private_functions (), class_constructors (), class_methods (), - cmdline_function (), autoload_function (), function_on_path (), - built_in_function () - { - std::size_t pos = name.rfind ('.'); - - if (pos != std::string::npos) - { - package_name = name.substr (0, pos); - name = name.substr (pos+1); - } - } - - // No copying! - - fcn_info_rep (const fcn_info_rep&) = delete; - - fcn_info_rep& operator = (const fcn_info_rep&) = delete; - - ~fcn_info_rep (void) = default; - - octave_value install_local_function (const std::string& file_name); - - octave_value load_private_function (const std::string& dir_name); - - octave_value load_class_constructor (void); - - octave_value load_class_method (const std::string& dispatch_type); - - octave_value find (const symbol_scope& search_scope, - const octave_value_list& args); - - octave_value builtin_find (const symbol_scope& search_scope); - - octave_value find_scoped_function (const symbol_scope& search_scope); - - octave_value find_private_function (const std::string& dir_name); + std::size_t pos = name.rfind ('.'); - octave_value find_method (const std::string& dispatch_type); - - octave_value find_method (const octave_value_list& args); - - octave_value find_autoload (void); - - octave_value find_package (void); - - octave_value find_user_function (void); - - bool is_user_function_defined (void) const - { - return function_on_path.is_defined (); - } - - octave_value find_function (const symbol_scope& search_scope, - const octave_value_list& args) - { - return find (search_scope, args); - } - - void install_cmdline_function (const octave_value& f) - { - cmdline_function = f; - } - - void install_local_function (const octave_value& f, - const std::string& file_name) - { - local_functions[file_name] = f; - } - - void install_user_function (const octave_value& f) - { - function_on_path = f; - } - - void install_built_in_function (const octave_value& f) - { - built_in_function = f; - } - - void install_built_in_dispatch (const std::string& klass); - - template - void - clear_map (std::map& map, bool force = false) - { - auto p = map.begin (); + if (pos != std::string::npos) + { + package_name = name.substr (0, pos); + name = name.substr (pos+1); + } + } - while (p != map.end ()) - { - if (force || ! p->second.islocked ()) - map.erase (p++); - else - p++; - } - } + // No copying! - void clear_autoload_function (bool force = false) - { - if (force || ! autoload_function.islocked ()) - autoload_function = octave_value (); - } - - // We also clear command line functions here, as these are both - // "user defined" - void clear_user_function (bool force = false) - { - clear_autoload_function (force); - - if (force || ! function_on_path.islocked ()) - function_on_path = octave_value (); + fcn_info_rep (const fcn_info_rep&) = delete; - if (force || ! cmdline_function.islocked ()) - cmdline_function = octave_value (); - } - - void clear_mex_function (void) - { - if (function_on_path.is_mex_function ()) - clear_user_function (); - } + fcn_info_rep& operator = (const fcn_info_rep&) = delete; - void clear_package (void) - { - package = octave_value (); - } - - void clear (bool force = false) - { - clear_map (local_functions, force); - clear_map (private_functions, force); - clear_map (class_constructors, force); - clear_map (class_methods, force); - - clear_autoload_function (force); - clear_user_function (force); - clear_package (); - } - - octave_value dump (void) const; + ~fcn_info_rep (void) = default; - std::string full_name (void) const - { - if (package_name.empty ()) - return name; - else - return package_name + '.' + name; - } - - std::string name; - - std::string package_name; + octave_value install_local_function (const std::string& file_name); - // File name to function object. - std::map local_functions; - - // Directory name to function object. - std::map private_functions; - - // Class name to function object. - std::map class_constructors; - - // Dispatch type to function object. - std::map class_methods; - - octave_value cmdline_function; + octave_value load_private_function (const std::string& dir_name); - octave_value autoload_function; - - octave_value function_on_path; - - octave_value package; - - octave_value built_in_function; - - private: - - octave_value xfind (const symbol_scope& search_scope, - const octave_value_list& args); + octave_value load_class_constructor (void); - octave_value x_builtin_find (const symbol_scope& search_scope); - }; - - public: - - fcn_info (const std::string& nm = "") - : m_rep (new fcn_info_rep (nm)) { } - - fcn_info (const fcn_info&) = default; - - fcn_info& operator = (const fcn_info&) = default; - - ~fcn_info (void) = default; + octave_value load_class_method (const std::string& dispatch_type); octave_value find (const symbol_scope& search_scope, - const octave_value_list& args = octave_value_list ()) - { - return m_rep->find (search_scope, args); - } + const octave_value_list& args); + + octave_value builtin_find (const symbol_scope& search_scope); - octave_value - builtin_find (const symbol_scope& search_scope) - { - return m_rep->builtin_find (search_scope); - } + octave_value find_scoped_function (const symbol_scope& search_scope); - octave_value find_scoped_function (const symbol_scope& search_scope) const - { - return m_rep->find_scoped_function (search_scope); - } - - octave_value find_private_function (const std::string& dir_name) const - { - return m_rep->find_private_function (dir_name); - } + octave_value find_private_function (const std::string& dir_name); - octave_value find_method (const std::string& dispatch_type) const - { - return m_rep->find_method (dispatch_type); - } + octave_value find_method (const std::string& dispatch_type); - octave_value find_built_in_function (void) const - { - return m_rep->built_in_function; - } + octave_value find_method (const octave_value_list& args); - octave_value find_cmdline_function (void) const - { - return m_rep->cmdline_function; - } + octave_value find_autoload (void); - octave_value find_autoload (void) - { - return m_rep->find_autoload (); - } + octave_value find_package (void); - // FIXME: find_function_on_path might be a better name? - octave_value find_user_function (void) - { - return m_rep->find_user_function (); - } + octave_value find_user_function (void); bool is_user_function_defined (void) const { - return m_rep->is_user_function_defined (); + return function_on_path.is_defined (); } - octave_value - find_function (const symbol_scope& search_scope, - const octave_value_list& args = octave_value_list ()) + octave_value find_function (const symbol_scope& search_scope, + const octave_value_list& args) { - return m_rep->find_function (search_scope, args); + return find (search_scope, args); } void install_cmdline_function (const octave_value& f) { - m_rep->install_cmdline_function (f); + cmdline_function = f; } void install_local_function (const octave_value& f, const std::string& file_name) { - m_rep->install_local_function (f, file_name); + local_functions[file_name] = f; } void install_user_function (const octave_value& f) { - m_rep->install_user_function (f); + function_on_path = f; } void install_built_in_function (const octave_value& f) { - m_rep->install_built_in_function (f); + built_in_function = f; } - void install_built_in_dispatch (const std::string& klass) + void install_built_in_dispatch (const std::string& klass); + + template + void + clear_map (std::map& map, bool force = false) { - m_rep->install_built_in_dispatch (klass); - } + auto p = map.begin (); - void clear (bool force = false) { m_rep->clear (force); } - - void clear_user_function (bool force = false) - { - m_rep->clear_user_function (force); + while (p != map.end ()) + { + if (force || ! p->second.islocked ()) + map.erase (p++); + else + p++; + } } void clear_autoload_function (bool force = false) { - m_rep->clear_autoload_function (force); + if (force || ! autoload_function.islocked ()) + autoload_function = octave_value (); + } + + // We also clear command line functions here, as these are both + // "user defined" + void clear_user_function (bool force = false) + { + clear_autoload_function (force); + + if (force || ! function_on_path.islocked ()) + function_on_path = octave_value (); + + if (force || ! cmdline_function.islocked ()) + cmdline_function = octave_value (); + } + + void clear_mex_function (void) + { + if (function_on_path.is_mex_function ()) + clear_user_function (); + } + + void clear_package (void) + { + package = octave_value (); } - void clear_mex_function (void) { m_rep->clear_mex_function (); } + void clear (bool force = false) + { + clear_map (local_functions, force); + clear_map (private_functions, force); + clear_map (class_constructors, force); + clear_map (class_methods, force); + + clear_autoload_function (force); + clear_user_function (force); + clear_package (); + } + + octave_value dump (void) const; + + std::string full_name (void) const + { + if (package_name.empty ()) + return name; + else + return package_name + '.' + name; + } + + std::string name; - octave_value dump (void) const { return m_rep->dump (); } + std::string package_name; + + // File name to function object. + std::map local_functions; + + // Directory name to function object. + std::map private_functions; + + // Class name to function object. + std::map class_constructors; + + // Dispatch type to function object. + std::map class_methods; + + octave_value cmdline_function; + + octave_value autoload_function; + + octave_value function_on_path; + + octave_value package; + + octave_value built_in_function; private: - std::shared_ptr m_rep; + octave_value xfind (const symbol_scope& search_scope, + const octave_value_list& args); + + octave_value x_builtin_find (const symbol_scope& search_scope); }; - extern OCTINTERP_API std::string - get_dispatch_type (const octave_value_list& args); +public: + + fcn_info (const std::string& nm = "") + : m_rep (new fcn_info_rep (nm)) { } + + fcn_info (const fcn_info&) = default; + + fcn_info& operator = (const fcn_info&) = default; + + ~fcn_info (void) = default; + + octave_value find (const symbol_scope& search_scope, + const octave_value_list& args = octave_value_list ()) + { + return m_rep->find (search_scope, args); + } + + octave_value + builtin_find (const symbol_scope& search_scope) + { + return m_rep->builtin_find (search_scope); + } + + octave_value find_scoped_function (const symbol_scope& search_scope) const + { + return m_rep->find_scoped_function (search_scope); + } + + octave_value find_private_function (const std::string& dir_name) const + { + return m_rep->find_private_function (dir_name); + } + + octave_value find_method (const std::string& dispatch_type) const + { + return m_rep->find_method (dispatch_type); + } + + octave_value find_built_in_function (void) const + { + return m_rep->built_in_function; + } + + octave_value find_cmdline_function (void) const + { + return m_rep->cmdline_function; + } + + octave_value find_autoload (void) + { + return m_rep->find_autoload (); + } + + // FIXME: find_function_on_path might be a better name? + octave_value find_user_function (void) + { + return m_rep->find_user_function (); + } + + bool is_user_function_defined (void) const + { + return m_rep->is_user_function_defined (); + } - extern OCTINTERP_API std::string - get_dispatch_type (const octave_value_list& args, - builtin_type_t& builtin_type); + octave_value + find_function (const symbol_scope& search_scope, + const octave_value_list& args = octave_value_list ()) + { + return m_rep->find_function (search_scope, args); + } + + void install_cmdline_function (const octave_value& f) + { + m_rep->install_cmdline_function (f); + } + + void install_local_function (const octave_value& f, + const std::string& file_name) + { + m_rep->install_local_function (f, file_name); + } + + void install_user_function (const octave_value& f) + { + m_rep->install_user_function (f); + } + + void install_built_in_function (const octave_value& f) + { + m_rep->install_built_in_function (f); + } - extern octave_value - dump_function_map (const std::map& fcn_map); + void install_built_in_dispatch (const std::string& klass) + { + m_rep->install_built_in_dispatch (klass); + } + + void clear (bool force = false) { m_rep->clear (force); } + + void clear_user_function (bool force = false) + { + m_rep->clear_user_function (force); + } + + void clear_autoload_function (bool force = false) + { + m_rep->clear_autoload_function (force); + } + + void clear_mex_function (void) { m_rep->clear_mex_function (); } + + octave_value dump (void) const { return m_rep->dump (); } + +private: + + std::shared_ptr m_rep; +}; + +extern OCTINTERP_API std::string +get_dispatch_type (const octave_value_list& args); + +extern OCTINTERP_API std::string +get_dispatch_type (const octave_value_list& args, + builtin_type_t& builtin_type); + +extern octave_value +dump_function_map (const std::map& fcn_map); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/fft.cc --- a/libinterp/corefcn/fft.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/fft.cc Thu Dec 01 20:05:44 2022 -0800 @@ -296,7 +296,7 @@ %! answer(n+1) = N/2; %! answer(N-n+1) = N/2; %! -%! assert (S, answer, 4*N*eps ("single")); +%! assert (S, answer, 4*N* eps ("single")); ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au) ## Comalco Research and Technology @@ -311,7 +311,7 @@ %! S(n+1) = N/2; %! S(N-n+1) = N/2; %! -%! assert (ifft (S), s, 4*N*eps ("single")); +%! assert (ifft (S), s, 4*N* eps ("single")); */ OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/fft2.cc --- a/libinterp/corefcn/fft2.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/fft2.cc Thu Dec 01 20:05:44 2022 -0800 @@ -235,7 +235,7 @@ %! s = kron (sx', sy); %! S = fft2 (s); %! answer = kron (fft (sx)', fft (sy)); -%! assert (S, answer, 4*M*N*eps ("single")); +%! assert (S, answer, 4*M*N* eps ("single")); ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au) ## Comalco Research and Technology @@ -257,7 +257,7 @@ %! answer = kron (sx', sy); %! s = ifft2 (S); %! -%! assert (s, answer, 30*eps ("single")); +%! assert (s, answer, 30* eps ("single")); */ OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/file-io.cc --- a/libinterp/corefcn/file-io.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/file-io.cc Thu Dec 01 20:05:44 2022 -0800 @@ -1014,7 +1014,7 @@ char type = (fmt_arg.is_sq_string () ? '\'' : '"'); retval(0) = (result.empty () ? octave_value (charMatrix (1, 0), type) - : octave_value (result, type)); + : octave_value (result, type)); return retval; } @@ -1169,8 +1169,8 @@ octave_idx_type count = 0; Array size = (nargin == 3) ? args(2).vector_value () - : Array (dim_vector (1, 1), - lo_ieee_inf_value ()); + : Array (dim_vector (1, 1), + lo_ieee_inf_value ()); octave_value tmp = os.scanf (args(1), size, count, who); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/filter.cc --- a/libinterp/corefcn/filter.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/filter.cc Thu Dec 01 20:05:44 2022 -0800 @@ -121,7 +121,7 @@ for (octave_idx_type num = 0; num < x_num; num++) { octave_idx_type x_offset = (x_stride == 1) ? num * x_len - : num + (num / x_stride) * x_stride * (x_len - 1); + : num + (num / x_stride) * x_stride * (x_len - 1); octave_idx_type si_offset = num * si_len; @@ -190,7 +190,7 @@ { octave_idx_type lo = u * num_inner; octave_idx_type hi = (lo + num_inner < num_execs-1) - ? lo + num_inner : num_execs-1; + ? lo + num_inner : num_execs-1; // Inner loop, no interruption for (octave_idx_type j = lo; j <= hi; j++) @@ -218,7 +218,7 @@ { octave_idx_type lo = u * num_inner; octave_idx_type hi = (lo + num_inner < num_execs-1) - ? lo + num_inner : num_execs-1; + ? lo + num_inner : num_execs-1; // Inner loop, no interruption for (octave_idx_type j = lo; j <= hi; j++) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/find.cc --- a/libinterp/corefcn/find.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/find.cc Thu Dec 01 20:05:44 2022 -0800 @@ -55,7 +55,7 @@ // The maximum element is always at the end. octave_idx_type iext = (idx.isempty () ? 0 - : idx.xelem (idx.numel () - 1) + 1); + : idx.xelem (idx.numel () - 1) + 1); switch (nargout) { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ft-text-renderer.cc --- a/libinterp/corefcn/ft-text-renderer.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ft-text-renderer.cc Thu Dec 01 20:05:44 2022 -0800 @@ -67,1465 +67,1465 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // FIXME: maybe issue at most one warning per glyph/font/size/weight - // combination. +// FIXME: maybe issue at most one warning per glyph/font/size/weight +// combination. - static void - warn_missing_glyph (FT_ULong c) - { - warning_with_id ("Octave:missing-glyph", - "text_renderer: skipping missing glyph for character '%lx'", c); - } +static void +warn_missing_glyph (FT_ULong c) +{ + warning_with_id ("Octave:missing-glyph", + "text_renderer: skipping missing glyph for character '%lx'", c); +} - static void - warn_glyph_render (FT_ULong c) - { - warning_with_id ("Octave:glyph-render", - "text_renderer: unable to render glyph for character '%lx'", c); - } +static void +warn_glyph_render (FT_ULong c) +{ + warning_with_id ("Octave:glyph-render", + "text_renderer: unable to render glyph for character '%lx'", c); +} #if defined (_MSC_VER) - // FIXME: is this really needed? - // - // This is just a trick to avoid multiple symbol definitions. - // PermMatrix.h contains a dllexport'ed Array - // that will cause MSVC not to generate a new instantiation and - // use the imported one instead. +// FIXME: is this really needed? +// +// This is just a trick to avoid multiple symbol definitions. +// PermMatrix.h contains a dllexport'ed Array +// that will cause MSVC not to generate a new instantiation and +// use the imported one instead. # include "PermMatrix.h" #endif - // Forward declaration - static void ft_face_destroyed (void *object); +// Forward declaration +static void ft_face_destroyed (void *object); - class - ft_manager - { - private: +class +ft_manager +{ +private: - ft_manager (void) - : m_library (), m_freetype_initialized (false), - m_fontconfig_initialized (false) - { - if (FT_Init_FreeType (&m_library)) - error ("unable to initialize FreeType library"); - else - m_freetype_initialized = true; + ft_manager (void) + : m_library (), m_freetype_initialized (false), + m_fontconfig_initialized (false) + { + if (FT_Init_FreeType (&m_library)) + error ("unable to initialize FreeType library"); + else + m_freetype_initialized = true; #if defined (HAVE_FONTCONFIG) - if (! FcInit ()) - error ("unable to initialize fontconfig library"); - else - m_fontconfig_initialized = true; + if (! FcInit ()) + error ("unable to initialize fontconfig library"); + else + m_fontconfig_initialized = true; #endif - } + } - public: +public: - // No copying! + // No copying! - ft_manager (const ft_manager&) = delete; + ft_manager (const ft_manager&) = delete; - ft_manager& operator = (const ft_manager&) = delete; + ft_manager& operator = (const ft_manager&) = delete; - private: +private: - ~ft_manager (void) - { - if (m_freetype_initialized) - FT_Done_FreeType (m_library); + ~ft_manager (void) + { + if (m_freetype_initialized) + FT_Done_FreeType (m_library); #if defined (HAVE_FONTCONFIG) - // FIXME: Skip the call to FcFini because it can trigger the assertion - // - // octave: fccache.c:507: FcCacheFini: Assertion 'fcCacheChains[i] == ((void *)0)' failed. - // - // if (m_fontconfig_initialized) - // FcFini (); + // FIXME: Skip the call to FcFini because it can trigger the assertion + // + // octave: fccache.c:507: FcCacheFini: Assertion 'fcCacheChains[i] == ((void *)0)' failed. + // + // if (m_fontconfig_initialized) + // FcFini (); #endif - } + } - public: +public: - static bool instance_ok (void) - { - bool retval = true; + static bool instance_ok (void) + { + bool retval = true; - if (! m_instance) - { - m_instance = new ft_manager (); - singleton_cleanup_list::add (cleanup_instance); - } + if (! m_instance) + { + m_instance = new ft_manager (); + singleton_cleanup_list::add (cleanup_instance); + } - return retval; - } + return retval; + } - static void cleanup_instance (void) - { delete m_instance; m_instance = nullptr; } + static void cleanup_instance (void) + { delete m_instance; m_instance = nullptr; } - static FT_Face get_font (const std::string& name, const std::string& weight, - const std::string& angle, double size, - FT_ULong c = 0) - { - return (instance_ok () - ? m_instance->do_get_font (name, weight, angle, size, c) - : nullptr); - } + static FT_Face get_font (const std::string& name, const std::string& weight, + const std::string& angle, double size, + FT_ULong c = 0) + { + return (instance_ok () + ? m_instance->do_get_font (name, weight, angle, size, c) + : nullptr); + } - static octave_map get_system_fonts (void) - { - return (instance_ok () - ? m_instance->do_get_system_fonts () - : octave_map ()); - } + static octave_map get_system_fonts (void) + { + return (instance_ok () + ? m_instance->do_get_system_fonts () + : octave_map ()); + } - static void font_destroyed (FT_Face face) - { - if (instance_ok ()) - m_instance->do_font_destroyed (face); - } + static void font_destroyed (FT_Face face) + { + if (instance_ok ()) + m_instance->do_font_destroyed (face); + } - private: +private: - typedef std::pair ft_key; - typedef std::map ft_cache; + typedef std::pair ft_key; + typedef std::map ft_cache; - static octave_map do_get_system_fonts (void) - { - static octave_map font_map; + static octave_map do_get_system_fonts (void) + { + static octave_map font_map; - if (font_map.isempty ()) - { + if (font_map.isempty ()) + { #if defined (HAVE_FONTCONFIG) - FcConfig *config = FcConfigGetCurrent(); - FcPattern *pat = FcPatternCreate (); - FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SLANT, FC_WEIGHT, - FC_CHARSET, nullptr); - FcFontSet *fs = FcFontList (config, pat, os); + FcConfig *config = FcConfigGetCurrent(); + FcPattern *pat = FcPatternCreate (); + FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, FC_SLANT, FC_WEIGHT, + FC_CHARSET, nullptr); + FcFontSet *fs = FcFontList (config, pat, os); - if (fs->nfont > 0) - { - // Mark fonts that have at least all printable ASCII chars - FcCharSet *minimal_charset = FcCharSetCreate (); - for (int i = 32; i < 127; i++) - FcCharSetAddChar (minimal_charset, static_cast (i)); + if (fs->nfont > 0) + { + // Mark fonts that have at least all printable ASCII chars + FcCharSet *minimal_charset = FcCharSetCreate (); + for (int i = 32; i < 127; i++) + FcCharSetAddChar (minimal_charset, static_cast (i)); - string_vector fields (4); - fields(0) = "family"; - fields(1) = "angle"; - fields(2) = "weight"; - fields(3) = "suitable"; + string_vector fields (4); + fields(0) = "family"; + fields(1) = "angle"; + fields(2) = "weight"; + fields(3) = "suitable"; - dim_vector dv (1, fs->nfont); - Cell families (dv); - Cell angles (dv); - Cell weights (dv); - Cell suitable (dv); + dim_vector dv (1, fs->nfont); + Cell families (dv); + Cell angles (dv); + Cell weights (dv); + Cell suitable (dv); - unsigned char *family; - int val; - for (int i = 0; fs && i < fs->nfont; i++) - { - FcPattern *font = fs->fonts[i]; - if (FcPatternGetString (font, FC_FAMILY, 0, &family) - == FcResultMatch) - families(i) = std::string (reinterpret_cast (family)); - else - families(i) = "unknown"; + unsigned char *family; + int val; + for (int i = 0; fs && i < fs->nfont; i++) + { + FcPattern *font = fs->fonts[i]; + if (FcPatternGetString (font, FC_FAMILY, 0, &family) + == FcResultMatch) + families(i) = std::string (reinterpret_cast (family)); + else + families(i) = "unknown"; - if (FcPatternGetInteger (font, FC_SLANT, 0, &val) - == FcResultMatch) - angles(i) = (val == FC_SLANT_ITALIC - || val == FC_SLANT_OBLIQUE) - ? "italic" : "normal"; - else - angles(i) = "unknown"; + if (FcPatternGetInteger (font, FC_SLANT, 0, &val) + == FcResultMatch) + angles(i) = (val == FC_SLANT_ITALIC + || val == FC_SLANT_OBLIQUE) + ? "italic" : "normal"; + else + angles(i) = "unknown"; - if (FcPatternGetInteger (font, FC_WEIGHT, 0, &val) - == FcResultMatch) - weights(i) = (val == FC_WEIGHT_BOLD - || val == FC_WEIGHT_DEMIBOLD) - ? "bold" : "normal"; - else - weights(i) = "unknown"; + if (FcPatternGetInteger (font, FC_WEIGHT, 0, &val) + == FcResultMatch) + weights(i) = (val == FC_WEIGHT_BOLD + || val == FC_WEIGHT_DEMIBOLD) + ? "bold" : "normal"; + else + weights(i) = "unknown"; - FcCharSet *cset; - if (FcPatternGetCharSet (font, FC_CHARSET, 0, &cset) - == FcResultMatch) - suitable(i) = (FcCharSetIsSubset (minimal_charset, cset) - ? true : false); - else - suitable(i) = false; - } + FcCharSet *cset; + if (FcPatternGetCharSet (font, FC_CHARSET, 0, &cset) + == FcResultMatch) + suitable(i) = (FcCharSetIsSubset (minimal_charset, cset) + ? true : false); + else + suitable(i) = false; + } - font_map = octave_map (dv, fields); + font_map = octave_map (dv, fields); - font_map.assign ("family", families); - font_map.assign ("angle", angles); - font_map.assign ("weight", weights); - font_map.assign ("suitable", suitable); + font_map.assign ("family", families); + font_map.assign ("angle", angles); + font_map.assign ("weight", weights); + font_map.assign ("suitable", suitable); - if (fs) - FcFontSetDestroy (fs); - } + if (fs) + FcFontSetDestroy (fs); + } #endif - } + } - return font_map; - } + return font_map; + } - FT_Face do_get_font (const std::string& name, const std::string& weight, - const std::string& angle, double size, - FT_ULong search_code_point) - { - FT_Face retval = nullptr; + FT_Face do_get_font (const std::string& name, const std::string& weight, + const std::string& angle, double size, + FT_ULong search_code_point) + { + FT_Face retval = nullptr; #if defined (HAVE_FT_REFERENCE_FACE) - // Look first into the font cache, then use fontconfig. If the font - // is present in the cache, simply add a reference and return it. - - ft_key key (name + ':' + weight + ':' + angle + ':' - + std::to_string (search_code_point), size); - ft_cache::const_iterator it = m_cache.find (key); - - if (it != m_cache.end ()) - { - FT_Reference_Face (it->second); - return it->second; - } -#endif - - static std::string fonts_dir; - - if (fonts_dir.empty ()) - { - fonts_dir = sys::env::getenv ("OCTAVE_FONTS_DIR"); - - if (fonts_dir.empty ()) -#if defined (SYSTEM_FREEFONT_DIR) - fonts_dir = SYSTEM_FREEFONT_DIR; -#else - fonts_dir = config::oct_fonts_dir (); -#endif - } - - - // Default font file - std::string file; - - if (! fonts_dir.empty ()) - { - file = fonts_dir + sys::file_ops::dir_sep_str () + "FreeSans"; - - if (weight == "bold") - file += "Bold"; - - if (angle == "italic" || angle == "oblique") - file += "Oblique"; - - file += ".otf"; - } - -#if defined (HAVE_FONTCONFIG) - if ((search_code_point != 0 || name != "*") && m_fontconfig_initialized) - { - int fc_weight, fc_angle; - - if (weight == "bold") - fc_weight = FC_WEIGHT_BOLD; - else - fc_weight = FC_WEIGHT_NORMAL; + // Look first into the font cache, then use fontconfig. If the font + // is present in the cache, simply add a reference and return it. - if (angle == "italic") - fc_angle = FC_SLANT_ITALIC; - else if (angle == "oblique") - fc_angle = FC_SLANT_OBLIQUE; - else - fc_angle = FC_SLANT_ROMAN; - - FcPattern *pat = FcPatternCreate (); - - FcPatternAddString (pat, FC_FAMILY, - (reinterpret_cast - (name.c_str ()))); - - FcPatternAddInteger (pat, FC_WEIGHT, fc_weight); - FcPatternAddInteger (pat, FC_SLANT, fc_angle); - FcPatternAddDouble (pat, FC_PIXEL_SIZE, size); - - if (search_code_point > 0) - { - FcCharSet *minimal_charset = FcCharSetCreate (); - FcCharSetAddChar (minimal_charset, - static_cast (search_code_point)); - FcPatternAddCharSet (pat, FC_CHARSET, minimal_charset); - } + ft_key key (name + ':' + weight + ':' + angle + ':' + + std::to_string (search_code_point), size); + ft_cache::const_iterator it = m_cache.find (key); - if (FcConfigSubstitute (nullptr, pat, FcMatchPattern)) - { - FcResult res; - FcPattern *match; - - FcDefaultSubstitute (pat); - - match = FcFontMatch (nullptr, pat, &res); - - // FIXME: originally, this test also required that - // res != FcResultNoMatch. Is that really needed? - if (match) - { - unsigned char *tmp; - - FcPatternGetString (match, FC_FILE, 0, &tmp); - file = reinterpret_cast (tmp); - } - else - ::warning ("could not match any font: %s-%s-%s-%g, using default font", - name.c_str (), weight.c_str (), angle.c_str (), - size); - - if (match) - FcPatternDestroy (match); - } - - FcPatternDestroy (pat); - } + if (it != m_cache.end ()) + { + FT_Reference_Face (it->second); + return it->second; + } #endif - if (file.empty ()) - ::warning ("unable to find default font files"); - else - { - std::string ascii_file = sys::get_ASCII_filename (file); - - if (FT_New_Face (m_library, ascii_file.c_str (), 0, &retval)) - ::warning ("ft_manager: unable to load font: %s", file.c_str ()); -#if defined (HAVE_FT_REFERENCE_FACE) - else - { - // Install a finalizer to notify ft_manager that the font is - // being destroyed. The class ft_manager only keeps weak - // references to font objects. + static std::string fonts_dir; - retval->generic.data = new ft_key (key); - retval->generic.finalizer = ft_face_destroyed; - - // Insert loaded font into the cache. - if (FT_Reference_Face (retval) == 0) - m_cache[key] = retval; - } -#endif - } - - return retval; - } - - void do_font_destroyed (FT_Face face) - { - if (face->generic.data) - { - ft_key *pkey = reinterpret_cast (face->generic.data); + if (fonts_dir.empty ()) + { + fonts_dir = sys::env::getenv ("OCTAVE_FONTS_DIR"); - m_cache.erase (*pkey); - delete pkey; - face->generic.data = nullptr; - FT_Done_Face (face); - } - } - - //-------- - - static ft_manager *m_instance; - - // Cache the fonts loaded by FreeType. This cache only contains - // weak references to the fonts, strong references are only present - // in class text_renderer. - ft_cache m_cache; - - FT_Library m_library; - bool m_freetype_initialized; - bool m_fontconfig_initialized; - }; + if (fonts_dir.empty ()) +#if defined (SYSTEM_FREEFONT_DIR) + fonts_dir = SYSTEM_FREEFONT_DIR; +#else + fonts_dir = config::oct_fonts_dir (); +#endif + } - ft_manager *ft_manager::m_instance = nullptr; - - static void - ft_face_destroyed (void *object) - { - ft_manager::font_destroyed (reinterpret_cast (object)); - } - - class - OCTINTERP_API - ft_text_renderer : public base_text_renderer - { - public: - - enum - { - MODE_BBOX = 0, - MODE_RENDER = 1 - }; - - public: - ft_text_renderer (void) - : base_text_renderer (), m_font (), m_bbox (1, 4, 0.0), m_halign (0), - m_xoffset (0), m_line_yoffset (0), m_yoffset (0), m_mode (MODE_BBOX), - m_color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (), - m_line_xoffset (0), m_ymin (0), m_ymax (0), m_deltax (0), - m_max_fontsize (0), m_antialias (true) - { } - - // No copying! - - ft_text_renderer (const ft_text_renderer&) = delete; - - ft_text_renderer& operator = (const ft_text_renderer&) = delete; - - ~ft_text_renderer (void) = default; - - void visit (text_element_string& e); - - void visit (text_element_list& e); - - void visit (text_element_subscript& e); + // Default font file + std::string file; - void visit (text_element_superscript& e); - - void visit (text_element_color& e); - - void visit (text_element_fontsize& e); - - void visit (text_element_fontname& e); - - void visit (text_element_fontstyle& e); - - void visit (text_element_symbol& e); - - void visit (text_element_combined& e); - - void reset (void); - - uint8NDArray get_pixels (void) const { return m_pixels; } - - Matrix get_boundingbox (void) const { return m_bbox; } - - uint8NDArray render (text_element *elt, Matrix& box, - int rotation = ROTATION_0); + if (! fonts_dir.empty ()) + { + file = fonts_dir + sys::file_ops::dir_sep_str () + "FreeSans"; - Matrix get_extent (text_element *elt, double rotation = 0.0); - Matrix get_extent (const std::string& txt, double rotation, - const caseless_str& interpreter); - - void set_anti_aliasing (bool val) { m_antialias = val; }; - - void set_font (const std::string& name, const std::string& weight, - const std::string& angle, double size); - - octave_map get_system_fonts (void); - - void set_color (const Matrix& c); - - void set_mode (int m); - - void text_to_pixels (const std::string& txt, - uint8NDArray& pxls, Matrix& bbox, - int halign, int valign, double rotation, - const caseless_str& interpreter, - bool handle_rotation); + if (weight == "bold") + file += "Bold"; - private: - - // Class to hold information about fonts and a strong - // reference to the font objects loaded by FreeType. - - class ft_font : public text_renderer::font - { - public: - - ft_font (void) - : text_renderer::font (), m_face (nullptr) { } + if (angle == "italic" || angle == "oblique") + file += "Oblique"; - ft_font (const std::string& nm, const std::string& wt, - const std::string& ang, double sz, FT_Face f = nullptr) - : text_renderer::font (nm, wt, ang, sz), m_face (f) - { } - - ft_font (const ft_font& ft); - - ~ft_font (void) - { - if (m_face) - FT_Done_Face (m_face); + file += ".otf"; } - ft_font& operator = (const ft_font& ft); - - bool is_valid (void) const { return get_face (); } - - FT_Face get_face (void) const; - - private: - - mutable FT_Face m_face; - }; +#if defined (HAVE_FONTCONFIG) + if ((search_code_point != 0 || name != "*") && m_fontconfig_initialized) + { + int fc_weight, fc_angle; - void push_new_line (void); - - void update_line_bbox (void); - - void compute_bbox (void); + if (weight == "bold") + fc_weight = FC_WEIGHT_BOLD; + else + fc_weight = FC_WEIGHT_NORMAL; - int compute_line_xoffset (const Matrix& lb) const; + if (angle == "italic") + fc_angle = FC_SLANT_ITALIC; + else if (angle == "oblique") + fc_angle = FC_SLANT_OBLIQUE; + else + fc_angle = FC_SLANT_ROMAN; - FT_UInt process_character (FT_ULong code, FT_UInt previous, - std::string& sub_font); - - public: + FcPattern *pat = FcPatternCreate (); - void text_to_strlist (const std::string& txt, - std::list& lst, Matrix& bbox, - int halign, int valign, double rotation, - const caseless_str& interp); + FcPatternAddString (pat, FC_FAMILY, + (reinterpret_cast + (name.c_str ()))); - private: - - // The current font used by the renderer. - ft_font m_font; + FcPatternAddInteger (pat, FC_WEIGHT, fc_weight); + FcPatternAddInteger (pat, FC_SLANT, fc_angle); + FcPatternAddDouble (pat, FC_PIXEL_SIZE, size); - // Used to stored the bounding box corresponding to the rendered text. - // The bounding box has the form [x, y, w, h] where x and y represent the - // coordinates of the bottom left corner relative to the anchor point of - // the text (== start of text on the baseline). Due to font descent or - // multiple lines, the value y is usually negative. - Matrix m_bbox; + if (search_code_point > 0) + { + FcCharSet *minimal_charset = FcCharSetCreate (); + FcCharSetAddChar (minimal_charset, + static_cast (search_code_point)); + FcPatternAddCharSet (pat, FC_CHARSET, minimal_charset); + } - // Used to stored the rendered text. It's a 3D matrix with size MxNx4 - // where M and N are the width and height of the bounding box. - uint8NDArray m_pixels; + if (FcConfigSubstitute (nullptr, pat, FcMatchPattern)) + { + FcResult res; + FcPattern *match; - // Used to store the bounding box of each line. This is used to layout - // multiline text properly. - std::list m_line_bbox; + FcDefaultSubstitute (pat); - // The current horizontal alignment. This is used to align multi-line text. - int m_halign; + match = FcFontMatch (nullptr, pat, &res); - // The X offset for the next glyph. - int m_xoffset; - - // The Y offset of the baseline for the current line. - int m_line_yoffset; - - // The Y offset of the baseline for the next glyph. The offset is relative - // to line_yoffset. The total Y offset is computed with: - // line_yoffset + yoffset. - int m_yoffset; + // FIXME: originally, this test also required that + // res != FcResultNoMatch. Is that really needed? + if (match) + { + unsigned char *tmp; - // The current mode of the rendering process (box computing or rendering). - int m_mode; - - // The base color of the rendered text. - uint8NDArray m_color; + FcPatternGetString (match, FC_FILE, 0, &tmp); + file = reinterpret_cast (tmp); + } + else + ::warning ("could not match any font: %s-%s-%s-%g, using default font", + name.c_str (), weight.c_str (), angle.c_str (), + size); - // A list of parsed strings to be used for printing. - bool m_do_strlist; - std::list m_strlist; + if (match) + FcPatternDestroy (match); + } - // The X offset of the baseline for the current line. - int m_line_xoffset; + FcPatternDestroy (pat); + } +#endif - // Min and max y coordinates of all glyphs in a line. - FT_Pos m_ymin; - FT_Pos m_ymax; - - // Difference between the advance and the actual extent of the latest glyph - FT_Pos m_deltax; - - // Used for computing the distance between lines. - double m_max_fontsize; - - // Anti-aliasing. - bool m_antialias; + if (file.empty ()) + ::warning ("unable to find default font files"); + else + { + std::string ascii_file = sys::get_ASCII_filename (file); - }; + if (FT_New_Face (m_library, ascii_file.c_str (), 0, &retval)) + ::warning ("ft_manager: unable to load font: %s", file.c_str ()); +#if defined (HAVE_FT_REFERENCE_FACE) + else + { + // Install a finalizer to notify ft_manager that the font is + // being destroyed. The class ft_manager only keeps weak + // references to font objects. - void - ft_text_renderer::set_font (const std::string& name, - const std::string& weight, - const std::string& angle, double size) - { - // FIXME: take "fontunits" into account - m_font = ft_font (name, weight, angle, size, nullptr); - } + retval->generic.data = new ft_key (key); + retval->generic.finalizer = ft_face_destroyed; - octave_map - ft_text_renderer::get_system_fonts (void) - { - return ft_manager::get_system_fonts (); + // Insert loaded font into the cache. + if (FT_Reference_Face (retval) == 0) + m_cache[key] = retval; + } +#endif + } + + return retval; } - void - ft_text_renderer::push_new_line (void) + void do_font_destroyed (FT_Face face) { - switch (m_mode) - { - case MODE_BBOX: - { - // Create a new bbox entry based on the current font. - - FT_Face face = m_font.get_face (); - - if (face) - { - Matrix bb (1, 5, 0.0); - - m_line_bbox.push_back (bb); - - m_xoffset = m_yoffset = 0; - m_ymin = m_ymax = m_deltax = 0; - } - } - break; - - case MODE_RENDER: - { - // Move to the next line bbox, adjust xoffset based on alignment - // and yoffset based on the old and new line bbox. - - Matrix old_bbox = m_line_bbox.front (); - m_line_bbox.pop_front (); - Matrix new_bbox = m_line_bbox.front (); - - m_xoffset = m_line_xoffset = compute_line_xoffset (new_bbox); - m_line_yoffset -= (-old_bbox(1) + math::round (0.4 * m_max_fontsize) - + (new_bbox(3) + new_bbox(1))); - m_yoffset = 0; - m_ymin = m_ymax = m_deltax = 0; - } - break; - } - } - - int - ft_text_renderer::compute_line_xoffset (const Matrix& lb) const - { - if (! m_bbox.isempty ()) + if (face->generic.data) { - switch (m_halign) - { - case 0: - return 0; - case 1: - return (m_bbox(2) - lb(2)) / 2; - case 2: - return (m_bbox(2) - lb(2)); - } - } - - return 0; - } - - void - ft_text_renderer::compute_bbox (void) - { - // Stack the various line bbox together and compute the final - // bounding box for the entire text string. - - m_bbox = Matrix (); - - switch (m_line_bbox.size ()) - { - case 0: - break; - - case 1: - m_bbox = m_line_bbox.front ().extract (0, 0, 0, 3); - break; + ft_key *pkey = reinterpret_cast (face->generic.data); - default: - for (const auto& lbox : m_line_bbox) - { - if (m_bbox.isempty ()) - m_bbox = lbox.extract (0, 0, 0, 3); - else - { - double delta = math::round (0.4 * m_max_fontsize) + lbox(3); - m_bbox(1) -= delta; - m_bbox(3) += delta; - m_bbox(2) = math::max (m_bbox(2), lbox(2)); - } - } - break; - } - } - - void - ft_text_renderer::update_line_bbox (void) - { - // Called after a font change, when in MODE_BBOX mode, to update the - // current line bbox with the new font metrics. This also includes the - // current yoffset, that is the offset of the current glyph's baseline - // the line's baseline. - - if (m_mode == MODE_BBOX) - { - Matrix& bb = m_line_bbox.back (); - bb(1) = m_ymin; - // Add one pixel to the bbox height to avoid occasional text clipping. - // See bug #55328. - bb(3) = (m_ymax + 1) - m_ymin; - if (m_deltax > 0) - bb(2) += m_deltax; + m_cache.erase (*pkey); + delete pkey; + face->generic.data = nullptr; + FT_Done_Face (face); } } - void - ft_text_renderer::set_mode (int m) + //-------- + + static ft_manager *m_instance; + + // Cache the fonts loaded by FreeType. This cache only contains + // weak references to the fonts, strong references are only present + // in class text_renderer. + ft_cache m_cache; + + FT_Library m_library; + bool m_freetype_initialized; + bool m_fontconfig_initialized; +}; + +ft_manager *ft_manager::m_instance = nullptr; + +static void +ft_face_destroyed (void *object) +{ + ft_manager::font_destroyed (reinterpret_cast (object)); +} + +class +OCTINTERP_API +ft_text_renderer : public base_text_renderer +{ +public: + + enum + { + MODE_BBOX = 0, + MODE_RENDER = 1 + }; + +public: + + ft_text_renderer (void) + : base_text_renderer (), m_font (), m_bbox (1, 4, 0.0), m_halign (0), + m_xoffset (0), m_line_yoffset (0), m_yoffset (0), m_mode (MODE_BBOX), + m_color (dim_vector (1, 3), 0), m_do_strlist (false), m_strlist (), + m_line_xoffset (0), m_ymin (0), m_ymax (0), m_deltax (0), + m_max_fontsize (0), m_antialias (true) + { } + + // No copying! + + ft_text_renderer (const ft_text_renderer&) = delete; + + ft_text_renderer& operator = (const ft_text_renderer&) = delete; + + ~ft_text_renderer (void) = default; + + void visit (text_element_string& e); + + void visit (text_element_list& e); + + void visit (text_element_subscript& e); + + void visit (text_element_superscript& e); + + void visit (text_element_color& e); + + void visit (text_element_fontsize& e); + + void visit (text_element_fontname& e); + + void visit (text_element_fontstyle& e); + + void visit (text_element_symbol& e); + + void visit (text_element_combined& e); + + void reset (void); + + uint8NDArray get_pixels (void) const { return m_pixels; } + + Matrix get_boundingbox (void) const { return m_bbox; } + + uint8NDArray render (text_element *elt, Matrix& box, + int rotation = ROTATION_0); + + Matrix get_extent (text_element *elt, double rotation = 0.0); + Matrix get_extent (const std::string& txt, double rotation, + const caseless_str& interpreter); + + void set_anti_aliasing (bool val) { m_antialias = val; }; + + void set_font (const std::string& name, const std::string& weight, + const std::string& angle, double size); + + octave_map get_system_fonts (void); + + void set_color (const Matrix& c); + + void set_mode (int m); + + void text_to_pixels (const std::string& txt, + uint8NDArray& pxls, Matrix& bbox, + int halign, int valign, double rotation, + const caseless_str& interpreter, + bool handle_rotation); + +private: + + // Class to hold information about fonts and a strong + // reference to the font objects loaded by FreeType. + + class ft_font : public text_renderer::font { - m_mode = m; + public: + + ft_font (void) + : text_renderer::font (), m_face (nullptr) { } + + ft_font (const std::string& nm, const std::string& wt, + const std::string& ang, double sz, FT_Face f = nullptr) + : text_renderer::font (nm, wt, ang, sz), m_face (f) + { } + + ft_font (const ft_font& ft); + + ~ft_font (void) + { + if (m_face) + FT_Done_Face (m_face); + } + + ft_font& operator = (const ft_font& ft); + + bool is_valid (void) const { return get_face (); } + + FT_Face get_face (void) const; + + private: + + mutable FT_Face m_face; + }; + + void push_new_line (void); + + void update_line_bbox (void); + + void compute_bbox (void); + + int compute_line_xoffset (const Matrix& lb) const; + + FT_UInt process_character (FT_ULong code, FT_UInt previous, + std::string& sub_font); + +public: + + void text_to_strlist (const std::string& txt, + std::list& lst, Matrix& bbox, + int halign, int valign, double rotation, + const caseless_str& interp); + +private: + + // The current font used by the renderer. + ft_font m_font; + + // Used to stored the bounding box corresponding to the rendered text. + // The bounding box has the form [x, y, w, h] where x and y represent the + // coordinates of the bottom left corner relative to the anchor point of + // the text (== start of text on the baseline). Due to font descent or + // multiple lines, the value y is usually negative. + Matrix m_bbox; + + // Used to stored the rendered text. It's a 3D matrix with size MxNx4 + // where M and N are the width and height of the bounding box. + uint8NDArray m_pixels; - switch (m_mode) + // Used to store the bounding box of each line. This is used to layout + // multiline text properly. + std::list m_line_bbox; + + // The current horizontal alignment. This is used to align multi-line text. + int m_halign; + + // The X offset for the next glyph. + int m_xoffset; + + // The Y offset of the baseline for the current line. + int m_line_yoffset; + + // The Y offset of the baseline for the next glyph. The offset is relative + // to line_yoffset. The total Y offset is computed with: + // line_yoffset + yoffset. + int m_yoffset; + + // The current mode of the rendering process (box computing or rendering). + int m_mode; + + // The base color of the rendered text. + uint8NDArray m_color; + + // A list of parsed strings to be used for printing. + bool m_do_strlist; + std::list m_strlist; + + // The X offset of the baseline for the current line. + int m_line_xoffset; + + // Min and max y coordinates of all glyphs in a line. + FT_Pos m_ymin; + FT_Pos m_ymax; + + // Difference between the advance and the actual extent of the latest glyph + FT_Pos m_deltax; + + // Used for computing the distance between lines. + double m_max_fontsize; + + // Anti-aliasing. + bool m_antialias; + +}; + +void +ft_text_renderer::set_font (const std::string& name, + const std::string& weight, + const std::string& angle, double size) +{ + // FIXME: take "fontunits" into account + m_font = ft_font (name, weight, angle, size, nullptr); +} + +octave_map +ft_text_renderer::get_system_fonts (void) +{ + return ft_manager::get_system_fonts (); +} + +void +ft_text_renderer::push_new_line (void) +{ + switch (m_mode) + { + case MODE_BBOX: { - case MODE_BBOX: - m_xoffset = m_line_yoffset = m_yoffset = 0; - m_max_fontsize = 0.0; - m_bbox = Matrix (1, 4, 0.0); - m_line_bbox.clear (); - push_new_line (); - break; + // Create a new bbox entry based on the current font. + + FT_Face face = m_font.get_face (); - case MODE_RENDER: - if (m_bbox.numel () != 4) + if (face) { - ::error ("ft_text_renderer: invalid bounding box, cannot render"); + Matrix bb (1, 5, 0.0); - m_xoffset = m_line_yoffset = m_yoffset = 0; - m_pixels = uint8NDArray (); + m_line_bbox.push_back (bb); + + m_xoffset = m_yoffset = 0; + m_ymin = m_ymax = m_deltax = 0; } - else - { - dim_vector d (4, octave_idx_type (m_bbox(2)), - octave_idx_type (m_bbox(3))); - m_pixels = uint8NDArray (d, static_cast (0)); - m_xoffset = compute_line_xoffset (m_line_bbox.front ()); - m_line_yoffset = -m_bbox(1); - m_yoffset = 0; - } - break; + } + break; + + case MODE_RENDER: + { + // Move to the next line bbox, adjust xoffset based on alignment + // and yoffset based on the old and new line bbox. - default: - error ("ft_text_renderer: invalid mode '%d'", m_mode); - break; - } - } + Matrix old_bbox = m_line_bbox.front (); + m_line_bbox.pop_front (); + Matrix new_bbox = m_line_bbox.front (); - bool is_opaque (const FT_GlyphSlot& glyph, const int x, const int y) - { - // Borrowed from https://stackoverflow.com/questions/14800827/ - // indexing-pixels-in-a-monochrome-freetype-glyph-buffer - int pitch = std::abs (glyph->bitmap.pitch); - unsigned char *row = &glyph->bitmap.buffer[pitch * y]; - char cvalue = row[x >> 3]; + m_xoffset = m_line_xoffset = compute_line_xoffset (new_bbox); + m_line_yoffset -= (-old_bbox(1) + math::round (0.4 * m_max_fontsize) + + (new_bbox(3) + new_bbox(1))); + m_yoffset = 0; + m_ymin = m_ymax = m_deltax = 0; + } + break; + } +} - return ((cvalue & (128 >> (x & 7))) != 0); - } +int +ft_text_renderer::compute_line_xoffset (const Matrix& lb) const +{ + if (! m_bbox.isempty ()) + { + switch (m_halign) + { + case 0: + return 0; + case 1: + return (m_bbox(2) - lb(2)) / 2; + case 2: + return (m_bbox(2) - lb(2)); + } + } + + return 0; +} + +void +ft_text_renderer::compute_bbox (void) +{ + // Stack the various line bbox together and compute the final + // bounding box for the entire text string. + + m_bbox = Matrix (); - FT_UInt - ft_text_renderer::process_character (FT_ULong code, FT_UInt previous, - std::string& sub_name) - { - FT_Face face = m_font.get_face (); + switch (m_line_bbox.size ()) + { + case 0: + break; + + case 1: + m_bbox = m_line_bbox.front ().extract (0, 0, 0, 3); + break; - sub_name = face->family_name; + default: + for (const auto& lbox : m_line_bbox) + { + if (m_bbox.isempty ()) + m_bbox = lbox.extract (0, 0, 0, 3); + else + { + double delta = math::round (0.4 * m_max_fontsize) + lbox(3); + m_bbox(1) -= delta; + m_bbox(3) += delta; + m_bbox(2) = math::max (m_bbox(2), lbox(2)); + } + } + break; + } +} + +void +ft_text_renderer::update_line_bbox (void) +{ + // Called after a font change, when in MODE_BBOX mode, to update the + // current line bbox with the new font metrics. This also includes the + // current yoffset, that is the offset of the current glyph's baseline + // the line's baseline. - FT_UInt glyph_index = 0; + if (m_mode == MODE_BBOX) + { + Matrix& bb = m_line_bbox.back (); + bb(1) = m_ymin; + // Add one pixel to the bbox height to avoid occasional text clipping. + // See bug #55328. + bb(3) = (m_ymax + 1) - m_ymin; + if (m_deltax > 0) + bb(2) += m_deltax; + } +} + +void +ft_text_renderer::set_mode (int m) +{ + m_mode = m; + + switch (m_mode) + { + case MODE_BBOX: + m_xoffset = m_line_yoffset = m_yoffset = 0; + m_max_fontsize = 0.0; + m_bbox = Matrix (1, 4, 0.0); + m_line_bbox.clear (); + push_new_line (); + break; + + case MODE_RENDER: + if (m_bbox.numel () != 4) + { + ::error ("ft_text_renderer: invalid bounding box, cannot render"); - if (face) - { - glyph_index = FT_Get_Char_Index (face, code); + m_xoffset = m_line_yoffset = m_yoffset = 0; + m_pixels = uint8NDArray (); + } + else + { + dim_vector d (4, octave_idx_type (m_bbox(2)), + octave_idx_type (m_bbox(3))); + m_pixels = uint8NDArray (d, static_cast (0)); + m_xoffset = compute_line_xoffset (m_line_bbox.front ()); + m_line_yoffset = -m_bbox(1); + m_yoffset = 0; + } + break; + + default: + error ("ft_text_renderer: invalid mode '%d'", m_mode); + break; + } +} - if (code != '\n' && code != '\t' - && (! glyph_index - || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))) - { +bool is_opaque (const FT_GlyphSlot& glyph, const int x, const int y) +{ + // Borrowed from https://stackoverflow.com/questions/14800827/ + // indexing-pixels-in-a-monochrome-freetype-glyph-buffer + int pitch = std::abs (glyph->bitmap.pitch); + unsigned char *row = &glyph->bitmap.buffer[pitch * y]; + char cvalue = row[x >> 3]; + + return ((cvalue & (128 >> (x & 7))) != 0); +} + +FT_UInt +ft_text_renderer::process_character (FT_ULong code, FT_UInt previous, + std::string& sub_name) +{ + FT_Face face = m_font.get_face (); + + sub_name = face->family_name; + + FT_UInt glyph_index = 0; + + if (face) + { + glyph_index = FT_Get_Char_Index (face, code); + + if (code != '\n' && code != '\t' + && (! glyph_index + || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT))) + { #if defined (HAVE_FONTCONFIG) - // Try to substitue font - FT_Face sub_face = ft_manager::get_font (m_font.get_name (), - m_font.get_weight (), - m_font.get_angle (), - m_font.get_size (), - code); + // Try to substitue font + FT_Face sub_face = ft_manager::get_font (m_font.get_name (), + m_font.get_weight (), + m_font.get_angle (), + m_font.get_size (), + code); + + if (sub_face) + { + FT_Set_Char_Size (sub_face, 0, m_font.get_size ()*64, 0, 0); + + glyph_index = FT_Get_Char_Index (sub_face, code); - if (sub_face) - { - FT_Set_Char_Size (sub_face, 0, m_font.get_size ()*64, 0, 0); + if (glyph_index + && (FT_Load_Glyph (sub_face, glyph_index, FT_LOAD_DEFAULT) + == 0)) + { + static std::string prev_sub_name; - glyph_index = FT_Get_Char_Index (sub_face, code); + if (prev_sub_name.empty () + || prev_sub_name != std::string (sub_face->family_name)) + { + prev_sub_name = sub_face->family_name; + warning_with_id ("Octave:substituted-glyph", + "text_renderer: substituting font to '%s' for some characters", + sub_face->family_name); + } + + ft_font saved_font = m_font; + + m_font = ft_font (m_font.get_name (), m_font.get_weight (), + m_font.get_angle (), m_font.get_size (), + sub_face); + + process_character (code, previous, sub_name); - if (glyph_index - && (FT_Load_Glyph (sub_face, glyph_index, FT_LOAD_DEFAULT) - == 0)) - { - static std::string prev_sub_name; + m_font = saved_font; + } + else + { + glyph_index = 0; + warn_missing_glyph (code); + } + } + else + { + glyph_index = 0; + warn_missing_glyph (code); + } +#else + glyph_index = 0; + warn_missing_glyph (code); +#endif + } + else if ((code == '\n') || (code == '\t')) + { + glyph_index = FT_Get_Char_Index (face, ' '); + if (! glyph_index + || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)) + { + glyph_index = 0; + warn_missing_glyph (' '); + } + else if (code == '\n') + push_new_line (); + else + { + // Advance to next multiple of 4 times the width of the "space" + // character. + int x_tab = 4 * (face->glyph->advance.x >> 6); + m_xoffset = (1 + std::floor (1. * m_xoffset / x_tab)) * x_tab; + } + } + else + { + switch (m_mode) + { + case MODE_RENDER: + if (FT_Render_Glyph (face->glyph, (m_antialias + ? FT_RENDER_MODE_NORMAL + : FT_RENDER_MODE_MONO))) + { + glyph_index = 0; + warn_glyph_render (code); + } + else + { + FT_Bitmap& bitmap = face->glyph->bitmap; + int x0, y0; - if (prev_sub_name.empty () - || prev_sub_name != std::string (sub_face->family_name)) + if (previous) + { + FT_Vector delta; + + FT_Get_Kerning (face, previous, glyph_index, + FT_KERNING_DEFAULT, &delta); + + m_xoffset += (delta.x >> 6); + } + + x0 = m_xoffset + face->glyph->bitmap_left; + y0 = m_line_yoffset + m_yoffset + + (face->glyph->bitmap_top - 1); + + // 'w' seems to have a negative -1 + // face->glyph->bitmap_left, this is so we don't index out + // of bound, and assumes we've allocated the right amount of + // horizontal space in the bbox. + if (x0 < 0) + x0 = 0; + + for (int r = 0; static_cast (r) < bitmap.rows; r++) + for (int c = 0; static_cast (c) < bitmap.width; c++) { - prev_sub_name = sub_face->family_name; - warning_with_id ("Octave:substituted-glyph", - "text_renderer: substituting font to '%s' for some characters", - sub_face->family_name); + unsigned char pix + = (m_antialias + ? bitmap.buffer[r*bitmap.width+c] + : (is_opaque (face->glyph, c, r) ? 255 : 0)); + + if (x0+c < 0 || x0+c >= m_pixels.dim2 () + || y0-r < 0 || y0-r >= m_pixels.dim3 ()) + { + // ::warning ("ft_text_renderer: x %d, y %d", + // x0+c, y0-r); + } + else if (m_pixels(3, x0+c, y0-r).value () == 0) + { + m_pixels(0, x0+c, y0-r) = m_color(0); + m_pixels(1, x0+c, y0-r) = m_color(1); + m_pixels(2, x0+c, y0-r) = m_color(2); + m_pixels(3, x0+c, y0-r) = pix; + } } - ft_font saved_font = m_font; + m_xoffset += (face->glyph->advance.x >> 6); + } + break; - m_font = ft_font (m_font.get_name (), m_font.get_weight (), - m_font.get_angle (), m_font.get_size (), - sub_face); - - process_character (code, previous, sub_name); + case MODE_BBOX: + Matrix& bb = m_line_bbox.back (); - m_font = saved_font; - } - else - { - glyph_index = 0; - warn_missing_glyph (code); - } - } - else - { - glyph_index = 0; - warn_missing_glyph (code); - } -#else - glyph_index = 0; - warn_missing_glyph (code); -#endif - } - else if ((code == '\n') || (code == '\t')) - { - glyph_index = FT_Get_Char_Index (face, ' '); - if (! glyph_index - || FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT)) - { - glyph_index = 0; - warn_missing_glyph (' '); - } - else if (code == '\n') - push_new_line (); - else - { - // Advance to next multiple of 4 times the width of the "space" - // character. - int x_tab = 4 * (face->glyph->advance.x >> 6); - m_xoffset = (1 + std::floor (1. * m_xoffset / x_tab)) * x_tab; - } - } - else - { - switch (m_mode) - { - case MODE_RENDER: - if (FT_Render_Glyph (face->glyph, (m_antialias - ? FT_RENDER_MODE_NORMAL - : FT_RENDER_MODE_MONO))) - { - glyph_index = 0; - warn_glyph_render (code); - } - else - { - FT_Bitmap& bitmap = face->glyph->bitmap; - int x0, y0; + // If we have a previous glyph, use kerning information. This + // usually means moving a bit backward before adding the next + // glyph. That is, "delta.x" is usually < 0. + if (previous) + { + FT_Vector delta; - if (previous) - { - FT_Vector delta; + FT_Get_Kerning (face, previous, glyph_index, + FT_KERNING_DEFAULT, &delta); - FT_Get_Kerning (face, previous, glyph_index, - FT_KERNING_DEFAULT, &delta); - - m_xoffset += (delta.x >> 6); - } + m_xoffset += (delta.x >> 6); + } - x0 = m_xoffset + face->glyph->bitmap_left; - y0 = m_line_yoffset + m_yoffset - + (face->glyph->bitmap_top - 1); + // Extend current X offset box by the width of the current + // glyph. Then extend the line bounding box if necessary. - // 'w' seems to have a negative -1 - // face->glyph->bitmap_left, this is so we don't index out - // of bound, and assumes we've allocated the right amount of - // horizontal space in the bbox. - if (x0 < 0) - x0 = 0; + m_xoffset += (face->glyph->advance.x >> 6); + bb(2) = math::max (bb(2), m_xoffset); - for (int r = 0; static_cast (r) < bitmap.rows; r++) - for (int c = 0; static_cast (c) < bitmap.width; c++) - { - unsigned char pix - = (m_antialias - ? bitmap.buffer[r*bitmap.width+c] - : (is_opaque (face->glyph, c, r) ? 255 : 0)); - - if (x0+c < 0 || x0+c >= m_pixels.dim2 () - || y0-r < 0 || y0-r >= m_pixels.dim3 ()) - { - // ::warning ("ft_text_renderer: x %d, y %d", - // x0+c, y0-r); - } - else if (m_pixels(3, x0+c, y0-r).value () == 0) - { - m_pixels(0, x0+c, y0-r) = m_color(0); - m_pixels(1, x0+c, y0-r) = m_color(1); - m_pixels(2, x0+c, y0-r) = m_color(2); - m_pixels(3, x0+c, y0-r) = pix; - } - } - - m_xoffset += (face->glyph->advance.x >> 6); - } - break; - - case MODE_BBOX: - Matrix& bb = m_line_bbox.back (); - - // If we have a previous glyph, use kerning information. This - // usually means moving a bit backward before adding the next - // glyph. That is, "delta.x" is usually < 0. - if (previous) - { - FT_Vector delta; - - FT_Get_Kerning (face, previous, glyph_index, - FT_KERNING_DEFAULT, &delta); - - m_xoffset += (delta.x >> 6); - } + // Store the actual bbox vertical coordinates of this character + FT_Glyph glyph; + if (FT_Get_Glyph (face->glyph, &glyph)) + warn_glyph_render (code); + else + { + FT_BBox glyph_bbox; + FT_Glyph_Get_CBox (glyph, FT_GLYPH_BBOX_UNSCALED, + &glyph_bbox); + m_deltax = (glyph_bbox.xMax - face->glyph->advance.x) >> 6; + m_ymin = math::min ((glyph_bbox.yMin >> 6) + m_yoffset, + m_ymin); + m_ymax = math::max ((glyph_bbox.yMax >> 6) + m_yoffset, + m_ymax); + FT_Done_Glyph (glyph); + update_line_bbox (); + } + break; + } + } + } - // Extend current X offset box by the width of the current - // glyph. Then extend the line bounding box if necessary. - - m_xoffset += (face->glyph->advance.x >> 6); - bb(2) = math::max (bb(2), m_xoffset); + return glyph_index; +} - // Store the actual bbox vertical coordinates of this character - FT_Glyph glyph; - if (FT_Get_Glyph (face->glyph, &glyph)) - warn_glyph_render (code); - else - { - FT_BBox glyph_bbox; - FT_Glyph_Get_CBox (glyph, FT_GLYPH_BBOX_UNSCALED, - &glyph_bbox); - m_deltax = (glyph_bbox.xMax - face->glyph->advance.x) >> 6; - m_ymin = math::min ((glyph_bbox.yMin >> 6) + m_yoffset, - m_ymin); - m_ymax = math::max ((glyph_bbox.yMax >> 6) + m_yoffset, - m_ymax); - FT_Done_Glyph (glyph); - update_line_bbox (); - } - break; - } - } - } +void +ft_text_renderer::text_to_strlist (const std::string& txt, + std::list& lst, + Matrix& box, + int ha, int va, double rot, + const caseless_str& interp) +{ + uint8NDArray pxls; - return glyph_index; - } + // First run text_to_pixels which will also build the string list - void - ft_text_renderer::text_to_strlist (const std::string& txt, - std::list& lst, - Matrix& box, - int ha, int va, double rot, - const caseless_str& interp) - { - uint8NDArray pxls; + m_strlist = std::list (); - // First run text_to_pixels which will also build the string list - - m_strlist = std::list (); - - unwind_protect_var restore_var1 (m_do_strlist); - unwind_protect_var> + unwind_protect_var restore_var1 (m_do_strlist); + unwind_protect_var> restore_var2 (m_strlist); - m_do_strlist = true; + m_do_strlist = true; - text_to_pixels (txt, pxls, box, ha, va, rot, interp, false); + text_to_pixels (txt, pxls, box, ha, va, rot, interp, false); - lst = m_strlist; - } + lst = m_strlist; +} - void - ft_text_renderer::visit (text_element_string& e) - { - if (m_font.is_valid ()) - { - m_max_fontsize = std::max (m_max_fontsize, m_font.get_size ()); - FT_UInt glyph_index, previous = 0; +void +ft_text_renderer::visit (text_element_string& e) +{ + if (m_font.is_valid ()) + { + m_max_fontsize = std::max (m_max_fontsize, m_font.get_size ()); + FT_UInt glyph_index, previous = 0; - std::string str = e.string_value (); - const uint8_t *c = reinterpret_cast (str.c_str ()); - uint32_t u32_c; + std::string str = e.string_value (); + const uint8_t *c = reinterpret_cast (str.c_str ()); + uint32_t u32_c; - std::size_t n = str.size (); - std::size_t icurr = 0; - std::size_t ibegin = 0; + std::size_t n = str.size (); + std::size_t icurr = 0; + std::size_t ibegin = 0; - // Initialize a new string - text_renderer::string fs (str, m_font, m_xoffset, m_yoffset); + // Initialize a new string + text_renderer::string fs (str, m_font, m_xoffset, m_yoffset); - std::string fname = m_font.get_face ()->family_name; + std::string fname = m_font.get_face ()->family_name; - if (fname.find (" ") != std::string::npos) - fname = "'" + fname + "'"; + if (fname.find (" ") != std::string::npos) + fname = "'" + fname + "'"; - fs.set_family (fname); + fs.set_family (fname); - std::vector xdata; - std::string sub_name; + std::vector xdata; + std::string sub_name; - while (n > 0) - { - // Retrieve the length and the u32 representation of the current - // character - int mblen = octave_u8_strmbtouc_wrapper (&u32_c, c + icurr); - if (mblen < 1) - { - // This is not an UTF-8 character, use a replacement character - mblen = 1; - u32_c = 0xFFFD; - } + while (n > 0) + { + // Retrieve the length and the u32 representation of the current + // character + int mblen = octave_u8_strmbtouc_wrapper (&u32_c, c + icurr); + if (mblen < 1) + { + // This is not an UTF-8 character, use a replacement character + mblen = 1; + u32_c = 0xFFFD; + } - n -= mblen; + n -= mblen; - if (m_do_strlist && m_mode == MODE_RENDER) - { - if (u32_c == 10) - { - // Finish previous string in m_strlist before processing - // the newline character - fs.set_y (m_line_yoffset + m_yoffset); - fs.set_color (m_color); + if (m_do_strlist && m_mode == MODE_RENDER) + { + if (u32_c == 10) + { + // Finish previous string in m_strlist before processing + // the newline character + fs.set_y (m_line_yoffset + m_yoffset); + fs.set_color (m_color); - std::string s = str.substr (ibegin, icurr - ibegin); - if (! s.empty ()) - { - fs.set_string (s); - fs.set_y (m_line_yoffset + m_yoffset); - fs.set_xdata (xdata); - fs.set_family (fname); - m_strlist.push_back (fs); - } - } - else - xdata.push_back (m_xoffset); - } + std::string s = str.substr (ibegin, icurr - ibegin); + if (! s.empty ()) + { + fs.set_string (s); + fs.set_y (m_line_yoffset + m_yoffset); + fs.set_xdata (xdata); + fs.set_family (fname); + m_strlist.push_back (fs); + } + } + else + xdata.push_back (m_xoffset); + } - glyph_index = process_character (u32_c, previous, sub_name); + glyph_index = process_character (u32_c, previous, sub_name); - if (m_do_strlist && m_mode == MODE_RENDER && ! sub_name.empty ()) - { - // Add substitution font to the family name stack - std::string tmp_family = fs.get_family (); + if (m_do_strlist && m_mode == MODE_RENDER && ! sub_name.empty ()) + { + // Add substitution font to the family name stack + std::string tmp_family = fs.get_family (); - if (tmp_family.find (sub_name) == std::string::npos) - { - if (sub_name.find (" ") != std::string::npos) - sub_name = "'" + sub_name + "'"; + if (tmp_family.find (sub_name) == std::string::npos) + { + if (sub_name.find (" ") != std::string::npos) + sub_name = "'" + sub_name + "'"; - fs.set_family (tmp_family + ", " + sub_name); - } - } + fs.set_family (tmp_family + ", " + sub_name); + } + } - if (u32_c == 10) - { - previous = 0; + if (u32_c == 10) + { + previous = 0; - if (m_do_strlist && m_mode == MODE_RENDER) - { - // Start a new string in m_strlist - ibegin = icurr+1; - xdata.clear (); - fs = text_renderer::string (str.substr (ibegin), m_font, - m_line_xoffset, m_yoffset); - } - } - else - previous = glyph_index; + if (m_do_strlist && m_mode == MODE_RENDER) + { + // Start a new string in m_strlist + ibegin = icurr+1; + xdata.clear (); + fs = text_renderer::string (str.substr (ibegin), m_font, + m_line_xoffset, m_yoffset); + } + } + else + previous = glyph_index; - icurr += mblen; - } + icurr += mblen; + } - if (m_do_strlist && m_mode == MODE_RENDER - && ! fs.get_string ().empty ()) - { - fs.set_y (m_line_yoffset + m_yoffset); - fs.set_color (m_color); - fs.set_xdata (xdata); - m_strlist.push_back (fs); - } - } - } + if (m_do_strlist && m_mode == MODE_RENDER + && ! fs.get_string ().empty ()) + { + fs.set_y (m_line_yoffset + m_yoffset); + fs.set_color (m_color); + fs.set_xdata (xdata); + m_strlist.push_back (fs); + } + } +} - void - ft_text_renderer::visit (text_element_list& e) - { - // Save and restore (after processing the list) the current font and color. +void +ft_text_renderer::visit (text_element_list& e) +{ + // Save and restore (after processing the list) the current font and color. - ft_font saved_font (m_font); - uint8NDArray saved_color (m_color); + ft_font saved_font (m_font); + uint8NDArray saved_color (m_color); - text_processor::visit (e); + text_processor::visit (e); - m_font = saved_font; - m_color = saved_color; - } + m_font = saved_font; + m_color = saved_color; +} - void - ft_text_renderer::visit (text_element_subscript& e) - { - ft_font saved_font (m_font); - int saved_line_yoffset = m_line_yoffset; - int saved_yoffset = m_yoffset; +void +ft_text_renderer::visit (text_element_subscript& e) +{ + ft_font saved_font (m_font); + int saved_line_yoffset = m_line_yoffset; + int saved_yoffset = m_yoffset; - double sz = m_font.get_size (); + double sz = m_font.get_size (); - // Reducing font size by 70% produces decent results. - set_font (m_font.get_name (), m_font.get_weight (), m_font.get_angle (), - std::max (5.0, sz * 0.7)); + // Reducing font size by 70% produces decent results. + set_font (m_font.get_name (), m_font.get_weight (), m_font.get_angle (), + std::max (5.0, sz * 0.7)); - if (m_font.is_valid ()) - { - // Shifting the baseline by 15% of the font size gives decent results. - m_yoffset -= std::ceil (sz * 0.15); + if (m_font.is_valid ()) + { + // Shifting the baseline by 15% of the font size gives decent results. + m_yoffset -= std::ceil (sz * 0.15); - if (m_mode == MODE_BBOX) - update_line_bbox (); - } + if (m_mode == MODE_BBOX) + update_line_bbox (); + } - text_processor::visit (e); + text_processor::visit (e); - m_font = saved_font; - // If line_yoffset changed, this means we moved to a new line; hence yoffset - // cannot be restored, because the saved value is not relevant anymore. - if (m_line_yoffset == saved_line_yoffset) - m_yoffset = saved_yoffset; - } + m_font = saved_font; + // If line_yoffset changed, this means we moved to a new line; hence yoffset + // cannot be restored, because the saved value is not relevant anymore. + if (m_line_yoffset == saved_line_yoffset) + m_yoffset = saved_yoffset; +} - void - ft_text_renderer::visit (text_element_superscript& e) - { - ft_font saved_font (m_font); - int saved_line_yoffset = m_line_yoffset; - int saved_yoffset = m_yoffset; +void +ft_text_renderer::visit (text_element_superscript& e) +{ + ft_font saved_font (m_font); + int saved_line_yoffset = m_line_yoffset; + int saved_yoffset = m_yoffset; - double sz = m_font.get_size (); + double sz = m_font.get_size (); - // Reducing font size by 70% produces decent results. - set_font (m_font.get_name (), m_font.get_weight (), m_font.get_angle (), - std::max (5.0, sz * 0.7)); + // Reducing font size by 70% produces decent results. + set_font (m_font.get_name (), m_font.get_weight (), m_font.get_angle (), + std::max (5.0, sz * 0.7)); - if (saved_font.is_valid ()) - { - // Shifting the baseline by 40% of the font size gives decent results. - m_yoffset += std::ceil (sz * 0.4); + if (saved_font.is_valid ()) + { + // Shifting the baseline by 40% of the font size gives decent results. + m_yoffset += std::ceil (sz * 0.4); - if (m_mode == MODE_BBOX) - update_line_bbox (); - } + if (m_mode == MODE_BBOX) + update_line_bbox (); + } - text_processor::visit (e); + text_processor::visit (e); - m_font = saved_font; - // If line_yoffset changed, this means we moved to a new line; hence yoffset - // cannot be restored, because the saved value is not relevant anymore. - if (m_line_yoffset == saved_line_yoffset) - m_yoffset = saved_yoffset; - } + m_font = saved_font; + // If line_yoffset changed, this means we moved to a new line; hence yoffset + // cannot be restored, because the saved value is not relevant anymore. + if (m_line_yoffset == saved_line_yoffset) + m_yoffset = saved_yoffset; +} - void - ft_text_renderer::visit (text_element_color& e) - { - if (m_mode == MODE_RENDER) - set_color (e.get_color ()); - } +void +ft_text_renderer::visit (text_element_color& e) +{ + if (m_mode == MODE_RENDER) + set_color (e.get_color ()); +} - void - ft_text_renderer::visit (text_element_fontsize& e) - { - double sz = e.get_fontsize (); +void +ft_text_renderer::visit (text_element_fontsize& e) +{ + double sz = e.get_fontsize (); - // FIXME: Matlab documentation says that the font size is expressed - // in the text object FontUnit. + // FIXME: Matlab documentation says that the font size is expressed + // in the text object FontUnit. - set_font (m_font.get_name (), m_font.get_weight (), - m_font.get_angle (), sz); + set_font (m_font.get_name (), m_font.get_weight (), + m_font.get_angle (), sz); - if (m_mode == MODE_BBOX) - update_line_bbox (); - } + if (m_mode == MODE_BBOX) + update_line_bbox (); +} - void - ft_text_renderer::visit (text_element_fontname& e) - { - set_font (e.get_fontname (), m_font.get_weight (), m_font.get_angle (), - m_font.get_size ()); +void +ft_text_renderer::visit (text_element_fontname& e) +{ + set_font (e.get_fontname (), m_font.get_weight (), m_font.get_angle (), + m_font.get_size ()); - if (m_mode == MODE_BBOX) - update_line_bbox (); - } + if (m_mode == MODE_BBOX) + update_line_bbox (); +} - void - ft_text_renderer::visit (text_element_fontstyle& e) - { - switch (e.get_fontstyle ()) - { - case text_element_fontstyle::normal: - set_font (m_font.get_name (), "normal", "normal", m_font.get_size ()); - break; +void +ft_text_renderer::visit (text_element_fontstyle& e) +{ + switch (e.get_fontstyle ()) + { + case text_element_fontstyle::normal: + set_font (m_font.get_name (), "normal", "normal", m_font.get_size ()); + break; - case text_element_fontstyle::bold: - set_font (m_font.get_name (), "bold", "normal", m_font.get_size ()); - break; + case text_element_fontstyle::bold: + set_font (m_font.get_name (), "bold", "normal", m_font.get_size ()); + break; - case text_element_fontstyle::italic: - set_font (m_font.get_name (), "normal", "italic", m_font.get_size ()); - break; + case text_element_fontstyle::italic: + set_font (m_font.get_name (), "normal", "italic", m_font.get_size ()); + break; - case text_element_fontstyle::oblique: - set_font (m_font.get_name (), "normal", "oblique", m_font.get_size ()); - break; - } + case text_element_fontstyle::oblique: + set_font (m_font.get_name (), "normal", "oblique", m_font.get_size ()); + break; + } - if (m_mode == MODE_BBOX) - update_line_bbox (); - } + if (m_mode == MODE_BBOX) + update_line_bbox (); +} - void - ft_text_renderer::visit (text_element_symbol& e) - { - uint32_t code = e.get_symbol_code (); +void +ft_text_renderer::visit (text_element_symbol& e) +{ + uint32_t code = e.get_symbol_code (); - std::vector xdata (1, m_xoffset); - text_renderer::string fs ("-", m_font, m_xoffset, m_yoffset); + std::vector xdata (1, m_xoffset); + text_renderer::string fs ("-", m_font, m_xoffset, m_yoffset); - if (code != text_element_symbol::invalid_code && m_font.is_valid ()) - { - std::string sub_name; + if (code != text_element_symbol::invalid_code && m_font.is_valid ()) + { + std::string sub_name; - process_character (code, 0, sub_name); + process_character (code, 0, sub_name); - if (m_do_strlist && m_mode == MODE_RENDER) - { - if (! sub_name.empty ()) - { - // Add substitution font to the family name - std::string tmp_family = fs.get_family (); + if (m_do_strlist && m_mode == MODE_RENDER) + { + if (! sub_name.empty ()) + { + // Add substitution font to the family name + std::string tmp_family = fs.get_family (); - if (tmp_family.find (sub_name) == std::string::npos) - { - if (sub_name.find (" ") != std::string::npos) - sub_name = "'" + sub_name + "'"; + if (tmp_family.find (sub_name) == std::string::npos) + { + if (sub_name.find (" ") != std::string::npos) + sub_name = "'" + sub_name + "'"; - fs.set_family (tmp_family + ", " + sub_name); - } - } + fs.set_family (tmp_family + ", " + sub_name); + } + } - fs.set_code (code); - fs.set_xdata (xdata); - } - } - else if (m_font.is_valid ()) - ::warning ("ignoring unknown symbol: %d", e.get_symbol ()); + fs.set_code (code); + fs.set_xdata (xdata); + } + } + else if (m_font.is_valid ()) + ::warning ("ignoring unknown symbol: %d", e.get_symbol ()); - if (m_do_strlist && m_mode == MODE_RENDER && fs.get_code ()) - { - fs.set_y (m_line_yoffset + m_yoffset); - fs.set_color (m_color); - fs.set_family (m_font.get_face ()->family_name); - m_strlist.push_back (fs); - } - } + if (m_do_strlist && m_mode == MODE_RENDER && fs.get_code ()) + { + fs.set_y (m_line_yoffset + m_yoffset); + fs.set_color (m_color); + fs.set_family (m_font.get_face ()->family_name); + m_strlist.push_back (fs); + } +} - void - ft_text_renderer::visit (text_element_combined& e) - { - int saved_xoffset = m_xoffset; - int max_xoffset = m_xoffset; +void +ft_text_renderer::visit (text_element_combined& e) +{ + int saved_xoffset = m_xoffset; + int max_xoffset = m_xoffset; - for (auto *txt_elt : e) - { - m_xoffset = saved_xoffset; - txt_elt->accept (*this); - max_xoffset = math::max (m_xoffset, max_xoffset); - } + for (auto *txt_elt : e) + { + m_xoffset = saved_xoffset; + txt_elt->accept (*this); + max_xoffset = math::max (m_xoffset, max_xoffset); + } - m_xoffset = max_xoffset; - } + m_xoffset = max_xoffset; +} - void - ft_text_renderer::reset (void) - { - set_mode (MODE_BBOX); - set_color (Matrix (1, 3, 0.0)); - m_strlist = std::list (); - } +void +ft_text_renderer::reset (void) +{ + set_mode (MODE_BBOX); + set_color (Matrix (1, 3, 0.0)); + m_strlist = std::list (); +} - void - ft_text_renderer::set_color (const Matrix& c) - { - if (c.numel () == 3) - { - m_color(0) = static_cast (c(0)*255); - m_color(1) = static_cast (c(1)*255); - m_color(2) = static_cast (c(2)*255); - } - else - ::warning ("ft_text_renderer::set_color: invalid color"); - } +void +ft_text_renderer::set_color (const Matrix& c) +{ + if (c.numel () == 3) + { + m_color(0) = static_cast (c(0)*255); + m_color(1) = static_cast (c(1)*255); + m_color(2) = static_cast (c(2)*255); + } + else + ::warning ("ft_text_renderer::set_color: invalid color"); +} - uint8NDArray - ft_text_renderer::render (text_element *elt, Matrix& box, int rotation) - { - set_mode (MODE_BBOX); - elt->accept (*this); - compute_bbox (); - box = m_bbox; +uint8NDArray +ft_text_renderer::render (text_element *elt, Matrix& box, int rotation) +{ + set_mode (MODE_BBOX); + elt->accept (*this); + compute_bbox (); + box = m_bbox; - set_mode (MODE_RENDER); + set_mode (MODE_RENDER); - if (m_pixels.numel () > 0) - { - elt->accept (*this); + if (m_pixels.numel () > 0) + { + elt->accept (*this); - rotate_pixels (m_pixels, rotation); - } + rotate_pixels (m_pixels, rotation); + } - return m_pixels; - } + return m_pixels; +} - // Note: - // x-extent accurately measures width of glyphs. - // y-extent is overly large because it is measured from baseline-to-baseline. - // Calling routines, such as ylabel, may need to account for this mismatch. +// Note: +// x-extent accurately measures width of glyphs. +// y-extent is overly large because it is measured from baseline-to-baseline. +// Calling routines, such as ylabel, may need to account for this mismatch. - Matrix - ft_text_renderer::get_extent (text_element *elt, double rotation) - { - set_mode (MODE_BBOX); - elt->accept (*this); - compute_bbox (); +Matrix +ft_text_renderer::get_extent (text_element *elt, double rotation) +{ + set_mode (MODE_BBOX); + elt->accept (*this); + compute_bbox (); - Matrix extent (1, 2, 0.0); + Matrix extent (1, 2, 0.0); - switch (rotation_to_mode (rotation)) - { - case ROTATION_0: - case ROTATION_180: - extent(0) = m_bbox(2); - extent(1) = m_bbox(3); - break; + switch (rotation_to_mode (rotation)) + { + case ROTATION_0: + case ROTATION_180: + extent(0) = m_bbox(2); + extent(1) = m_bbox(3); + break; - case ROTATION_90: - case ROTATION_270: - extent(0) = m_bbox(3); - extent(1) = m_bbox(2); - } + case ROTATION_90: + case ROTATION_270: + extent(0) = m_bbox(3); + extent(1) = m_bbox(2); + } - return extent; - } + return extent; +} - Matrix - ft_text_renderer::get_extent (const std::string& txt, double rotation, - const caseless_str& interpreter) - { - text_element *elt = text_parser::parse (txt, interpreter); - Matrix extent = get_extent (elt, rotation); - delete elt; +Matrix +ft_text_renderer::get_extent (const std::string& txt, double rotation, + const caseless_str& interpreter) +{ + text_element *elt = text_parser::parse (txt, interpreter); + Matrix extent = get_extent (elt, rotation); + delete elt; - return extent; - } + return extent; +} - void - ft_text_renderer::text_to_pixels (const std::string& txt, - uint8NDArray& pxls, Matrix& box, - int _halign, int valign, double rotation, - const caseless_str& interpreter, - bool handle_rotation) - { - int rot_mode = rotation_to_mode (rotation); +void +ft_text_renderer::text_to_pixels (const std::string& txt, + uint8NDArray& pxls, Matrix& box, + int _halign, int valign, double rotation, + const caseless_str& interpreter, + bool handle_rotation) +{ + int rot_mode = rotation_to_mode (rotation); - m_halign = _halign; + m_halign = _halign; - text_element *elt = text_parser::parse (txt, interpreter); - pxls = render (elt, box, rot_mode); - delete elt; + text_element *elt = text_parser::parse (txt, interpreter); + pxls = render (elt, box, rot_mode); + delete elt; - if (pxls.isempty ()) - return; // nothing to render + if (pxls.isempty ()) + return; // nothing to render - // Move X0 and Y0 depending on alignments and eventually swap all values - // for text rotated 90° 180° or 270° - fix_bbox_anchor (box, m_halign, valign, rot_mode, handle_rotation); - } + // Move X0 and Y0 depending on alignments and eventually swap all values + // for text rotated 90° 180° or 270° + fix_bbox_anchor (box, m_halign, valign, rot_mode, handle_rotation); +} - ft_text_renderer::ft_font::ft_font (const ft_font& ft) - : text_renderer::font (ft), m_face (nullptr) - { +ft_text_renderer::ft_font::ft_font (const ft_font& ft) + : text_renderer::font (ft), m_face (nullptr) +{ #if defined (HAVE_FT_REFERENCE_FACE) - FT_Face ft_face = ft.get_face (); + FT_Face ft_face = ft.get_face (); - if (ft_face && FT_Reference_Face (ft_face) == 0) - m_face = ft_face; + if (ft_face && FT_Reference_Face (ft_face) == 0) + m_face = ft_face; #endif - } +} - ft_text_renderer::ft_font& - ft_text_renderer::ft_font::operator = (const ft_font& ft) - { - if (&ft != this) - { - text_renderer::font::operator = (ft); +ft_text_renderer::ft_font& +ft_text_renderer::ft_font::operator = (const ft_font& ft) +{ + if (&ft != this) + { + text_renderer::font::operator = (ft); - if (m_face) - { - FT_Done_Face (m_face); - m_face = nullptr; - } + if (m_face) + { + FT_Done_Face (m_face); + m_face = nullptr; + } #if defined (HAVE_FT_REFERENCE_FACE) - FT_Face ft_face = ft.get_face (); + FT_Face ft_face = ft.get_face (); - if (ft_face && FT_Reference_Face (ft_face) == 0) - m_face = ft_face; + if (ft_face && FT_Reference_Face (ft_face) == 0) + m_face = ft_face; #endif - } + } - return *this; - } + return *this; +} - FT_Face - ft_text_renderer::ft_font::get_face (void) const - { - if (! m_face && ! m_name.empty ()) - { - m_face = ft_manager::get_font (m_name, m_weight, m_angle, m_size); +FT_Face +ft_text_renderer::ft_font::get_face (void) const +{ + if (! m_face && ! m_name.empty ()) + { + m_face = ft_manager::get_font (m_name, m_weight, m_angle, m_size); - if (m_face) - { - if (FT_Set_Char_Size (m_face, 0, m_size*64, 0, 0)) - ::warning ("ft_text_renderer: unable to set font size to %g", m_size); - } - else - ::warning ("ft_text_renderer: unable to load appropriate font"); - } + if (m_face) + { + if (FT_Set_Char_Size (m_face, 0, m_size*64, 0, 0)) + ::warning ("ft_text_renderer: unable to set font size to %g", m_size); + } + else + ::warning ("ft_text_renderer: unable to load appropriate font"); + } - return m_face; - } + return m_face; +} OCTAVE_END_NAMESPACE(octave) @@ -1533,14 +1533,14 @@ OCTAVE_BEGIN_NAMESPACE(octave) - base_text_renderer * - make_ft_text_renderer (void) - { +base_text_renderer * +make_ft_text_renderer (void) +{ #if defined (HAVE_FREETYPE) - return new ft_text_renderer (); + return new ft_text_renderer (); #else - return 0; + return 0; #endif - } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ft-text-renderer.h --- a/libinterp/corefcn/ft-text-renderer.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ft-text-renderer.h Thu Dec 01 20:05:44 2022 -0800 @@ -30,9 +30,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class base_text_renderer; +class base_text_renderer; - extern base_text_renderer * make_ft_text_renderer (void); +extern base_text_renderer * make_ft_text_renderer (void); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gcd.cc --- a/libinterp/corefcn/gcd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gcd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -264,7 +264,7 @@ { octave_value retval; builtin_type_t btyp = btyp_mixed_numeric (a.builtin_type (), - b.builtin_type ()); + b.builtin_type ()); switch (btyp) { case btyp_double: @@ -284,14 +284,14 @@ retval = do_simple_gcd (a, b); \ break - MAKE_INT_BRANCH (int8); - MAKE_INT_BRANCH (int16); - MAKE_INT_BRANCH (int32); - MAKE_INT_BRANCH (int64); - MAKE_INT_BRANCH (uint8); - MAKE_INT_BRANCH (uint16); - MAKE_INT_BRANCH (uint32); - MAKE_INT_BRANCH (uint64); + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); #undef MAKE_INT_BRANCH @@ -383,7 +383,7 @@ octave_value retval; builtin_type_t btyp = btyp_mixed_numeric (a.builtin_type (), - b.builtin_type ()); + b.builtin_type ()); switch (btyp) { case btyp_double: @@ -396,14 +396,14 @@ retval = do_extended_gcd (a, b, x, y); \ break - MAKE_INT_BRANCH (int8); - MAKE_INT_BRANCH (int16); - MAKE_INT_BRANCH (int32); - MAKE_INT_BRANCH (int64); - MAKE_INT_BRANCH (uint8); - MAKE_INT_BRANCH (uint16); - MAKE_INT_BRANCH (uint32); - MAKE_INT_BRANCH (uint64); + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); #undef MAKE_INT_BRANCH diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gl-render.cc --- a/libinterp/corefcn/gl-render.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gl-render.cc Thu Dec 01 20:05:44 2022 -0800 @@ -49,4941 +49,4942 @@ #if defined (HAVE_OPENGL) - static int - next_power_of_2 (int n) - { - int m = 1; - - while (m < n && m < std::numeric_limits::max ()) - m <<= 1; - - return m; - } +static int +next_power_of_2 (int n) +{ + int m = 1; + + while (m < n && m < std::numeric_limits::max ()) + m <<= 1; + + return m; +} #define LIGHT_MODE GL_FRONT_AND_BACK - // Use symbolic names for axes - enum - { - X_AXIS, - Y_AXIS, - Z_AXIS - }; - - // Use symbolic names for color mode - enum - { - UNIFORM, - FLAT, - INTERP, - TEXTURE - }; - - // Use symbolic names for lighting - enum - { - NONE, - //FLAT, // Already declared in anonymous enum for color mode - GOURAUD = 2 - }; - - // Win32 API requires the CALLBACK attributes for - // GLU callback functions. Define it to empty on - // other platforms. +// Use symbolic names for axes +enum +{ + X_AXIS, + Y_AXIS, + Z_AXIS +}; + +// Use symbolic names for color mode +enum +{ + UNIFORM, + FLAT, + INTERP, + TEXTURE +}; + +// Use symbolic names for lighting +enum +{ + NONE, + //FLAT, // Already declared in anonymous enum for color mode + GOURAUD = 2 +}; + +// Win32 API requires the CALLBACK attributes for +// GLU callback functions. Define it to empty on +// other platforms. #if ! defined (CALLBACK) # define CALLBACK #endif - class opengl_texture - { - private: - - class texture_rep - { - public: - - texture_rep (opengl_functions& glfcns) - : m_glfcns (glfcns), m_id (), m_w (), m_h (), m_tw (), m_th (), - m_tx (), m_ty (), m_valid (false) - { } - - texture_rep (opengl_functions& glfcns, GLuint id, int w, int h, - int tw, int th) - : m_glfcns (glfcns), m_id (id), m_w (w), m_h (h), m_tw (tw), m_th (th), - m_tx (double(m_w)/m_tw), m_ty (double(m_h)/m_th), m_valid (true) - { } - - ~texture_rep (void) - { - if (m_valid) - m_glfcns.glDeleteTextures (1, &m_id); - } - - void bind (int mode) const - { - if (m_valid) - m_glfcns.glBindTexture (mode, m_id); - } - - void tex_coord (double q, double r) const - { - if (m_valid) - m_glfcns.glTexCoord2d (q*m_tx, r*m_ty); - } - - opengl_functions& m_glfcns; - GLuint m_id; - int m_w, m_h; - int m_tw, m_th; - double m_tx, m_ty; - bool m_valid; - }; - - public: - - opengl_texture (opengl_functions& glfcns) - : m_rep (new texture_rep (glfcns)) - { } - - opengl_texture (opengl_functions& glfcns, GLuint id, int w, int h, - int tw, int th) - : m_rep (new texture_rep (glfcns, id, w, h, tw, th)) - { } - - opengl_texture (const opengl_texture&) = default; - - ~opengl_texture (void) = default; - - opengl_texture& operator = (const opengl_texture&) = default; - - static opengl_texture create (opengl_functions& glfcns, - const octave_value& data); - - void bind (int mode = GL_TEXTURE_2D) const { m_rep->bind (mode); } - - void tex_coord (double q, double r) const { m_rep->tex_coord (q, r); } - - bool is_valid (void) const { return m_rep->m_valid; } - - private: - - opengl_texture (const std::shared_ptr& new_rep) - : m_rep (new_rep) - { } - - std::shared_ptr m_rep; - }; - - opengl_texture - opengl_texture::create (opengl_functions& glfcns, const octave_value& data) - { - opengl_texture retval (glfcns); - - dim_vector dv (data.dims ()); - - // Expect RGB data - if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4)) - { - // FIXME: dim_vectors hold octave_idx_type values. - // Should we check for dimensions larger than intmax? - int h, w, tw, th; - h = dv(0), w = dv(1); - - // Return early if the image data are larger than the texture - // can hold - int max_size; - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size); - static bool warned = false; - if (h > max_size || w > max_size) - { - if (! warned) - { - warning ("opengl_texture::create: the opengl library in use " - "doesn't support images with either dimension larger " - "than %d. Not rendering.", max_size); - warned = true; - } - - return opengl_texture (glfcns); - } - - GLuint id; - bool ok = true; - - tw = next_power_of_2 (w); - th = next_power_of_2 (h); - - glfcns.glGenTextures (1, &id); - glfcns.glBindTexture (GL_TEXTURE_2D, id); - - if (data.is_double_type ()) - { - const NDArray xdata = data.array_value (); - - OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th)); - - for (int i = 0; i < h; i++) - { - for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) - { - a[idx] = xdata(i,j,0); - a[idx+1] = xdata(i,j,1); - a[idx+2] = xdata(i,j,2); - } - } - - glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, - GL_FLOAT, a); - } - - else if (data.is_single_type ()) - { - const FloatNDArray xdata = data.float_array_value (); - - OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th)); - - for (int i = 0; i < h; i++) - { - for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) - { - a[idx] = xdata(i,j,0); - a[idx+1] = xdata(i,j,1); - a[idx+2] = xdata(i,j,2); - } - } - - glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, - GL_FLOAT, a); - } - else if (data.is_uint16_type ()) - { - const uint16NDArray xdata = data.uint16_array_value (); - - OCTAVE_LOCAL_BUFFER (GLushort, a, (3*tw*th)); - - for (int i = 0; i < h; i++) - { - for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) - { - a[idx] = xdata(i,j,0); - a[idx+1] = xdata(i,j,1); - a[idx+2] = xdata(i,j,2); - } - } - - glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, - GL_RGB, GL_UNSIGNED_SHORT, a); - } - else if (data.is_uint8_type () && dv(2) == 3) - { - const uint8NDArray xdata = data.uint8_array_value (); - - OCTAVE_LOCAL_BUFFER (GLubyte, a, (3*tw*th)); - - for (int i = 0; i < h; i++) - { - for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) - { - a[idx] = xdata(i,j,0); - a[idx+1] = xdata(i,j,1); - a[idx+2] = xdata(i,j,2); - } - } - - glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, - GL_RGB, GL_UNSIGNED_BYTE, a); - } - else if (data.is_uint8_type () && dv(2) == 4) - { - const uint8NDArray xdata = data.uint8_array_value (); - - OCTAVE_LOCAL_BUFFER (GLubyte, a, (4*tw*th)); - - for (int i = 0; i < h; i++) - { - for (int j = 0, idx = i*tw*4; j < w; j++, idx += 4) - { - a[idx] = xdata(i,j,0); - a[idx+1] = xdata(i,j,1); - a[idx+2] = xdata(i,j,2); - a[idx+3] = xdata(i,j,3); - } - } - - glfcns.glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, - GL_RGBA, GL_UNSIGNED_BYTE, a); - } - else - { - ok = false; - warning ("opengl_texture::create: invalid image data type, expected double, single, uint8, or uint16"); - } - - if (ok) - { - glfcns.glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - glfcns.glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - - if (glfcns.glGetError () != GL_NO_ERROR) - warning ("opengl_texture::create: OpenGL error while generating texture data"); - else - retval = opengl_texture (glfcns, id, w, h, tw, th); - } - } - else - warning ("opengl_texture::create: invalid texture data size"); - - return retval; - } - - class - opengl_tessellator +class opengl_texture +{ +private: + + class texture_rep { public: -#if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS) - typedef GLvoid (CALLBACK *fcn) (...); -#else - typedef void (CALLBACK *fcn) (void); -#endif - - public: - - opengl_tessellator (void) : m_glu_tess (nullptr), m_fill () { init (); } - - // No copying! - - opengl_tessellator (const opengl_tessellator&) = delete; - - opengl_tessellator operator = (const opengl_tessellator&) = delete; - - virtual ~opengl_tessellator (void) - { if (m_glu_tess) gluDeleteTess (m_glu_tess); } - - void begin_polygon (bool filled = true) + + texture_rep (opengl_functions& glfcns) + : m_glfcns (glfcns), m_id (), m_w (), m_h (), m_tw (), m_th (), + m_tx (), m_ty (), m_valid (false) + { } + + texture_rep (opengl_functions& glfcns, GLuint id, int w, int h, + int tw, int th) + : m_glfcns (glfcns), m_id (id), m_w (w), m_h (h), m_tw (tw), m_th (th), + m_tx (double(m_w)/m_tw), m_ty (double(m_h)/m_th), m_valid (true) + { } + + ~texture_rep (void) { - gluTessProperty (m_glu_tess, GLU_TESS_BOUNDARY_ONLY, - (filled ? GL_FALSE : GL_TRUE)); - m_fill = filled; - gluTessBeginPolygon (m_glu_tess, this); + if (m_valid) + m_glfcns.glDeleteTextures (1, &m_id); + } + + void bind (int mode) const + { + if (m_valid) + m_glfcns.glBindTexture (mode, m_id); + } + + void tex_coord (double q, double r) const + { + if (m_valid) + m_glfcns.glTexCoord2d (q*m_tx, r*m_ty); } - void end_polygon (void) const - { gluTessEndPolygon (m_glu_tess); } - - void begin_contour (void) const - { gluTessBeginContour (m_glu_tess); } - - void end_contour (void) const - { gluTessEndContour (m_glu_tess); } - - void add_vertex (double *loc, void *data) const - { gluTessVertex (m_glu_tess, loc, data); } - - protected: - virtual void begin (GLenum /*type*/) { } - - virtual void end (void) { } - - virtual void vertex (void * /*data*/) { } - - virtual void combine (GLdouble [3] /*c*/, void * [4] /*data*/, - GLfloat [4] /*w*/, void ** /*out_data*/) { } - - virtual void edge_flag (GLboolean /*flag*/) { } - - virtual void error (GLenum err) - { ::error ("OpenGL tessellation error (%d)", err); } - - virtual void init (void) - { - m_glu_tess = gluNewTess (); - - gluTessCallback (m_glu_tess, GLU_TESS_BEGIN_DATA, - reinterpret_cast (tess_begin)); - gluTessCallback (m_glu_tess, GLU_TESS_END_DATA, - reinterpret_cast (tess_end)); - gluTessCallback (m_glu_tess, GLU_TESS_VERTEX_DATA, - reinterpret_cast (tess_vertex)); - gluTessCallback (m_glu_tess, GLU_TESS_COMBINE_DATA, - reinterpret_cast (tess_combine)); - gluTessCallback (m_glu_tess, GLU_TESS_EDGE_FLAG_DATA, - reinterpret_cast (tess_edge_flag)); - gluTessCallback (m_glu_tess, GLU_TESS_ERROR_DATA, - reinterpret_cast (tess_error)); - } - - bool is_filled (void) const { return m_fill; } - - private: - static void CALLBACK tess_begin (GLenum type, void *t) - { reinterpret_cast (t)->begin (type); } - - static void CALLBACK tess_end (void *t) - { reinterpret_cast (t)->end (); } - - static void CALLBACK tess_vertex (void *v, void *t) - { reinterpret_cast (t)->vertex (v); } - - static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4], - void **out, void *t) - { reinterpret_cast (t)->combine (c, v, w, out); } - - static void CALLBACK tess_edge_flag (GLboolean flag, void *t) - { reinterpret_cast (t)->edge_flag (flag); } - - static void CALLBACK tess_error (GLenum err, void *t) - { reinterpret_cast (t)->error (err); } - - //-------- - - GLUtesselator *m_glu_tess; - bool m_fill; + opengl_functions& m_glfcns; + GLuint m_id; + int m_w, m_h; + int m_tw, m_th; + double m_tx, m_ty; + bool m_valid; }; - class vertex_data - { - public: - - class vertex_data_rep +public: + + opengl_texture (opengl_functions& glfcns) + : m_rep (new texture_rep (glfcns)) + { } + + opengl_texture (opengl_functions& glfcns, GLuint id, int w, int h, + int tw, int th) + : m_rep (new texture_rep (glfcns, id, w, h, tw, th)) + { } + + opengl_texture (const opengl_texture&) = default; + + ~opengl_texture (void) = default; + + opengl_texture& operator = (const opengl_texture&) = default; + + static opengl_texture create (opengl_functions& glfcns, + const octave_value& data); + + void bind (int mode = GL_TEXTURE_2D) const { m_rep->bind (mode); } + + void tex_coord (double q, double r) const { m_rep->tex_coord (q, r); } + + bool is_valid (void) const { return m_rep->m_valid; } + +private: + + opengl_texture (const std::shared_ptr& new_rep) + : m_rep (new_rep) + { } + + std::shared_ptr m_rep; +}; + +opengl_texture +opengl_texture::create (opengl_functions& glfcns, const octave_value& data) +{ + opengl_texture retval (glfcns); + + dim_vector dv (data.dims ()); + + // Expect RGB data + if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4)) { - public: - - vertex_data_rep (void) - : m_coords (), m_color (), m_vertex_normal (), m_face_normal (), - m_alpha (), m_ambient (), m_diffuse (), m_specular (), - m_specular_exp (), m_specular_color_refl () - { } - - vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& vn, - const Matrix& fn, double a, float as, float ds, float ss, - float se, float scr) - : m_coords (c), m_color (col), m_vertex_normal (vn), - m_face_normal (fn), m_alpha (a), m_ambient (as), m_diffuse (ds), - m_specular (ss), m_specular_exp (se), m_specular_color_refl (scr) - { } - - Matrix m_coords; - Matrix m_color; - Matrix m_vertex_normal; - Matrix m_face_normal; - double m_alpha; - float m_ambient; - float m_diffuse; - float m_specular; - float m_specular_exp; - float m_specular_color_refl; - }; - - public: - - // Required to instantiate std::list objects. - vertex_data (void) : m_rep (nil_rep ()) { } - - vertex_data (const Matrix& c, const Matrix& col, const Matrix& vn, - const Matrix& fn, double a, float as, float ds, float ss, - float se, float scr) - : m_rep (new vertex_data_rep (c, col, vn, fn, a, as, ds, ss, se, scr)) - { } - - vertex_data (const vertex_data&) = default; - - ~vertex_data (void) = default; - - vertex_data& operator = (const vertex_data&) = default; - - vertex_data_rep * get_rep (void) const { return m_rep.get (); } - - private: - - static std::shared_ptr nil_rep (void) - { - static std::shared_ptr nr (new vertex_data_rep ()); - - return nr; - } - - std::shared_ptr m_rep; - }; - - class - opengl_renderer::patch_tessellator : public opengl_tessellator - { - public: - patch_tessellator (opengl_renderer *r, int cmode, int lmode, bool fl, - float idx = 0.0) - : opengl_tessellator (), m_renderer (r), - m_color_mode (cmode), m_light_mode (lmode), m_face_lighting (fl), - m_index (idx), m_first (true), m_tmp_vdata () - { } - - protected: - void begin (GLenum type) - { - opengl_functions& glfcns = m_renderer->get_opengl_functions (); - - //printf ("patch_tessellator::begin (%d)\n", type); - m_first = true; - - if (m_color_mode == INTERP || m_light_mode == GOURAUD) - glfcns.glShadeModel (GL_SMOOTH); - else - glfcns.glShadeModel (GL_FLAT); - - if (is_filled ()) - m_renderer->set_polygon_offset (true, m_index); - - glfcns.glBegin (type); - } - - void end (void) - { - opengl_functions& glfcns = m_renderer->get_opengl_functions (); - - //printf ("patch_tessellator::end\n"); - glfcns.glEnd (); - m_renderer->set_polygon_offset (false); - } - - void vertex (void *data) - { - opengl_functions& glfcns = m_renderer->get_opengl_functions (); - - vertex_data::vertex_data_rep *v - = reinterpret_cast (data); - //printf ("patch_tessellator::vertex (%g, %g, %g)\n", v->m_coords(0), v->m_coords(1), v->m_coords(2)); - - // NOTE: OpenGL can re-order vertices. For "flat" coloring of FaceColor - // the first vertex must be identified in the draw_patch routine. - - if (m_color_mode == INTERP || (m_color_mode == FLAT && ! is_filled ())) + // FIXME: dim_vectors hold octave_idx_type values. + // Should we check for dimensions larger than intmax? + int h, w, tw, th; + h = dv(0), w = dv(1); + + // Return early if the image data are larger than the texture + // can hold + int max_size; + glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size); + static bool warned = false; + if (h > max_size || w > max_size) + { + if (! warned) + { + warning ("opengl_texture::create: the opengl library in use " + "doesn't support images with either dimension larger " + "than %d. Not rendering.", max_size); + warned = true; + } + + return opengl_texture (glfcns); + } + + GLuint id; + bool ok = true; + + tw = next_power_of_2 (w); + th = next_power_of_2 (h); + + glfcns.glGenTextures (1, &id); + glfcns.glBindTexture (GL_TEXTURE_2D, id); + + if (data.is_double_type ()) + { + const NDArray xdata = data.array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th)); + + for (int i = 0; i < h; i++) + { + for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) + { + a[idx] = xdata(i, j, 0); + a[idx+1] = xdata(i, j, 1); + a[idx+2] = xdata(i, j, 2); + } + } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, + GL_FLOAT, a); + } + + else if (data.is_single_type ()) { - Matrix col = v->m_color; - - if (col.numel () == 3) + const FloatNDArray xdata = data.float_array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*tw*th)); + + for (int i = 0; i < h; i++) { - glfcns.glColor4d (col(0), col(1), col(2), v->m_alpha); - if (m_light_mode > 0) + for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) + { + a[idx] = xdata(i, j, 0); + a[idx+1] = xdata(i, j, 1); + a[idx+2] = xdata(i, j, 2); + } + } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, GL_RGB, + GL_FLOAT, a); + } + else if (data.is_uint16_type ()) + { + const uint16NDArray xdata = data.uint16_array_value (); + + OCTAVE_LOCAL_BUFFER (GLushort, a, (3*tw*th)); + + for (int i = 0; i < h; i++) + { + for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) { - // edge lighting only uses ambient light - float buf[4] = { 0.0f, 0.0f, 0.0f, 1.0f };; - - if (m_face_lighting) - for (int k = 0; k < 3; k++) - buf[k] = (v->m_specular - * (v->m_specular_color_refl + - (1 - v->m_specular_color_refl) * col(k))); - glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf); - - if (m_face_lighting) - for (int k = 0; k < 3; k++) - buf[k] = (v->m_diffuse * col(k)); - glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf); - - for (int k = 0; k < 3; k++) - buf[k] = (v->m_ambient * col(k)); - glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf); + a[idx] = xdata(i, j, 0); + a[idx+1] = xdata(i, j, 1); + a[idx+2] = xdata(i, j, 2); + } + } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, + GL_RGB, GL_UNSIGNED_SHORT, a); + } + else if (data.is_uint8_type () && dv(2) == 3) + { + const uint8NDArray xdata = data.uint8_array_value (); + + OCTAVE_LOCAL_BUFFER (GLubyte, a, (3*tw*th)); + + for (int i = 0; i < h; i++) + { + for (int j = 0, idx = i*tw*3; j < w; j++, idx += 3) + { + a[idx] = xdata(i, j, 0); + a[idx+1] = xdata(i, j, 1); + a[idx+2] = xdata(i, j, 2); + } + } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, 3, tw, th, 0, + GL_RGB, GL_UNSIGNED_BYTE, a); + } + else if (data.is_uint8_type () && dv(2) == 4) + { + const uint8NDArray xdata = data.uint8_array_value (); + + OCTAVE_LOCAL_BUFFER (GLubyte, a, (4*tw*th)); + + for (int i = 0; i < h; i++) + { + for (int j = 0, idx = i*tw*4; j < w; j++, idx += 4) + { + a[idx] = xdata(i, j, 0); + a[idx+1] = xdata(i, j, 1); + a[idx+2] = xdata(i, j, 2); + a[idx+3] = xdata(i, j, 3); } } + + glfcns.glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, tw, th, 0, + GL_RGBA, GL_UNSIGNED_BYTE, a); } - - if (m_light_mode == FLAT && m_first) - glfcns.glNormal3dv (v->m_face_normal.data ()); - else if (m_light_mode == GOURAUD) - glfcns.glNormal3dv (v->m_vertex_normal.data ()); - - glfcns.glVertex3dv (v->m_coords.data ()); - - m_first = false; - } - - void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data) - { - vertex_data::vertex_data_rep *v[4]; - int vmax = 4; - - for (int i = 0; i < 4; i++) + else { - v[i] = reinterpret_cast (data[i]); - - if (vmax == 4 && ! v[i]) - vmax = i; + ok = false; + warning ("opengl_texture::create: invalid image data type, expected double, single, uint8, or uint16"); } - Matrix vv (1, 3, 0.0); - Matrix cc; - Matrix vnn (1, 3, 0.0); - Matrix fnn (1, 3, 0.0); - double aa = 0.0; - - vv(0) = xyz[0]; - vv(1) = xyz[1]; - vv(2) = xyz[2]; - - if (v[0]->m_color.numel ()) - { - cc.resize (1, 3, 0.0); - for (int ic = 0; ic < 3; ic++) - for (int iv = 0; iv < vmax; iv++) - cc(ic) += (w[iv] * v[iv]->m_color (ic)); - } - - if (v[0]->m_vertex_normal.numel () > 0) + if (ok) { - for (int in = 0; in < 3; in++) - for (int iv = 0; iv < vmax; iv++) - vnn(in) += (w[iv] * v[iv]->m_vertex_normal (in)); - } - - if (v[0]->m_face_normal.numel () > 0) - { - for (int in = 0; in < 3; in++) - for (int iv = 0; iv < vmax; iv++) - fnn(in) += (w[iv] * v[iv]->m_face_normal (in)); + glfcns.glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glfcns.glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + + if (glfcns.glGetError () != GL_NO_ERROR) + warning ("opengl_texture::create: OpenGL error while generating texture data"); + else + retval = opengl_texture (glfcns, id, w, h, tw, th); } - - for (int iv = 0; iv < vmax; iv++) - aa += (w[iv] * v[iv]->m_alpha); - - vertex_data new_v (vv, cc, vnn, fnn, aa, v[0]->m_ambient, v[0]->m_diffuse, - v[0]->m_specular, v[0]->m_specular_exp, - v[0]->m_specular_color_refl); - m_tmp_vdata.push_back (new_v); - - *out_data = new_v.get_rep (); } - - private: - - // No copying! - - patch_tessellator (const patch_tessellator&) = delete; - - patch_tessellator& operator = (const patch_tessellator&) = delete; - - opengl_renderer *m_renderer; - int m_color_mode; - int m_light_mode; - bool m_face_lighting; - int m_index; - bool m_first; - std::list m_tmp_vdata; - }; - + else + warning ("opengl_texture::create: invalid texture data size"); + + return retval; +} + +class +opengl_tessellator +{ +public: +#if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS) + typedef GLvoid (CALLBACK *fcn) (...); #else - - class - opengl_renderer::patch_tessellator - { - // Dummy class. - }; - + typedef void (CALLBACK *fcn) (void); #endif - opengl_renderer::opengl_renderer (opengl_functions& glfcns) - : m_glfcns (glfcns), m_xmin (), m_xmax (), m_ymin (), m_ymax (), - m_zmin (), m_zmax (), m_devpixratio (1.0), m_xform (), m_toolkit (), - m_xZ1 (), m_xZ2 (), m_marker_id (), m_filled_marker_id (), - m_camera_pos (), m_camera_dir (), m_view_vector (), - m_interpreter ("none"), m_txt_renderer (), m_current_light (0), - m_max_lights (0), m_selecting (false), m_printing (false) - { - // This constructor will fail if we don't have OpenGL or if the data - // types we assumed in our public interface aren't compatible with the - // OpenGL types. - -#if defined (HAVE_OPENGL) - - // Ensure that we can't request an image larger than OpenGL can handle. - // FIXME: should we check signed vs. unsigned? - - static bool ok = (sizeof (int) <= sizeof (GLsizei)); - - if (! ok) - error ("the size of GLsizei is smaller than the size of int"); - -#else - - err_disabled_feature ("opengl_renderer", "OpenGL"); - -#endif - } - - void - opengl_renderer::draw (const graphics_object& go, bool toplevel) - { - if (! go.valid_object ()) - return; - - const base_properties& props = go.get_properties (); - - if (! m_toolkit) - m_toolkit = props.get_toolkit (); - - if (go.isa ("figure")) - draw_figure (dynamic_cast (props)); - else if (go.isa ("axes")) - draw_axes (dynamic_cast (props)); - else if (go.isa ("line")) - draw_line (dynamic_cast (props)); - else if (go.isa ("surface")) - draw_surface (dynamic_cast (props)); - else if (go.isa ("patch")) - draw_patch (dynamic_cast (props)); - else if (go.isa ("scatter")) - draw_scatter (dynamic_cast (props)); - else if (go.isa ("light")) - draw_light (dynamic_cast (props)); - else if (go.isa ("hggroup")) - draw_hggroup (dynamic_cast (props)); - else if (go.isa ("text")) - draw_text (dynamic_cast (props)); - else if (go.isa ("image")) - draw_image (dynamic_cast (props)); - else if (go.isa ("uimenu") || go.isa ("uicontrol") - || go.isa ("uicontextmenu") || go.isa ("uitoolbar") - || go.isa ("uipushtool") || go.isa ("uitoggletool") - || go.isa ("uitable")) - ; // SKIP - else if (go.isa ("uipanel")) - { - if (toplevel) - draw_uipanel (dynamic_cast (props), go); - } - else if (go.isa ("uibuttongroup")) - { - if (toplevel) - draw_uibuttongroup (dynamic_cast (props), go); - } - else - { - warning ("opengl_renderer: cannot render object of type '%s'", - props.graphics_object_name ().c_str ()); - } - -#if defined (HAVE_OPENGL) - - GLenum gl_error = m_glfcns.glGetError (); - if (gl_error) - warning ("opengl_renderer: Error '%s' (%d) occurred drawing '%s' object", - gluErrorString (gl_error), gl_error, - props.graphics_object_name ().c_str ()); - -#endif - } - - void - opengl_renderer::draw_figure (const figure::properties& props) - { - m_printing = props.is___printing__ (); - - // Initialize OpenGL context - init_gl_context (props.is_graphicssmoothing (), props.get_color_rgb ()); - -#if defined (HAVE_OPENGL) - - props.set___gl_extensions__ (get_string (GL_EXTENSIONS)); - props.set___gl_renderer__ (get_string (GL_RENDERER)); - props.set___gl_vendor__ (get_string (GL_VENDOR)); - props.set___gl_version__ (get_string (GL_VERSION)); - -#endif - - // Draw children - - draw (props.get_all_children (), false); - } - - void - opengl_renderer::draw_uipanel (const uipanel::properties& props, - const graphics_object& go) - { - graphics_object fig = go.get_ancestor ("figure"); - const figure::properties& figProps - = dynamic_cast (fig.get_properties ()); - - // Initialize OpenGL context - - init_gl_context (figProps.is_graphicssmoothing (), - props.get_backgroundcolor_rgb ()); - - // Draw children - - draw (props.get_all_children (), false); - } - - void - opengl_renderer::draw_uibuttongroup (const uibuttongroup::properties& props, - const graphics_object& go) +public: + + opengl_tessellator (void) : m_glu_tess (nullptr), m_fill () { init (); } + + // No copying! + + opengl_tessellator (const opengl_tessellator&) = delete; + + opengl_tessellator operator = (const opengl_tessellator&) = delete; + + virtual ~opengl_tessellator (void) + { if (m_glu_tess) gluDeleteTess (m_glu_tess); } + + void begin_polygon (bool filled = true) { - graphics_object fig = go.get_ancestor ("figure"); - const figure::properties& figProps - = dynamic_cast (fig.get_properties ()); - - // Initialize OpenGL context - - init_gl_context (figProps.is_graphicssmoothing (), - props.get_backgroundcolor_rgb ()); - - // Draw children - - draw (props.get_all_children (), false); + gluTessProperty (m_glu_tess, GLU_TESS_BOUNDARY_ONLY, + (filled ? GL_FALSE : GL_TRUE)); + m_fill = filled; + gluTessBeginPolygon (m_glu_tess, this); } - void - opengl_renderer::init_gl_context (bool enhanced, const Matrix& c) - { -#if defined (HAVE_OPENGL) - - // Initialize OpenGL context - - m_glfcns.glEnable (GL_DEPTH_TEST); - m_glfcns.glDepthFunc (GL_LEQUAL); - m_glfcns.glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - m_glfcns.glAlphaFunc (GL_GREATER, 0.0f); - m_glfcns.glEnable (GL_NORMALIZE); - m_glfcns.glEnable (GL_BLEND); - - if (enhanced) - { - m_glfcns.glEnable (GL_MULTISAMPLE); - bool has_multisample = false; - if (! m_glfcns.glGetError ()) - { - GLint iMultiSample, iNumSamples; - m_glfcns.glGetIntegerv (GL_SAMPLE_BUFFERS, &iMultiSample); - m_glfcns.glGetIntegerv (GL_SAMPLES, &iNumSamples); - if (iMultiSample == GL_TRUE && iNumSamples > 0) - has_multisample = true; - } - - if (! has_multisample) - { - // MultiSample not implemented. Use old-style anti-aliasing - m_glfcns.glDisable (GL_MULTISAMPLE); - // Disabling GL_MULTISAMPLE will raise a gl error if it is not - // implemented. Thus, call glGetError to reset the error state. - m_glfcns.glGetError (); - - m_glfcns.glEnable (GL_LINE_SMOOTH); - m_glfcns.glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); - } - } - else - { - m_glfcns.glDisable (GL_LINE_SMOOTH); - } - - // Clear background - - if (c.numel () >= 3) - { - m_glfcns.glClearColor (c(0), c(1), c(2), 1); - m_glfcns.glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - - GLenum gl_error = m_glfcns.glGetError (); - if (gl_error) - warning ("opengl_renderer: Error '%s' (%d) occurred in init_gl_context", - gluErrorString (gl_error), gl_error); - -#else - - octave_unused_parameter (enhanced); - octave_unused_parameter (c); - - // 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::render_grid (const double linewidth, - const std::string& gridstyle, - const Matrix& gridcolor, const double gridalpha, - const Matrix& ticks, double lim1, double lim2, - double p1, double p1N, double p2, double p2N, - int xyz, bool is_3D) + void end_polygon (void) const + { gluTessEndPolygon (m_glu_tess); } + + void begin_contour (void) const + { gluTessBeginContour (m_glu_tess); } + + void end_contour (void) const + { gluTessEndContour (m_glu_tess); } + + void add_vertex (double *loc, void *data) const + { gluTessVertex (m_glu_tess, loc, data); } + +protected: + virtual void begin (GLenum /*type*/) { } + + virtual void end (void) { } + + virtual void vertex (void * /*data*/) { } + + virtual void combine (GLdouble [3] /*c*/, void *[4] /*data*/, + GLfloat [4] /*w*/, void ** /*out_data*/) { } + + virtual void edge_flag (GLboolean /*flag*/) { } + + virtual void error (GLenum err) + { ::error ("OpenGL tessellation error (%d)", err); } + + virtual void init (void) { -#if defined (HAVE_OPENGL) - - m_glfcns.glColor4d (gridcolor(0), gridcolor(1), gridcolor(2), gridalpha); - set_linestyle (gridstyle, true, linewidth); - m_glfcns.glBegin (GL_LINES); - for (int i = 0; i < ticks.numel (); i++) - { - double val = ticks(i); - if (lim1 <= val && val <= lim2) - { - if (xyz == X_AXIS) - { - m_glfcns.glVertex3d (val, p1N, p2); - m_glfcns.glVertex3d (val, p1, p2); - if (is_3D) - { - m_glfcns.glVertex3d (val, p1, p2N); - m_glfcns.glVertex3d (val, p1, p2); - } - } - else if (xyz == Y_AXIS) - { - m_glfcns.glVertex3d (p1N, val, p2); - m_glfcns.glVertex3d (p1, val, p2); - if (is_3D) - { - m_glfcns.glVertex3d (p1, val, p2N); - m_glfcns.glVertex3d (p1, val, p2); - } - } - else if (xyz == Z_AXIS) - { - m_glfcns.glVertex3d (p1N, p2, val); - m_glfcns.glVertex3d (p1, p2, val); - m_glfcns.glVertex3d (p1, p2N, val); - m_glfcns.glVertex3d (p1, p2, val); - } - } - } - m_glfcns.glEnd (); - set_linestyle ("-"); // Disable LineStipple - double black[3] = {0, 0, 0}; - m_glfcns.glColor3dv (black); - -#else - - octave_unused_parameter (linewidth); - octave_unused_parameter (gridstyle); - octave_unused_parameter (gridcolor); - octave_unused_parameter (gridalpha); - octave_unused_parameter (ticks); - octave_unused_parameter (lim1); - octave_unused_parameter (lim2); - octave_unused_parameter (p1); - octave_unused_parameter (p1N); - octave_unused_parameter (p2); - octave_unused_parameter (p2N); - octave_unused_parameter (xyz); - octave_unused_parameter (is_3D); - - // 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::render_tickmarks (const Matrix& ticks, - double lim1, double lim2, - double p1, double p1N, - double p2, double p2N, - double dx, double dy, double dz, - int xyz, bool mirror) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glBegin (GL_LINES); - - for (int i = 0; i < ticks.numel (); i++) - { - double val = ticks(i); - - if (lim1 <= val && val <= lim2) - { - if (xyz == X_AXIS) - { - m_glfcns.glVertex3d (val, p1, p2); - m_glfcns.glVertex3d (val, p1+dy, p2+dz); - if (mirror) - { - m_glfcns.glVertex3d (val, p1N, p2N); - m_glfcns.glVertex3d (val, p1N-dy, p2N-dz); - } - } - else if (xyz == Y_AXIS) - { - m_glfcns.glVertex3d (p1, val, p2); - m_glfcns.glVertex3d (p1+dx, val, p2+dz); - if (mirror) - { - m_glfcns.glVertex3d (p1N, val, p2N); - m_glfcns.glVertex3d (p1N-dx, val, p2N-dz); - } - } - else if (xyz == Z_AXIS) - { - m_glfcns.glVertex3d (p1, p2, val); - m_glfcns.glVertex3d (p1+dx, p2+dy, val); - if (mirror) - { - m_glfcns.glVertex3d (p1N, p2N, val); - m_glfcns.glVertex3d (p1N-dx, p2N-dy, val); - } - } - } - } - - m_glfcns.glEnd (); - -#else - - octave_unused_parameter (ticks); - octave_unused_parameter (lim1); - octave_unused_parameter (lim2); - octave_unused_parameter (p1); - octave_unused_parameter (p1N); - octave_unused_parameter (p2); - octave_unused_parameter (p2N); - octave_unused_parameter (dx); - octave_unused_parameter (dy); - octave_unused_parameter (dz); - octave_unused_parameter (xyz); - octave_unused_parameter (mirror); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); - -#endif + m_glu_tess = gluNewTess (); + + gluTessCallback (m_glu_tess, GLU_TESS_BEGIN_DATA, + reinterpret_cast (tess_begin)); + gluTessCallback (m_glu_tess, GLU_TESS_END_DATA, + reinterpret_cast (tess_end)); + gluTessCallback (m_glu_tess, GLU_TESS_VERTEX_DATA, + reinterpret_cast (tess_vertex)); + gluTessCallback (m_glu_tess, GLU_TESS_COMBINE_DATA, + reinterpret_cast (tess_combine)); + gluTessCallback (m_glu_tess, GLU_TESS_EDGE_FLAG_DATA, + reinterpret_cast (tess_edge_flag)); + gluTessCallback (m_glu_tess, GLU_TESS_ERROR_DATA, + reinterpret_cast (tess_error)); } - void - opengl_renderer::render_ticktexts (const Matrix& ticks, - const string_vector& ticklabels, - double lim1, double lim2, - double p1, double p2, - int xyz, int ha, int va, - int& wmax, int& hmax) - { -#if defined (HAVE_OPENGL) - - int nticks = ticks.numel (); - int nlabels = ticklabels.numel (); - - if (nlabels == 0) - return; - - for (int i = 0; i < nticks; i++) - { - double val = ticks(i); - - if (lim1 <= val && val <= lim2) - { - Matrix b; - - std::string label (ticklabels(i % nlabels)); - label.erase (0, label.find_first_not_of (' ')); - label = label.substr (0, label.find_last_not_of (' ')+1); - - // FIXME: As tick text is transparent, shouldn't it be - // drawn after axes object, for correct rendering? - if (xyz == X_AXIS) - { - b = render_text (label, val, p1, p2, ha, va); - } - else if (xyz == Y_AXIS) - { - b = render_text (label, p1, val, p2, ha, va); - } - else if (xyz == Z_AXIS) - { - b = render_text (label, p1, p2, val, ha, va); - } - - wmax = std::max (wmax, static_cast (b(2))); - hmax = std::max (hmax, static_cast (b(3))); - } - } - -#else - - octave_unused_parameter (ticks); - octave_unused_parameter (ticklabels); - octave_unused_parameter (lim1); - octave_unused_parameter (lim2); - octave_unused_parameter (p1); - octave_unused_parameter (p2); - octave_unused_parameter (xyz); - octave_unused_parameter (ha); - octave_unused_parameter (va); - octave_unused_parameter (wmax); - octave_unused_parameter (hmax); - - // 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_zoom_rect (int x1, int y1, int x2, int y2) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glVertex2d (x1, y1); - m_glfcns.glVertex2d (x2, y1); - m_glfcns.glVertex2d (x2, y2); - m_glfcns.glVertex2d (x1, y2); - m_glfcns.glVertex2d (x1, y1); - -#else - - octave_unused_parameter (x1); - octave_unused_parameter (x2); - octave_unused_parameter (y1); - octave_unused_parameter (y2); - - // 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_zoom_box (int width, int height, - int x1, int y1, int x2, int y2, - const Matrix& overlaycolor, - double overlayalpha, - const Matrix& bordercolor, - double borderalpha, double borderwidth) + bool is_filled (void) const { return m_fill; } + +private: + static void CALLBACK tess_begin (GLenum type, void *t) + { reinterpret_cast (t)->begin (type); } + + static void CALLBACK tess_end (void *t) + { reinterpret_cast (t)->end (); } + + static void CALLBACK tess_vertex (void *v, void *t) + { reinterpret_cast (t)->vertex (v); } + + static void CALLBACK tess_combine (GLdouble c[3], void *v[4], GLfloat w[4], + void **out, void *t) + { reinterpret_cast (t)->combine (c, v, w, out); } + + static void CALLBACK tess_edge_flag (GLboolean flag, void *t) + { reinterpret_cast (t)->edge_flag (flag); } + + static void CALLBACK tess_error (GLenum err, void *t) + { reinterpret_cast (t)->error (err); } + + //-------- + + GLUtesselator *m_glu_tess; + bool m_fill; +}; + +class vertex_data +{ +public: + + class vertex_data_rep { -#if defined (HAVE_OPENGL) - - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glPushMatrix (); - m_glfcns.glLoadIdentity (); - - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glPushMatrix (); - m_glfcns.glLoadIdentity (); - m_glfcns.glOrtho (0, width, height, 0, 1, -1); - - m_glfcns.glPushAttrib (GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT); - m_glfcns.glDisable (GL_DEPTH_TEST); - - m_glfcns.glBegin (GL_POLYGON); - m_glfcns.glColor4f (overlaycolor(0), overlaycolor(1), overlaycolor(2), - overlayalpha); - draw_zoom_rect (x1, y1, x2, y2); - m_glfcns.glEnd (); - - m_glfcns.glLineWidth (borderwidth); - m_glfcns.glBegin (GL_LINE_STRIP); - m_glfcns.glColor4f (bordercolor(0), bordercolor(1), bordercolor(2), - borderalpha); - draw_zoom_rect (x1, y1, x2, y2); - m_glfcns.glEnd (); - - m_glfcns.glPopAttrib (); - - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glPopMatrix (); - - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glPopMatrix (); - -#else - - octave_unused_parameter (width); - octave_unused_parameter (height); - octave_unused_parameter (x1); - octave_unused_parameter (x2); - octave_unused_parameter (y1); - octave_unused_parameter (y2); - octave_unused_parameter (overlaycolor); - octave_unused_parameter (overlayalpha); - octave_unused_parameter (bordercolor); - octave_unused_parameter (borderalpha); - octave_unused_parameter (borderwidth); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); - -#endif - } - - uint8NDArray - opengl_renderer::get_pixels (int width, int height) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glPixelStorei (GL_PACK_ALIGNMENT, 1); - uint8NDArray pix(dim_vector (3, width, height), 0); - - m_glfcns.glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, - pix.fortran_vec ()); - - // Permute and flip data - Array perm (dim_vector (3, 1)); - perm(0) = 2; - perm(1) = 1; - perm(2) = 0; - - Array idx (dim_vector (3, 1)); - idx(0) = idx_vector::make_range (height - 1, -1, height); - idx(1) = idx_vector::colon; - idx(2) = idx_vector::colon; - - return pix.permute (perm).index (idx); - -#else - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - octave_unused_parameter (width); - octave_unused_parameter (height); - - panic_impossible (); - -#endif - } - - void - opengl_renderer::finish (void) - { -#if defined (HAVE_OPENGL) - - m_glfcns.glFinish (); - -#else - - // 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::setup_opengl_transformation (const axes::properties& props) + public: + + vertex_data_rep (void) + : m_coords (), m_color (), m_vertex_normal (), m_face_normal (), + m_alpha (), m_ambient (), m_diffuse (), m_specular (), + m_specular_exp (), m_specular_color_refl () + { } + + vertex_data_rep (const Matrix& c, const Matrix& col, const Matrix& vn, + const Matrix& fn, double a, float as, float ds, float ss, + float se, float scr) + : m_coords (c), m_color (col), m_vertex_normal (vn), + m_face_normal (fn), m_alpha (a), m_ambient (as), m_diffuse (ds), + m_specular (ss), m_specular_exp (se), m_specular_color_refl (scr) + { } + + Matrix m_coords; + Matrix m_color; + Matrix m_vertex_normal; + Matrix m_face_normal; + double m_alpha; + float m_ambient; + float m_diffuse; + float m_specular; + float m_specular_exp; + float m_specular_color_refl; + }; + +public: + + // Required to instantiate std::list objects. + vertex_data (void) : m_rep (nil_rep ()) { } + + vertex_data (const Matrix& c, const Matrix& col, const Matrix& vn, + const Matrix& fn, double a, float as, float ds, float ss, + float se, float scr) + : m_rep (new vertex_data_rep (c, col, vn, fn, a, as, ds, ss, se, scr)) + { } + + vertex_data (const vertex_data&) = default; + + ~vertex_data (void) = default; + + vertex_data& operator = (const vertex_data&) = default; + + vertex_data_rep * get_rep (void) const { return m_rep.get (); } + +private: + + static std::shared_ptr nil_rep (void) { -#if defined (HAVE_OPENGL) - - // setup OpenGL transformation - - Matrix x_zlim = props.get_transform_zlim (); - - // Expand the distance between the clipping planes symmetrically by - // an arbitrary factor (see bug #54551). - const double expansion_fac = 100.0; - // Also make sure that the distance between the clipping planes - // differs in single precision (see bug #58956). This factor is also - // arbitrary. Different values (>2) might also work. - const double single_prec_fac = 10.0; - - double avgZ = x_zlim(0) / 2.0 + x_zlim(1) / 2.0; - double span - = std::max (expansion_fac * (x_zlim(1)-x_zlim(0)), - single_prec_fac * std::abs (avgZ) - * std::numeric_limits::epsilon ()); - m_xZ1 = avgZ - span; - m_xZ2 = avgZ + span; - - Matrix x_mat1 = props.get_opengl_matrix_1 (); - Matrix x_mat2 = props.get_opengl_matrix_2 (); - - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glLoadIdentity (); - m_glfcns.glScaled (1, 1, -1); - m_glfcns.glMultMatrixd (x_mat1.data ()); - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glLoadIdentity (); - - Matrix vp = get_viewport_scaled (); - m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2); - m_glfcns.glMultMatrixd (x_mat2.data ()); - m_glfcns.glMatrixMode (GL_MODELVIEW); - - m_glfcns.glClear (GL_DEPTH_BUFFER_BIT); - - // store axes transformation data - - m_xform = props.get_transform (); - -#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 + static std::shared_ptr nr (new vertex_data_rep ()); + + return nr; } - void - opengl_renderer::draw_axes_planes (const axes::properties& props) + std::shared_ptr m_rep; +}; + +class +opengl_renderer::patch_tessellator : public opengl_tessellator +{ +public: + patch_tessellator (opengl_renderer *r, int cmode, int lmode, bool fl, + float idx = 0.0) + : opengl_tessellator (), m_renderer (r), + m_color_mode (cmode), m_light_mode (lmode), m_face_lighting (fl), + m_index (idx), m_first (true), m_tmp_vdata () + { } + +protected: + void begin (GLenum type) { -#if defined (HAVE_OPENGL) - - Matrix axe_color = props.get_color_rgb (); - if (axe_color.isempty () || ! props.is_visible ()) - return; - - double xPlane = props.get_xPlane (); - double yPlane = props.get_yPlane (); - double zPlane = props.get_zPlane (); - double xPlaneN = props.get_xPlaneN (); - double yPlaneN = props.get_yPlaneN (); - double zPlaneN = props.get_zPlaneN (); - bool is2D = props.get_is2D (); - - // Axes planes - set_color (axe_color); - set_polygon_offset (true, 9.0); - - m_glfcns.glBegin (GL_QUADS); - - if (! is2D) - { - // X plane - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlane, zPlane); - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); - - // Y plane - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlane, zPlane); - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); - } - - // Z plane - m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlane); - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); - m_glfcns.glVertex3d (xPlane, yPlane, zPlane); - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); - - m_glfcns.glEnd (); - - set_polygon_offset (false); - -#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 + opengl_functions& glfcns = m_renderer->get_opengl_functions (); + + //printf ("patch_tessellator::begin (%d)\n", type); + m_first = true; + + if (m_color_mode == INTERP || m_light_mode == GOURAUD) + glfcns.glShadeModel (GL_SMOOTH); + else + glfcns.glShadeModel (GL_FLAT); + + if (is_filled ()) + m_renderer->set_polygon_offset (true, m_index); + + glfcns.glBegin (type); } - void - opengl_renderer::draw_axes_boxes (const axes::properties& props) + void end (void) { -#if defined (HAVE_OPENGL) - - if (! props.is_visible ()) - return; - - bool xySym = props.get_xySym (); - bool layer2Dtop = props.get_layer2Dtop (); - bool is2D = props.get_is2D (); - bool isXOrigin = props.xaxislocation_is ("origin") - && ! props.yscale_is ("log"); - bool isYOrigin = props.yaxislocation_is ("origin") - && ! props.xscale_is ("log"); - bool boxFull = (props.get_boxstyle () == "full"); - double linewidth = props.get_linewidth (); - double xPlane = props.get_xPlane (); - double yPlane = props.get_yPlane (); - double zPlane = props.get_zPlane (); - double xPlaneN = props.get_xPlaneN (); - double yPlaneN = props.get_yPlaneN (); - double zPlaneN = props.get_zPlaneN (); - double xpTick = props.get_xpTick (); - double ypTick = props.get_ypTick (); - double zpTick = props.get_zpTick (); - double xpTickN = props.get_xpTickN (); - double ypTickN = props.get_ypTickN (); - double zpTickN = props.get_zpTickN (); - - bool plotyy = (props.has_property ("__plotyy_axes__")); - - // Axes box - - set_linecap ("square"); - set_linestyle ("-", true, linewidth); - - m_glfcns.glBegin (GL_LINES); - - if (layer2Dtop) - std::swap (zpTick, zpTickN); - - // X box - Matrix color = props.get_xcolor_rgb (); - - if (! color.isempty ()) + opengl_functions& glfcns = m_renderer->get_opengl_functions (); + + //printf ("patch_tessellator::end\n"); + glfcns.glEnd (); + m_renderer->set_polygon_offset (false); + } + + void vertex (void *data) + { + opengl_functions& glfcns = m_renderer->get_opengl_functions (); + + vertex_data::vertex_data_rep *v + = reinterpret_cast (data); + //printf ("patch_tessellator::vertex (%g, %g, %g)\n", v->m_coords(0), v->m_coords(1), v->m_coords(2)); + + // NOTE: OpenGL can re-order vertices. For "flat" coloring of FaceColor + // the first vertex must be identified in the draw_patch routine. + + if (m_color_mode == INTERP || (m_color_mode == FLAT && ! is_filled ())) { - set_color (color); - - if (! isXOrigin || props.is_box() || ! is2D) + Matrix col = v->m_color; + + if (col.numel () == 3) { - m_glfcns.glVertex3d (xPlaneN, ypTick, zpTick); - m_glfcns.glVertex3d (xPlane, ypTick, zpTick); - } - - if (props.is_box ()) - { - m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTick); - m_glfcns.glVertex3d (xPlane, ypTickN, zpTick); - if (! is2D) + glfcns.glColor4d (col(0), col(1), col(2), v->m_alpha); + if (m_light_mode > 0) { - m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTickN); - m_glfcns.glVertex3d (xPlane, ypTickN, zpTickN); - if (boxFull) - { - m_glfcns.glVertex3d (xPlaneN, ypTick, zpTickN); - m_glfcns.glVertex3d (xPlane, ypTick, zpTickN); - } - } - } - } - - // Y box - color = props.get_ycolor_rgb (); - - if (! color.isempty ()) - { - set_color (color); - if (! isYOrigin || props.is_box() || ! is2D) - { - m_glfcns.glVertex3d (xpTick, yPlaneN, zpTick); - m_glfcns.glVertex3d (xpTick, yPlane, zpTick); - } - - if (props.is_box () && ! plotyy) - { - m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTick); - m_glfcns.glVertex3d (xpTickN, yPlane, zpTick); - - if (! is2D) - { - m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTickN); - m_glfcns.glVertex3d (xpTickN, yPlane, zpTickN); - if (boxFull) - { - m_glfcns.glVertex3d (xpTick, yPlaneN, zpTickN); - m_glfcns.glVertex3d (xpTick, yPlane, zpTickN); - } - } - } - } - - // Z box - color = props.get_zcolor_rgb (); - - if (! color.isempty () && ! is2D) - { - set_color (color); - - if (xySym) - { - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN); - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); - } - else - { - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); - } - - if (props.is_box ()) - { - m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlane, zPlane); - - if (xySym) - { - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN); - m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); - } - else - { - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN); - m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); - } - - if (boxFull) - { - m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlaneN); - m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlane); + // edge lighting only uses ambient light + float buf[4] = { 0.0f, 0.0f, 0.0f, 1.0f };; + + if (m_face_lighting) + for (int k = 0; k < 3; k++) + buf[k] = (v->m_specular + * (v->m_specular_color_refl + + (1 - v->m_specular_color_refl) * col(k))); + glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, buf); + + if (m_face_lighting) + for (int k = 0; k < 3; k++) + buf[k] = (v->m_diffuse * col(k)); + glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, buf); + + for (int k = 0; k < 3; k++) + buf[k] = (v->m_ambient * col(k)); + glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, buf); } } } - m_glfcns.glEnd (); - - set_linestyle ("-"); // Disable LineStipple + if (m_light_mode == FLAT && m_first) + glfcns.glNormal3dv (v->m_face_normal.data ()); + else if (m_light_mode == GOURAUD) + glfcns.glNormal3dv (v->m_vertex_normal.data ()); + + glfcns.glVertex3dv (v->m_coords.data ()); + + m_first = false; + } + + void combine (GLdouble xyz[3], void *data[4], GLfloat w[4], void **out_data) + { + vertex_data::vertex_data_rep *v[4]; + int vmax = 4; + + for (int i = 0; i < 4; i++) + { + v[i] = reinterpret_cast (data[i]); + + if (vmax == 4 && ! v[i]) + vmax = i; + } + + Matrix vv (1, 3, 0.0); + Matrix cc; + Matrix vnn (1, 3, 0.0); + Matrix fnn (1, 3, 0.0); + double aa = 0.0; + + vv(0) = xyz[0]; + vv(1) = xyz[1]; + vv(2) = xyz[2]; + + if (v[0]->m_color.numel ()) + { + cc.resize (1, 3, 0.0); + for (int ic = 0; ic < 3; ic++) + for (int iv = 0; iv < vmax; iv++) + cc(ic) += (w[iv] * v[iv]->m_color (ic)); + } + + if (v[0]->m_vertex_normal.numel () > 0) + { + for (int in = 0; in < 3; in++) + for (int iv = 0; iv < vmax; iv++) + vnn(in) += (w[iv] * v[iv]->m_vertex_normal (in)); + } + + if (v[0]->m_face_normal.numel () > 0) + { + for (int in = 0; in < 3; in++) + for (int iv = 0; iv < vmax; iv++) + fnn(in) += (w[iv] * v[iv]->m_face_normal (in)); + } + + for (int iv = 0; iv < vmax; iv++) + aa += (w[iv] * v[iv]->m_alpha); + + vertex_data new_v (vv, cc, vnn, fnn, aa, v[0]->m_ambient, v[0]->m_diffuse, + v[0]->m_specular, v[0]->m_specular_exp, + v[0]->m_specular_color_refl); + m_tmp_vdata.push_back (new_v); + + *out_data = new_v.get_rep (); + } + +private: + + // No copying! + + patch_tessellator (const patch_tessellator&) = delete; + + patch_tessellator& operator = (const patch_tessellator&) = delete; + + opengl_renderer *m_renderer; + int m_color_mode; + int m_light_mode; + bool m_face_lighting; + int m_index; + bool m_first; + std::list m_tmp_vdata; +}; #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 (); +class +opengl_renderer::patch_tessellator +{ + // Dummy class. +}; #endif - } - - void - opengl_renderer::draw_axes_x_grid (const axes::properties& props) - { + +opengl_renderer::opengl_renderer (opengl_functions& glfcns) + : m_glfcns (glfcns), m_xmin (), m_xmax (), m_ymin (), m_ymax (), + m_zmin (), m_zmax (), m_devpixratio (1.0), m_xform (), m_toolkit (), + m_xZ1 (), m_xZ2 (), m_marker_id (), m_filled_marker_id (), + m_camera_pos (), m_camera_dir (), m_view_vector (), + m_interpreter ("none"), m_txt_renderer (), m_current_light (0), + m_max_lights (0), m_selecting (false), m_printing (false) +{ + // This constructor will fail if we don't have OpenGL or if the data + // types we assumed in our public interface aren't compatible with the + // OpenGL types. + #if defined (HAVE_OPENGL) - gh_manager& gh_mgr = __get_gh_manager__ (); - - int xstate = props.get_xstate (); - - if (xstate != AXE_DEPTH_DIR - && (props.is_visible () - || (m_selecting && props.pickableparts_is ("all")))) - { - int zstate = props.get_zstate (); - bool x2Dtop = props.get_x2Dtop (); - bool layer2Dtop = props.get_layer2Dtop (); - bool xyzSym = props.get_xyzSym (); - bool nearhoriz = props.get_nearhoriz (); - double xticklen = props.get_xticklen (); - double xtickoffset = props.get_xtickoffset (); - double fy = props.get_fy (); - double fz = props.get_fz (); - double x_min = props.get_x_min (); - double x_max = props.get_x_max (); - double y_min = props.get_y_min (); - double y_max = props.get_y_max (); - double yPlane = props.get_yPlane (); - double yPlaneN = props.get_yPlaneN (); - double ypTick = props.get_ypTick (); - double ypTickN = props.get_ypTickN (); - double zPlane = props.get_zPlane (); - double zPlaneN = props.get_zPlaneN (); - double zpTick = props.get_zpTick (); - double zpTickN = props.get_zpTickN (); - - // X ticks and grid properties - Matrix xticks = m_xform.xscale (props.get_xtick ().matrix_value ()); - Matrix xmticks = m_xform.xscale (props.get_xminortickvalues ().matrix_value ()); - bool do_xminortick = props.is_xminortick () && ! xticks.isempty (); - string_vector xticklabels = props.get_xticklabel ().string_vector_value (); - int wmax = 0; - int hmax = 0; - bool tick_along_z = nearhoriz || math::isinf (fy); - double linewidth = props.get_linewidth (); - std::string gridstyle = props.get_gridlinestyle (); - std::string minorgridstyle = props.get_minorgridlinestyle (); - Matrix gridcolor = props.get_gridcolor_rgb (); - Matrix minorgridcolor = props.get_minorgridcolor_rgb (); - double gridalpha = props.get_gridalpha (); - double minorgridalpha = props.get_minorgridalpha (); - bool do_xgrid = (props.is_xgrid () && (gridstyle != "none")); - bool do_xminorgrid = (props.is_xminorgrid () - && (minorgridstyle != "none") - && ! xticks.isempty ()); - bool is_origin = props.xaxislocation_is ("origin") && props.get_is2D () - && ! props.yscale_is ("log"); - bool is_origin_low = is_origin && (y_min + y_max) < 0; - bool mirror = props.is_box () && xstate != AXE_ANY_DIR; - - // X grid - - // possibly use axis color for gridcolor & minorgridcolor - if (props.gridcolormode_is ("auto")) - if (props.xcolormode_is ("manual") && ! props.xcolor_is ("none")) - gridcolor = props.get_xcolor_rgb (); - - if (props.minorgridcolormode_is ("auto")) - if (props.xcolormode_is ("manual") && ! props.xcolor_is ("none")) - minorgridcolor = props.get_xcolor_rgb (); - - if (gridcolor.isempty ()) - do_xgrid = false; - - if (minorgridcolor.isempty ()) - do_xminorgrid = false; - - // set styles when drawing only minor grid - if (do_xminorgrid && ! do_xgrid) - { - gridstyle = minorgridstyle; - gridcolor = minorgridcolor; - gridalpha = minorgridalpha; - do_xgrid = true; - } - - // minor grid lines - if (do_xminorgrid) - render_grid (linewidth, - minorgridstyle, minorgridcolor, minorgridalpha, - xmticks, x_min, x_max, - yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, - 0, (zstate != AXE_DEPTH_DIR)); - - // grid lines - if (do_xgrid) - render_grid (linewidth, - gridstyle, gridcolor, gridalpha, - xticks, x_min, x_max, - yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, - 0, (zstate != AXE_DEPTH_DIR)); - - // Skip drawing axis, ticks, and ticklabels when color is "none" - if (props.xcolor_is ("none")) - return; - - set_color (props.get_xcolor_rgb ()); - - // axis line - double y_axis_pos = 0.; - if (is_origin) - { - y_axis_pos = math::max (math::min (0., y_max), y_min); - m_glfcns.glBegin (GL_LINES); - set_color (props.get_xcolor_rgb ()); - m_glfcns.glVertex3d (x_min, y_axis_pos, zpTick); - m_glfcns.glVertex3d (x_max, y_axis_pos, zpTick); - m_glfcns.glEnd (); - } - - // minor tick marks - if (do_xminortick) - { - if (tick_along_z) - render_tickmarks (xmticks, x_min, x_max, - is_origin ? y_axis_pos : ypTick, ypTick, - zpTick, zpTickN, 0., 0., - (is_origin_low ? -1. : 1.) * - math::signum (zpTick-zpTickN)*fz*xticklen/2, - 0, ! is_origin && mirror); - else - render_tickmarks (xmticks, x_min, x_max, - is_origin ? y_axis_pos : ypTick, ypTickN, - zpTick, zpTick, 0., - (is_origin_low ? -1. : 1.) * - math::signum (ypTick-ypTickN)*fy*xticklen/2, - 0., 0, ! is_origin && mirror); - } - - // tick marks - if (tick_along_z) - render_tickmarks (xticks, x_min, x_max, - is_origin ? y_axis_pos : ypTick, ypTick, - zpTick, zpTickN, 0., 0., - (is_origin_low ? -1. : 1.) * - math::signum (zpTick-zpTickN)*fz*xticklen, - 0, ! is_origin && mirror); - else - render_tickmarks (xticks, x_min, x_max, - is_origin ? y_axis_pos : ypTick, ypTickN, - zpTick, zpTick, 0., - (is_origin_low ? -1. : 1.) * - math::signum (ypTick-ypTickN)*fy*xticklen, - 0., 0, ! is_origin && mirror); - - // tick texts - if (xticklabels.numel () > 0) - { - int halign = (xstate == AXE_HORZ_DIR - ? 1 - : (xyzSym || is_origin_low ? 0 : 2)); - int valign = (xstate == AXE_VERT_DIR - ? 1 - : (x2Dtop || is_origin_low ? 0 : 2)); - - if (tick_along_z) - render_ticktexts (xticks, xticklabels, x_min, x_max, - is_origin ? y_axis_pos : ypTick, - zpTick + - (is_origin_low ? -1. : 1.) * - math::signum (zpTick-zpTickN)*fz*xtickoffset, - 0, halign, valign, wmax, hmax); - else - render_ticktexts (xticks, xticklabels, x_min, x_max, - (is_origin ? y_axis_pos : ypTick) + - (is_origin_low ? -1. : 1.) * - math::signum (ypTick-ypTickN)*fy*xtickoffset, - zpTick, 0, halign, valign, wmax, hmax); - } - - gh_mgr.get_object (props.get_xlabel ()).set ("visible", "on"); - } - else - gh_mgr.get_object (props.get_xlabel ()).set ("visible", "off"); + // Ensure that we can't request an image larger than OpenGL can handle. + // FIXME: should we check signed vs. unsigned? + + static bool ok = (sizeof (int) <= sizeof (GLsizei)); + + if (! ok) + error ("the size of GLsizei is smaller than the size of int"); #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 (); + err_disabled_feature ("opengl_renderer", "OpenGL"); + +#endif +} + +void +opengl_renderer::draw (const graphics_object& go, bool toplevel) +{ + if (! go.valid_object ()) + return; + + const base_properties& props = go.get_properties (); + + if (! m_toolkit) + m_toolkit = props.get_toolkit (); + + if (go.isa ("figure")) + draw_figure (dynamic_cast (props)); + else if (go.isa ("axes")) + draw_axes (dynamic_cast (props)); + else if (go.isa ("line")) + draw_line (dynamic_cast (props)); + else if (go.isa ("surface")) + draw_surface (dynamic_cast (props)); + else if (go.isa ("patch")) + draw_patch (dynamic_cast (props)); + else if (go.isa ("scatter")) + draw_scatter (dynamic_cast (props)); + else if (go.isa ("light")) + draw_light (dynamic_cast (props)); + else if (go.isa ("hggroup")) + draw_hggroup (dynamic_cast (props)); + else if (go.isa ("text")) + draw_text (dynamic_cast (props)); + else if (go.isa ("image")) + draw_image (dynamic_cast (props)); + else if (go.isa ("uimenu") || go.isa ("uicontrol") + || go.isa ("uicontextmenu") || go.isa ("uitoolbar") + || go.isa ("uipushtool") || go.isa ("uitoggletool") + || go.isa ("uitable")) + ; // SKIP + else if (go.isa ("uipanel")) + { + if (toplevel) + draw_uipanel (dynamic_cast (props), go); + } + else if (go.isa ("uibuttongroup")) + { + if (toplevel) + draw_uibuttongroup (dynamic_cast (props), go); + } + else + { + warning ("opengl_renderer: cannot render object of type '%s'", + props.graphics_object_name ().c_str ()); + } + +#if defined (HAVE_OPENGL) + + GLenum gl_error = m_glfcns.glGetError (); + if (gl_error) + warning ("opengl_renderer: Error '%s' (%d) occurred drawing '%s' object", + gluErrorString (gl_error), gl_error, + props.graphics_object_name ().c_str ()); + +#endif +} + +void +opengl_renderer::draw_figure (const figure::properties& props) +{ + m_printing = props.is___printing__ (); + + // Initialize OpenGL context + init_gl_context (props.is_graphicssmoothing (), props.get_color_rgb ()); + +#if defined (HAVE_OPENGL) + + props.set___gl_extensions__ (get_string (GL_EXTENSIONS)); + props.set___gl_renderer__ (get_string (GL_RENDERER)); + props.set___gl_vendor__ (get_string (GL_VENDOR)); + props.set___gl_version__ (get_string (GL_VERSION)); + +#endif + + // Draw children + + draw (props.get_all_children (), false); +} + +void +opengl_renderer::draw_uipanel (const uipanel::properties& props, + const graphics_object& go) +{ + graphics_object fig = go.get_ancestor ("figure"); + const figure::properties& figProps + = dynamic_cast (fig.get_properties ()); + + // Initialize OpenGL context + + init_gl_context (figProps.is_graphicssmoothing (), + props.get_backgroundcolor_rgb ()); + + // Draw children + + draw (props.get_all_children (), false); +} + +void +opengl_renderer::draw_uibuttongroup (const uibuttongroup::properties& props, + const graphics_object& go) +{ + graphics_object fig = go.get_ancestor ("figure"); + const figure::properties& figProps + = dynamic_cast (fig.get_properties ()); + + // Initialize OpenGL context + + init_gl_context (figProps.is_graphicssmoothing (), + props.get_backgroundcolor_rgb ()); + + // Draw children + + draw (props.get_all_children (), false); +} + +void +opengl_renderer::init_gl_context (bool enhanced, const Matrix& c) +{ +#if defined (HAVE_OPENGL) + + // Initialize OpenGL context + + m_glfcns.glEnable (GL_DEPTH_TEST); + m_glfcns.glDepthFunc (GL_LEQUAL); + m_glfcns.glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + m_glfcns.glAlphaFunc (GL_GREATER, 0.0f); + m_glfcns.glEnable (GL_NORMALIZE); + m_glfcns.glEnable (GL_BLEND); + + if (enhanced) + { + m_glfcns.glEnable (GL_MULTISAMPLE); + bool has_multisample = false; + if (! m_glfcns.glGetError ()) + { + GLint iMultiSample, iNumSamples; + m_glfcns.glGetIntegerv (GL_SAMPLE_BUFFERS, &iMultiSample); + m_glfcns.glGetIntegerv (GL_SAMPLES, &iNumSamples); + if (iMultiSample == GL_TRUE && iNumSamples > 0) + has_multisample = true; + } + + if (! has_multisample) + { + // MultiSample not implemented. Use old-style anti-aliasing + m_glfcns.glDisable (GL_MULTISAMPLE); + // Disabling GL_MULTISAMPLE will raise a gl error if it is not + // implemented. Thus, call glGetError to reset the error state. + m_glfcns.glGetError (); + + m_glfcns.glEnable (GL_LINE_SMOOTH); + m_glfcns.glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + } + } + else + { + m_glfcns.glDisable (GL_LINE_SMOOTH); + } + + // Clear background + + if (c.numel () >= 3) + { + m_glfcns.glClearColor (c(0), c(1), c(2), 1); + m_glfcns.glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + } + + GLenum gl_error = m_glfcns.glGetError (); + if (gl_error) + warning ("opengl_renderer: Error '%s' (%d) occurred in init_gl_context", + gluErrorString (gl_error), gl_error); + +#else + + octave_unused_parameter (enhanced); + octave_unused_parameter (c); + + // 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_axes_y_grid (const axes::properties& props) - { +} + +void +opengl_renderer::render_grid (const double linewidth, + const std::string& gridstyle, + const Matrix& gridcolor, const double gridalpha, + const Matrix& ticks, double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + int xyz, bool is_3D) +{ #if defined (HAVE_OPENGL) - gh_manager& gh_mgr = __get_gh_manager__ (); - - int ystate = props.get_ystate (); - - if (ystate != AXE_DEPTH_DIR && props.is_visible () - && (props.is_visible () - || (m_selecting && props.pickableparts_is ("all")))) - { - int zstate = props.get_zstate (); - bool y2Dright = props.get_y2Dright (); - bool layer2Dtop = props.get_layer2Dtop (); - bool xyzSym = props.get_xyzSym (); - bool nearhoriz = props.get_nearhoriz (); - double yticklen = props.get_yticklen (); - double ytickoffset = props.get_ytickoffset (); - double fx = props.get_fx (); - double fz = props.get_fz (); - double xPlane = props.get_xPlane (); - double xPlaneN = props.get_xPlaneN (); - double xpTick = props.get_xpTick (); - double xpTickN = props.get_xpTickN (); - double y_min = props.get_y_min (); - double y_max = props.get_y_max (); - double x_min = props.get_x_min (); - double x_max = props.get_x_max (); - double zPlane = props.get_zPlane (); - double zPlaneN = props.get_zPlaneN (); - double zpTick = props.get_zpTick (); - double zpTickN = props.get_zpTickN (); - - // Y ticks and grid properties - Matrix yticks = m_xform.yscale (props.get_ytick ().matrix_value ()); - Matrix ymticks = m_xform.yscale (props.get_yminortickvalues ().matrix_value ()); - bool do_yminortick = props.is_yminortick () && ! yticks.isempty (); - string_vector yticklabels = props.get_yticklabel ().string_vector_value (); - int wmax = 0; - int hmax = 0; - bool tick_along_z = nearhoriz || math::isinf (fx); - double linewidth = props.get_linewidth (); - std::string gridstyle = props.get_gridlinestyle (); - std::string minorgridstyle = props.get_minorgridlinestyle (); - Matrix gridcolor = props.get_gridcolor_rgb (); - Matrix minorgridcolor = props.get_minorgridcolor_rgb (); - double gridalpha = props.get_gridalpha (); - double minorgridalpha = props.get_minorgridalpha (); - bool do_ygrid = (props.is_ygrid () && (gridstyle != "none")); - bool do_yminorgrid = (props.is_yminorgrid () - && (minorgridstyle != "none") - && ! yticks.isempty ()); - bool is_origin = props.yaxislocation_is ("origin") && props.get_is2D () - && ! props.xscale_is ("log"); - bool is_origin_low = is_origin && (x_min + x_max) < 0; - bool mirror = props.is_box () && ystate != AXE_ANY_DIR - && (! props.has_property ("__plotyy_axes__")); - - // Y grid - - // possibly use axis color for gridcolor & minorgridcolor - if (props.gridcolormode_is ("auto")) - if (props.ycolormode_is ("manual") && ! props.ycolor_is ("none")) - gridcolor = props.get_ycolor_rgb (); - - if (props.minorgridcolormode_is ("auto")) - if (props.ycolormode_is ("manual") && ! props.ycolor_is ("none")) - minorgridcolor = props.get_ycolor_rgb (); - - if (gridcolor.isempty ()) - do_ygrid = false; - - if (minorgridcolor.isempty ()) - do_yminorgrid = false; - - // set styles when drawing only minor grid - if (do_yminorgrid && ! do_ygrid) - { - gridstyle = minorgridstyle; - gridcolor = minorgridcolor; - gridalpha = minorgridalpha; - do_ygrid = true; - } - - // minor grid lines - if (do_yminorgrid) - render_grid (linewidth, - minorgridstyle, minorgridcolor, minorgridalpha, - ymticks, y_min, y_max, - xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, - 1, (zstate != AXE_DEPTH_DIR)); - - // grid lines - if (do_ygrid) - render_grid (linewidth, - gridstyle, gridcolor, gridalpha, - yticks, y_min, y_max, - xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, - 1, (zstate != AXE_DEPTH_DIR)); - - // Skip drawing axis, ticks, and ticklabels when color is "none" - if (props.ycolor_is ("none")) - return; - - set_color (props.get_ycolor_rgb ()); - - // axis line - double x_axis_pos = 0.; - if (is_origin) - { - x_axis_pos = math::max (math::min (0., x_max), x_min); - m_glfcns.glBegin (GL_LINES); - set_color (props.get_ycolor_rgb ()); - m_glfcns.glVertex3d (x_axis_pos, y_min, zpTick); - m_glfcns.glVertex3d (x_axis_pos, y_max, zpTick); - m_glfcns.glEnd (); - } - - // minor tick marks - if (do_yminortick) - { - if (tick_along_z) - render_tickmarks (ymticks, y_min, y_max, - is_origin ? x_axis_pos : xpTick, xpTick, - zpTick, zpTickN, 0., 0., - (is_origin_low ? -1. : 1.) * - math::signum (zpTick-zpTickN)*fz*yticklen/2, - 1, ! is_origin && mirror); - else - render_tickmarks (ymticks, y_min, y_max, - is_origin ? x_axis_pos : xpTick, xpTickN, - zpTick, zpTick, - (is_origin_low ? -1. : 1.) * - math::signum (xpTick-xpTickN)*fx*yticklen/2, - 0., 0., 1, ! is_origin && mirror); - } - - // tick marks - if (tick_along_z) - render_tickmarks (yticks, y_min, y_max, - is_origin ? x_axis_pos : xpTick, xpTick, - zpTick, zpTickN, 0., 0., - (is_origin_low ? -1. : 1.) * - math::signum (zpTick-zpTickN)*fz*yticklen, - 1, ! is_origin && mirror); - else - render_tickmarks (yticks, y_min, y_max, - is_origin ? x_axis_pos : xpTick, xpTickN, - zpTick, zpTick, - (is_origin_low ? -1. : 1.) * - math::signum (xPlaneN-xPlane)*fx*yticklen, - 0., 0., 1, ! is_origin && mirror); - - // tick texts - if (yticklabels.numel () > 0) - { - int halign = (ystate == AXE_HORZ_DIR - ? 1 - : (! xyzSym || y2Dright || is_origin_low ? 0 : 2)); - int valign = (ystate == AXE_VERT_DIR - ? 1 - : (is_origin_low ? 0 : 2)); - - if (tick_along_z) - render_ticktexts (yticks, yticklabels, y_min, y_max, - is_origin ? x_axis_pos : xpTick, - zpTick + - (is_origin_low ? -1. : 1.) * - math::signum (zpTick-zpTickN)*fz*ytickoffset, - 1, halign, valign, wmax, hmax); - else - render_ticktexts (yticks, yticklabels, y_min, y_max, - (is_origin ? x_axis_pos : xpTick) + - (is_origin_low ? -1. : 1.) * - math::signum (xpTick-xpTickN)*fx*ytickoffset, - zpTick, 1, halign, valign, wmax, hmax); - } - - gh_mgr.get_object (props.get_ylabel ()).set ("visible", "on"); - } - else - gh_mgr.get_object (props.get_ylabel ()).set ("visible", "off"); + m_glfcns.glColor4d (gridcolor(0), gridcolor(1), gridcolor(2), gridalpha); + set_linestyle (gridstyle, true, linewidth); + m_glfcns.glBegin (GL_LINES); + for (int i = 0; i < ticks.numel (); i++) + { + double val = ticks(i); + if (lim1 <= val && val <= lim2) + { + if (xyz == X_AXIS) + { + m_glfcns.glVertex3d (val, p1N, p2); + m_glfcns.glVertex3d (val, p1, p2); + if (is_3D) + { + m_glfcns.glVertex3d (val, p1, p2N); + m_glfcns.glVertex3d (val, p1, p2); + } + } + else if (xyz == Y_AXIS) + { + m_glfcns.glVertex3d (p1N, val, p2); + m_glfcns.glVertex3d (p1, val, p2); + if (is_3D) + { + m_glfcns.glVertex3d (p1, val, p2N); + m_glfcns.glVertex3d (p1, val, p2); + } + } + else if (xyz == Z_AXIS) + { + m_glfcns.glVertex3d (p1N, p2, val); + m_glfcns.glVertex3d (p1, p2, val); + m_glfcns.glVertex3d (p1, p2N, val); + m_glfcns.glVertex3d (p1, p2, val); + } + } + } + m_glfcns.glEnd (); + set_linestyle ("-"); // Disable LineStipple + double black[3] = {0, 0, 0}; + m_glfcns.glColor3dv (black); #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 (); + octave_unused_parameter (linewidth); + octave_unused_parameter (gridstyle); + octave_unused_parameter (gridcolor); + octave_unused_parameter (gridalpha); + octave_unused_parameter (ticks); + octave_unused_parameter (lim1); + octave_unused_parameter (lim2); + octave_unused_parameter (p1); + octave_unused_parameter (p1N); + octave_unused_parameter (p2); + octave_unused_parameter (p2N); + octave_unused_parameter (xyz); + octave_unused_parameter (is_3D); + + // 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::render_tickmarks (const Matrix& ticks, + double lim1, double lim2, + double p1, double p1N, + double p2, double p2N, + double dx, double dy, double dz, + int xyz, bool mirror) +{ +#if defined (HAVE_OPENGL) + + m_glfcns.glBegin (GL_LINES); + + for (int i = 0; i < ticks.numel (); i++) + { + double val = ticks(i); + + if (lim1 <= val && val <= lim2) + { + if (xyz == X_AXIS) + { + m_glfcns.glVertex3d (val, p1, p2); + m_glfcns.glVertex3d (val, p1+dy, p2+dz); + if (mirror) + { + m_glfcns.glVertex3d (val, p1N, p2N); + m_glfcns.glVertex3d (val, p1N-dy, p2N-dz); + } + } + else if (xyz == Y_AXIS) + { + m_glfcns.glVertex3d (p1, val, p2); + m_glfcns.glVertex3d (p1+dx, val, p2+dz); + if (mirror) + { + m_glfcns.glVertex3d (p1N, val, p2N); + m_glfcns.glVertex3d (p1N-dx, val, p2N-dz); + } + } + else if (xyz == Z_AXIS) + { + m_glfcns.glVertex3d (p1, p2, val); + m_glfcns.glVertex3d (p1+dx, p2+dy, val); + if (mirror) + { + m_glfcns.glVertex3d (p1N, p2N, val); + m_glfcns.glVertex3d (p1N-dx, p2N-dy, val); + } + } + } + } + + m_glfcns.glEnd (); + +#else + + octave_unused_parameter (ticks); + octave_unused_parameter (lim1); + octave_unused_parameter (lim2); + octave_unused_parameter (p1); + octave_unused_parameter (p1N); + octave_unused_parameter (p2); + octave_unused_parameter (p2N); + octave_unused_parameter (dx); + octave_unused_parameter (dy); + octave_unused_parameter (dz); + octave_unused_parameter (xyz); + octave_unused_parameter (mirror); + + // 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::render_ticktexts (const Matrix& ticks, + const string_vector& ticklabels, + double lim1, double lim2, + double p1, double p2, + int xyz, int ha, int va, + int& wmax, int& hmax) +{ +#if defined (HAVE_OPENGL) + + int nticks = ticks.numel (); + int nlabels = ticklabels.numel (); + + if (nlabels == 0) + return; + + for (int i = 0; i < nticks; i++) + { + double val = ticks(i); + + if (lim1 <= val && val <= lim2) + { + Matrix b; + + std::string label (ticklabels(i % nlabels)); + label.erase (0, label.find_first_not_of (' ')); + label = label.substr (0, label.find_last_not_of (' ')+1); + + // FIXME: As tick text is transparent, shouldn't it be + // drawn after axes object, for correct rendering? + if (xyz == X_AXIS) + { + b = render_text (label, val, p1, p2, ha, va); + } + else if (xyz == Y_AXIS) + { + b = render_text (label, p1, val, p2, ha, va); + } + else if (xyz == Z_AXIS) + { + b = render_text (label, p1, p2, val, ha, va); + } + + wmax = std::max (wmax, static_cast (b(2))); + hmax = std::max (hmax, static_cast (b(3))); + } + } + +#else + + octave_unused_parameter (ticks); + octave_unused_parameter (ticklabels); + octave_unused_parameter (lim1); + octave_unused_parameter (lim2); + octave_unused_parameter (p1); + octave_unused_parameter (p2); + octave_unused_parameter (xyz); + octave_unused_parameter (ha); + octave_unused_parameter (va); + octave_unused_parameter (wmax); + octave_unused_parameter (hmax); + + // 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_zoom_rect (int x1, int y1, int x2, int y2) +{ +#if defined (HAVE_OPENGL) + + m_glfcns.glVertex2d (x1, y1); + m_glfcns.glVertex2d (x2, y1); + m_glfcns.glVertex2d (x2, y2); + m_glfcns.glVertex2d (x1, y2); + m_glfcns.glVertex2d (x1, y1); + +#else + + octave_unused_parameter (x1); + octave_unused_parameter (x2); + octave_unused_parameter (y1); + octave_unused_parameter (y2); + + // 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_axes_z_grid (const axes::properties& props) - { - gh_manager& gh_mgr = __get_gh_manager__ (); - - int zstate = props.get_zstate (); - - if (zstate != AXE_DEPTH_DIR && props.is_visible () - && (props.is_visible () - || (m_selecting && props.pickableparts_is ("all")))) - { - bool xySym = props.get_xySym (); - bool zSign = props.get_zSign (); - double zticklen = props.get_zticklen (); - double ztickoffset = props.get_ztickoffset (); - double fx = props.get_fx (); - double fy = props.get_fy (); - double xPlane = props.get_xPlane (); - double xPlaneN = props.get_xPlaneN (); - double yPlane = props.get_yPlane (); - double yPlaneN = props.get_yPlaneN (); - double z_min = props.get_z_min (); - double z_max = props.get_z_max (); - - // Z ticks and grid properties - Matrix zticks = m_xform.zscale (props.get_ztick ().matrix_value ()); - Matrix zmticks = m_xform.zscale (props.get_zminortickvalues ().matrix_value ()); - bool do_zminortick = props.is_zminortick () && ! zticks.isempty (); - string_vector zticklabels = props.get_zticklabel ().string_vector_value (); - int wmax = 0; - int hmax = 0; - double linewidth = props.get_linewidth (); - std::string gridstyle = props.get_gridlinestyle (); - std::string minorgridstyle = props.get_minorgridlinestyle (); - Matrix gridcolor = props.get_gridcolor_rgb (); - Matrix minorgridcolor = props.get_minorgridcolor_rgb (); - double gridalpha = props.get_gridalpha (); - double minorgridalpha = props.get_minorgridalpha (); - bool do_zgrid = (props.is_zgrid () && (gridstyle != "none")); - bool do_zminorgrid = (props.is_zminorgrid () - && (minorgridstyle != "none") - && ! zticks.isempty ()); - bool mirror = props.is_box () && zstate != AXE_ANY_DIR; - - // Z grid - - // possibly use axis color for gridcolor & minorgridcolor - if (props.gridcolormode_is ("auto")) - if (props.zcolormode_is ("manual") && ! props.zcolor_is ("none")) - gridcolor = props.get_zcolor_rgb (); - - if (props.minorgridcolormode_is ("auto")) - if (props.zcolormode_is ("manual") && ! props.zcolor_is ("none")) - minorgridcolor = props.get_zcolor_rgb (); - - if (gridcolor.isempty ()) - do_zgrid = false; - - if (minorgridcolor.isempty ()) - do_zminorgrid = false; - - // set styles when drawing only minor grid - if (do_zminorgrid && ! do_zgrid) - { - gridstyle = minorgridstyle; - gridcolor = minorgridcolor; - gridalpha = minorgridalpha; - do_zgrid = true; - } - - // minor grid lines - if (do_zminorgrid) - render_grid (linewidth, - minorgridstyle, minorgridcolor, minorgridalpha, - zmticks, z_min, z_max, - xPlane, xPlaneN, yPlane, yPlaneN, 2, true); - - // grid lines - if (do_zgrid) - render_grid (linewidth, - gridstyle, gridcolor, gridalpha, - zticks, z_min, z_max, - xPlane, xPlaneN, yPlane, yPlaneN, 2, true); - - // Skip drawing axis, ticks, and ticklabels when color is "none" - if (props.zcolor_is ("none")) - return; - - set_color (props.get_zcolor_rgb ()); - - // minor tick marks - if (do_zminortick) - { - if (xySym) - { - if (math::isinf (fy)) - render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane, - yPlane, yPlane, - math::signum (xPlaneN-xPlane)*fx*zticklen/2, - 0., 0., 2, mirror); - else - render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN, - yPlane, yPlane, 0., - math::signum (yPlane-yPlaneN)*fy*zticklen/2, - 0., 2, false); - } - else - { - if (math::isinf (fx)) - render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane, - yPlaneN, yPlane, 0., - math::signum (yPlaneN-yPlane)*fy*zticklen/2, - 0., 2, mirror); - else - render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane, - yPlaneN, yPlaneN, - math::signum (xPlane-xPlaneN)*fx*zticklen/2, - 0., 0., 2, false); - } - } - - // tick marks - if (xySym) - { - if (math::isinf (fy)) - render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane, - yPlane, yPlane, - math::signum (xPlaneN-xPlane)*fx*zticklen, - 0., 0., 2, mirror); - else - render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN, - yPlane, yPlane, 0., - math::signum (yPlane-yPlaneN)*fy*zticklen, - 0., 2, false); - } - else - { - if (math::isinf (fx)) - render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane, - yPlaneN, yPlane, 0., - math::signum (yPlaneN-yPlane)*fy*zticklen, - 0., 2, mirror); - else - render_tickmarks (zticks, z_min, z_max, xPlane, xPlane, - yPlaneN, yPlane, - math::signum (xPlane-xPlaneN)*fx*zticklen, - 0., 0., 2, false); - } - - // tick texts - if (zticklabels.numel () > 0) - { - int halign = 2; - int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2)); - - if (xySym) - { - if (math::isinf (fy)) - render_ticktexts (zticks, zticklabels, z_min, z_max, - xPlaneN + math::signum (xPlaneN-xPlane)*fx*ztickoffset, - yPlane, 2, halign, valign, wmax, hmax); - else - render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN, - yPlane + math::signum (yPlane-yPlaneN)*fy*ztickoffset, - 2, halign, valign, wmax, hmax); - } - else - { - if (math::isinf (fx)) - render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane, - yPlaneN + math::signum (yPlaneN-yPlane)*fy*ztickoffset, - 2, halign, valign, wmax, hmax); - else - render_ticktexts (zticks, zticklabels, z_min, z_max, - xPlane + math::signum (xPlane-xPlaneN)*fx*ztickoffset, - yPlaneN, 2, halign, valign, wmax, hmax); - } - } - - gh_mgr.get_object (props.get_zlabel ()).set ("visible", "on"); - } - else - gh_mgr.get_object (props.get_zlabel ()).set ("visible", "off"); - } - - void - opengl_renderer::draw_axes_grids (const axes::properties& props) - { +} + +void +opengl_renderer::draw_zoom_box (int width, int height, + int x1, int y1, int x2, int y2, + const Matrix& overlaycolor, + double overlayalpha, + const Matrix& bordercolor, + double borderalpha, double borderwidth) +{ #if defined (HAVE_OPENGL) - // Disable line smoothing for axes - GLboolean antialias; - - m_glfcns.glGetBooleanv (GL_LINE_SMOOTH, &antialias); - - if (antialias == GL_TRUE) - m_glfcns.glDisable (GL_LINE_SMOOTH); - - set_linecap ("butt"); - set_linewidth (props.get_linewidth ()); - set_font (props); - set_interpreter (props.get_ticklabelinterpreter ()); - - draw_axes_x_grid (props); - draw_axes_y_grid (props); - draw_axes_z_grid (props); - - if (antialias == GL_TRUE) - m_glfcns.glEnable (GL_LINE_SMOOTH); + + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glPushMatrix (); + m_glfcns.glLoadIdentity (); + + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glPushMatrix (); + m_glfcns.glLoadIdentity (); + m_glfcns.glOrtho (0, width, height, 0, 1, -1); + + m_glfcns.glPushAttrib (GL_DEPTH_BUFFER_BIT | GL_CURRENT_BIT); + m_glfcns.glDisable (GL_DEPTH_TEST); + + m_glfcns.glBegin (GL_POLYGON); + m_glfcns.glColor4f (overlaycolor(0), overlaycolor(1), overlaycolor(2), + overlayalpha); + draw_zoom_rect (x1, y1, x2, y2); + m_glfcns.glEnd (); + + m_glfcns.glLineWidth (borderwidth); + m_glfcns.glBegin (GL_LINE_STRIP); + m_glfcns.glColor4f (bordercolor(0), bordercolor(1), bordercolor(2), + borderalpha); + draw_zoom_rect (x1, y1, x2, y2); + m_glfcns.glEnd (); + + m_glfcns.glPopAttrib (); + + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glPopMatrix (); + + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glPopMatrix (); + #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 (); + octave_unused_parameter (width); + octave_unused_parameter (height); + octave_unused_parameter (x1); + octave_unused_parameter (x2); + octave_unused_parameter (y1); + octave_unused_parameter (y2); + octave_unused_parameter (overlaycolor); + octave_unused_parameter (overlayalpha); + octave_unused_parameter (bordercolor); + octave_unused_parameter (borderalpha); + octave_unused_parameter (borderwidth); + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); + +#endif +} + +uint8NDArray +opengl_renderer::get_pixels (int width, int height) +{ +#if defined (HAVE_OPENGL) + + m_glfcns.glPixelStorei (GL_PACK_ALIGNMENT, 1); + uint8NDArray pix(dim_vector (3, width, height), 0); + + m_glfcns.glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, + pix.fortran_vec ()); + + // Permute and flip data + Array perm (dim_vector (3, 1)); + perm(0) = 2; + perm(1) = 1; + perm(2) = 0; + + Array idx (dim_vector (3, 1)); + idx(0) = idx_vector::make_range (height - 1, -1, height); + idx(1) = idx_vector::colon; + idx(2) = idx_vector::colon; + + return pix.permute (perm).index (idx); + +#else + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + octave_unused_parameter (width); + octave_unused_parameter (height); + + panic_impossible (); #endif - } - - void - opengl_renderer::draw_all_lights (const base_properties& props, - std::list& obj_list) - { +} + +void +opengl_renderer::finish (void) +{ +#if defined (HAVE_OPENGL) + + m_glfcns.glFinish (); + +#else + + // 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::setup_opengl_transformation (const axes::properties& props) +{ #if defined (HAVE_OPENGL) - gh_manager& gh_mgr = __get_gh_manager__ (); - - Matrix children = props.get_all_children (); - - for (octave_idx_type i = children.numel () - 1; i >= 0; i--) - { - graphics_object go = gh_mgr.get_object (children(i)); - - base_properties p = go.get_properties (); - - if (p.is_visible () - || (m_selecting && p.pickableparts_is ("all"))) - { - if (go.isa ("light") && ! m_selecting) - { - if (m_current_light-GL_LIGHT0 < m_max_lights) - { - set_clipping (p.is_clipping ()); - draw (go); - m_current_light++; - } - } - else if (go.isa ("hggroup") - && ! (m_selecting && p.pickableparts_is ("none"))) - draw_all_lights (go.get_properties (), obj_list); - else if (! (m_selecting && p.pickableparts_is ("none"))) - obj_list.push_back (go); - } - } + + // setup OpenGL transformation + + Matrix x_zlim = props.get_transform_zlim (); + + // Expand the distance between the clipping planes symmetrically by + // an arbitrary factor (see bug #54551). + const double expansion_fac = 100.0; + // Also make sure that the distance between the clipping planes + // differs in single precision (see bug #58956). This factor is also + // arbitrary. Different values (>2) might also work. + const double single_prec_fac = 10.0; + + double avgZ = x_zlim(0) / 2.0 + x_zlim(1) / 2.0; + double span + = std::max (expansion_fac * (x_zlim(1)-x_zlim(0)), + single_prec_fac * std::abs (avgZ) + * std::numeric_limits::epsilon ()); + m_xZ1 = avgZ - span; + m_xZ2 = avgZ + span; + + Matrix x_mat1 = props.get_opengl_matrix_1 (); + Matrix x_mat2 = props.get_opengl_matrix_2 (); + + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glLoadIdentity (); + m_glfcns.glScaled (1, 1, -1); + m_glfcns.glMultMatrixd (x_mat1.data ()); + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glLoadIdentity (); + + Matrix vp = get_viewport_scaled (); + m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2); + m_glfcns.glMultMatrixd (x_mat2.data ()); + m_glfcns.glMatrixMode (GL_MODELVIEW); + + m_glfcns.glClear (GL_DEPTH_BUFFER_BIT); + + // store axes transformation data + + m_xform = props.get_transform (); + #else - octave_unused_parameter (props); - octave_unused_parameter (obj_list); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + 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_axes_planes (const axes::properties& props) +{ +#if defined (HAVE_OPENGL) + + Matrix axe_color = props.get_color_rgb (); + if (axe_color.isempty () || ! props.is_visible ()) + return; + + double xPlane = props.get_xPlane (); + double yPlane = props.get_yPlane (); + double zPlane = props.get_zPlane (); + double xPlaneN = props.get_xPlaneN (); + double yPlaneN = props.get_yPlaneN (); + double zPlaneN = props.get_zPlaneN (); + bool is2D = props.get_is2D (); + + // Axes planes + set_color (axe_color); + set_polygon_offset (true, 9.0); + + m_glfcns.glBegin (GL_QUADS); + + if (! is2D) + { + // X plane + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlane, zPlane); + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); + + // Y plane + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlane, zPlane); + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); + } + + // Z plane + m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlane); + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); + m_glfcns.glVertex3d (xPlane, yPlane, zPlane); + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); + + m_glfcns.glEnd (); + + set_polygon_offset (false); + +#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_axes_children (const axes::properties& props) - { +} + +void +opengl_renderer::draw_axes_boxes (const axes::properties& props) +{ #if defined (HAVE_OPENGL) - // list for non-light child objects - std::list obj_list; - std::list::iterator it; - - // 1st pass: draw light objects - - // FIXME: max_lights only needs to be set once. - // It would be better if this could be in the constructor for gl_renderer - // but this seems to lead to calls of OpenGL functions before the context - // is actually initialized. See bug #48669. - // Check actual maximum number of lights possible - init_maxlights (); - - // Start with the last element of the array of child objects to - // display them in the order they were added to the array. - - if (props.get_num_lights () > m_max_lights) - warning_with_id ("Octave:max-lights-exceeded", - "light: Maximum number of lights (%d) in these axes is " - "exceeded.", m_max_lights); - - m_current_light = GL_LIGHT0; - draw_all_lights (props, obj_list); - - // disable other OpenGL lights - for (unsigned int i = props.get_num_lights (); i < m_max_lights; i++) - m_glfcns.glDisable (GL_LIGHT0 + i); - - // save camera position and set ambient light color before drawing - // other objects - m_view_vector = props.get_cameraposition ().matrix_value (); - - float cb[4] = { 1.0, 1.0, 1.0, 1.0 }; - ColumnVector ambient_color = props.get_ambientlightcolor_rgb (); - for (int i = 0; i < 3; i++) - cb[i] = ambient_color(i); - m_glfcns.glLightfv (GL_LIGHT0, GL_AMBIENT, cb); - - // 2nd pass: draw other objects (with units set to "data") - - it = obj_list.begin (); - while (it != obj_list.end ()) - { - graphics_object go = (*it); - - // FIXME: check whether object has "units" property and it is set - // to "data" - if (! go.isa ("text") || go.get ("units").string_value () == "data") - { - set_clipping (go.get_properties ().is_clipping ()); - draw (go); - - it = obj_list.erase (it); - } - else - it++; - } - - // 3rd pass: draw remaining objects - - m_glfcns.glDisable (GL_DEPTH_TEST); - - for (it = obj_list.begin (); it != obj_list.end (); it++) - { - graphics_object go = (*it); - - set_clipping (go.get_properties ().is_clipping ()); - draw (go); - } - - set_clipping (false); - - // FIXME: finalize rendering (transparency processing) - // FIXME: draw zoom box, if needed - -#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_axes (const axes::properties& props) - { -#if defined (HAVE_OPENGL) - - // Legends are not drawn when "visible" is "off". - if (! props.is_visible () && props.get_tag () == "legend") - return; - - // Don't draw the axes and its children if we are in selection and - // pickable parts is "none". - if (m_selecting && props.pickableparts_is ("none")) - return; - - static double floatmax = std::numeric_limits::max (); - - double x_min = props.get_x_min (); - double x_max = props.get_x_max (); - double y_min = props.get_y_min (); - double y_max = props.get_y_max (); - double z_min = props.get_z_min (); - double z_max = props.get_z_max (); - - if (x_max > floatmax || y_max > floatmax || z_max > floatmax - || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax) - { - warning ("opengl_renderer: data values greater than float capacity. (1) Scale data, or (2) Use gnuplot"); - return; - } - - setup_opengl_transformation (props); - - // For 2D axes with only 2D primitives, draw from back to front without - // depth sorting - bool is2D = props.get_is2D (true); - if (is2D) - m_glfcns.glDisable (GL_DEPTH_TEST); - else - m_glfcns.glEnable (GL_DEPTH_TEST); - - draw_axes_planes (props); - - if (! is2D || props.layer_is ("bottom")) - { - draw_axes_grids (props); - if (props.get_tag () != "legend" || props.get_box () != "off") - draw_axes_boxes (props); - } - - set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max); - - draw_axes_children (props); - - if (is2D && props.layer_is ("top")) - { - draw_axes_grids (props); - if (props.get_tag () != "legend" || props.get_box () != "off") - draw_axes_boxes (props); - } + + if (! props.is_visible ()) + return; + + bool xySym = props.get_xySym (); + bool layer2Dtop = props.get_layer2Dtop (); + bool is2D = props.get_is2D (); + bool isXOrigin = props.xaxislocation_is ("origin") + && ! props.yscale_is ("log"); + bool isYOrigin = props.yaxislocation_is ("origin") + && ! props.xscale_is ("log"); + bool boxFull = (props.get_boxstyle () == "full"); + double linewidth = props.get_linewidth (); + double xPlane = props.get_xPlane (); + double yPlane = props.get_yPlane (); + double zPlane = props.get_zPlane (); + double xPlaneN = props.get_xPlaneN (); + double yPlaneN = props.get_yPlaneN (); + double zPlaneN = props.get_zPlaneN (); + double xpTick = props.get_xpTick (); + double ypTick = props.get_ypTick (); + double zpTick = props.get_zpTick (); + double xpTickN = props.get_xpTickN (); + double ypTickN = props.get_ypTickN (); + double zpTickN = props.get_zpTickN (); + + bool plotyy = (props.has_property ("__plotyy_axes__")); + + // Axes box + + set_linecap ("square"); + set_linestyle ("-", true, linewidth); + + m_glfcns.glBegin (GL_LINES); + + if (layer2Dtop) + std::swap (zpTick, zpTickN); + + // X box + Matrix color = props.get_xcolor_rgb (); + + if (! color.isempty ()) + { + set_color (color); + + if (! isXOrigin || props.is_box() || ! is2D) + { + m_glfcns.glVertex3d (xPlaneN, ypTick, zpTick); + m_glfcns.glVertex3d (xPlane, ypTick, zpTick); + } + + if (props.is_box ()) + { + m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTick); + m_glfcns.glVertex3d (xPlane, ypTickN, zpTick); + if (! is2D) + { + m_glfcns.glVertex3d (xPlaneN, ypTickN, zpTickN); + m_glfcns.glVertex3d (xPlane, ypTickN, zpTickN); + if (boxFull) + { + m_glfcns.glVertex3d (xPlaneN, ypTick, zpTickN); + m_glfcns.glVertex3d (xPlane, ypTick, zpTickN); + } + } + } + } + + // Y box + color = props.get_ycolor_rgb (); + + if (! color.isempty ()) + { + set_color (color); + if (! isYOrigin || props.is_box() || ! is2D) + { + m_glfcns.glVertex3d (xpTick, yPlaneN, zpTick); + m_glfcns.glVertex3d (xpTick, yPlane, zpTick); + } + + if (props.is_box () && ! plotyy) + { + m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTick); + m_glfcns.glVertex3d (xpTickN, yPlane, zpTick); + + if (! is2D) + { + m_glfcns.glVertex3d (xpTickN, yPlaneN, zpTickN); + m_glfcns.glVertex3d (xpTickN, yPlane, zpTickN); + if (boxFull) + { + m_glfcns.glVertex3d (xpTick, yPlaneN, zpTickN); + m_glfcns.glVertex3d (xpTick, yPlane, zpTickN); + } + } + } + } + + // Z box + color = props.get_zcolor_rgb (); + + if (! color.isempty () && ! is2D) + { + set_color (color); + + if (xySym) + { + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN); + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); + } + else + { + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); + } + + if (props.is_box ()) + { + m_glfcns.glVertex3d (xPlane, yPlane, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlane, zPlane); + + if (xySym) + { + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlaneN); + m_glfcns.glVertex3d (xPlane, yPlaneN, zPlane); + } + else + { + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlaneN); + m_glfcns.glVertex3d (xPlaneN, yPlane, zPlane); + } + + if (boxFull) + { + m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlaneN); + m_glfcns.glVertex3d (xPlaneN, yPlaneN, zPlane); + } + } + } + + m_glfcns.glEnd (); + + set_linestyle ("-"); // Disable LineStipple #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 (); + 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_line (const line::properties& props) - { +} + +void +opengl_renderer::draw_axes_x_grid (const axes::properties& props) +{ #if defined (HAVE_OPENGL) - bool draw_all = m_selecting && props.pickableparts_is ("all"); - - Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ()); - Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ()); - Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ()); - - bool has_z = (z.numel () > 0); - int n = static_cast (std::min (std::min (x.numel (), y.numel ()), - (has_z ? z.numel () - : std::numeric_limits::max ()))); - uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40); - uint8_t clip_ok = 0x40; - - std::vector clip (n); - - if (has_z) - for (int i = 0; i < n; i++) - clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask); - else - { - double z_mid = (m_zmin+m_zmax)/2; - - for (int i = 0; i < n; i++) - clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask); - } - - if (! props.linestyle_is ("none") && ! props.color_is ("none")) - { - set_color (props.get_color_rgb ()); - set_linestyle (props.get_linestyle (), false, props.get_linewidth ()); - set_linewidth (props.get_linewidth ()); - set_linecap ("butt"); - set_linejoin (props.get_linejoin ()); - - if (has_z) - { - bool flag = false; - - for (int i = 1; i < n; i++) - { - if ((clip[i-1] & clip[i]) == clip_ok) - { - if (! flag) - { - flag = true; - m_glfcns.glBegin (GL_LINE_STRIP); - m_glfcns.glVertex3d (x(i-1), y(i-1), z(i-1)); - } - m_glfcns.glVertex3d (x(i), y(i), z(i)); - } - else if (flag) - { - flag = false; - m_glfcns.glEnd (); - } - } - - if (flag) - m_glfcns.glEnd (); - } - else - { - bool flag = false; - - for (int i = 1; i < n; i++) - { - if ((clip[i-1] & clip[i]) == clip_ok) - { - if (! flag) - { - flag = true; - m_glfcns.glBegin (GL_LINE_STRIP); - m_glfcns.glVertex2d (x(i-1), y(i-1)); - } - m_glfcns.glVertex2d (x(i), y(i)); - } - else if (flag) - { - flag = false; - m_glfcns.glEnd (); - } - } - - if (flag) - m_glfcns.glEnd (); - } - - set_linewidth (0.5f); - set_linestyle ("-"); - } - - set_clipping (false); - - if (! props.marker_is ("none") - && ! (props.markeredgecolor_is ("none") - && props.markerfacecolor_is ("none"))) - { - Matrix lc, fc; - - if (draw_all) - lc = Matrix (1, 3, 0.0); - else if (props.markeredgecolor_is ("auto")) - lc = props.get_color_rgb (); - else if (! props.markeredgecolor_is ("none")) - lc = props.get_markeredgecolor_rgb (); - - if (draw_all) - fc = Matrix (1, 3, 0.0); - if (props.markerfacecolor_is ("auto")) - fc = props.get_color_rgb (); - else if (! props.markerfacecolor_is ("none")) - fc = props.get_markerfacecolor_rgb (); - - init_marker (props.get_marker (), props.get_markersize (), - props.get_linewidth ()); - - for (int i = 0; i < n; i++) - { - if (clip[i] == clip_ok) - draw_marker (x(i), y(i), - has_z ? z(i) : 0.0, - lc, fc); - } - - end_marker (); - } - - set_clipping (props.is_clipping ()); + gh_manager& gh_mgr = __get_gh_manager__ (); + + int xstate = props.get_xstate (); + + if (xstate != AXE_DEPTH_DIR + && (props.is_visible () + || (m_selecting && props.pickableparts_is ("all")))) + { + int zstate = props.get_zstate (); + bool x2Dtop = props.get_x2Dtop (); + bool layer2Dtop = props.get_layer2Dtop (); + bool xyzSym = props.get_xyzSym (); + bool nearhoriz = props.get_nearhoriz (); + double xticklen = props.get_xticklen (); + double xtickoffset = props.get_xtickoffset (); + double fy = props.get_fy (); + double fz = props.get_fz (); + double x_min = props.get_x_min (); + double x_max = props.get_x_max (); + double y_min = props.get_y_min (); + double y_max = props.get_y_max (); + double yPlane = props.get_yPlane (); + double yPlaneN = props.get_yPlaneN (); + double ypTick = props.get_ypTick (); + double ypTickN = props.get_ypTickN (); + double zPlane = props.get_zPlane (); + double zPlaneN = props.get_zPlaneN (); + double zpTick = props.get_zpTick (); + double zpTickN = props.get_zpTickN (); + + // X ticks and grid properties + Matrix xticks = m_xform.xscale (props.get_xtick ().matrix_value ()); + Matrix xmticks = m_xform.xscale (props.get_xminortickvalues ().matrix_value ()); + bool do_xminortick = props.is_xminortick () && ! xticks.isempty (); + string_vector xticklabels = props.get_xticklabel ().string_vector_value (); + int wmax = 0; + int hmax = 0; + bool tick_along_z = nearhoriz || math::isinf (fy); + double linewidth = props.get_linewidth (); + std::string gridstyle = props.get_gridlinestyle (); + std::string minorgridstyle = props.get_minorgridlinestyle (); + Matrix gridcolor = props.get_gridcolor_rgb (); + Matrix minorgridcolor = props.get_minorgridcolor_rgb (); + double gridalpha = props.get_gridalpha (); + double minorgridalpha = props.get_minorgridalpha (); + bool do_xgrid = (props.is_xgrid () && (gridstyle != "none")); + bool do_xminorgrid = (props.is_xminorgrid () + && (minorgridstyle != "none") + && ! xticks.isempty ()); + bool is_origin = props.xaxislocation_is ("origin") && props.get_is2D () + && ! props.yscale_is ("log"); + bool is_origin_low = is_origin && (y_min + y_max) < 0; + bool mirror = props.is_box () && xstate != AXE_ANY_DIR; + + // X grid + + // possibly use axis color for gridcolor & minorgridcolor + if (props.gridcolormode_is ("auto")) + if (props.xcolormode_is ("manual") && ! props.xcolor_is ("none")) + gridcolor = props.get_xcolor_rgb (); + + if (props.minorgridcolormode_is ("auto")) + if (props.xcolormode_is ("manual") && ! props.xcolor_is ("none")) + minorgridcolor = props.get_xcolor_rgb (); + + if (gridcolor.isempty ()) + do_xgrid = false; + + if (minorgridcolor.isempty ()) + do_xminorgrid = false; + + // set styles when drawing only minor grid + if (do_xminorgrid && ! do_xgrid) + { + gridstyle = minorgridstyle; + gridcolor = minorgridcolor; + gridalpha = minorgridalpha; + do_xgrid = true; + } + + // minor grid lines + if (do_xminorgrid) + render_grid (linewidth, + minorgridstyle, minorgridcolor, minorgridalpha, + xmticks, x_min, x_max, + yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 0, (zstate != AXE_DEPTH_DIR)); + + // grid lines + if (do_xgrid) + render_grid (linewidth, + gridstyle, gridcolor, gridalpha, + xticks, x_min, x_max, + yPlane, yPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 0, (zstate != AXE_DEPTH_DIR)); + + // Skip drawing axis, ticks, and ticklabels when color is "none" + if (props.xcolor_is ("none")) + return; + + set_color (props.get_xcolor_rgb ()); + + // axis line + double y_axis_pos = 0.; + if (is_origin) + { + y_axis_pos = math::max (math::min (0., y_max), y_min); + m_glfcns.glBegin (GL_LINES); + set_color (props.get_xcolor_rgb ()); + m_glfcns.glVertex3d (x_min, y_axis_pos, zpTick); + m_glfcns.glVertex3d (x_max, y_axis_pos, zpTick); + m_glfcns.glEnd (); + } + + // minor tick marks + if (do_xminortick) + { + if (tick_along_z) + render_tickmarks (xmticks, x_min, x_max, + is_origin ? y_axis_pos : ypTick, ypTick, + zpTick, zpTickN, 0., 0., + (is_origin_low ? -1. : 1.) * + math::signum (zpTick-zpTickN)*fz*xticklen/2, + 0, ! is_origin && mirror); + else + render_tickmarks (xmticks, x_min, x_max, + is_origin ? y_axis_pos : ypTick, ypTickN, + zpTick, zpTick, 0., + (is_origin_low ? -1. : 1.) * + math::signum (ypTick-ypTickN)*fy*xticklen/2, + 0., 0, ! is_origin && mirror); + } + + // tick marks + if (tick_along_z) + render_tickmarks (xticks, x_min, x_max, + is_origin ? y_axis_pos : ypTick, ypTick, + zpTick, zpTickN, 0., 0., + (is_origin_low ? -1. : 1.) * + math::signum (zpTick-zpTickN)*fz*xticklen, + 0, ! is_origin && mirror); + else + render_tickmarks (xticks, x_min, x_max, + is_origin ? y_axis_pos : ypTick, ypTickN, + zpTick, zpTick, 0., + (is_origin_low ? -1. : 1.) * + math::signum (ypTick-ypTickN)*fy*xticklen, + 0., 0, ! is_origin && mirror); + + // tick texts + if (xticklabels.numel () > 0) + { + int halign = (xstate == AXE_HORZ_DIR + ? 1 + : (xyzSym || is_origin_low ? 0 : 2)); + int valign = (xstate == AXE_VERT_DIR + ? 1 + : (x2Dtop || is_origin_low ? 0 : 2)); + + if (tick_along_z) + render_ticktexts (xticks, xticklabels, x_min, x_max, + is_origin ? y_axis_pos : ypTick, + zpTick + + (is_origin_low ? -1. : 1.) * + math::signum (zpTick-zpTickN)*fz*xtickoffset, + 0, halign, valign, wmax, hmax); + else + render_ticktexts (xticks, xticklabels, x_min, x_max, + (is_origin ? y_axis_pos : ypTick) + + (is_origin_low ? -1. : 1.) * + math::signum (ypTick-ypTickN)*fy*xtickoffset, + zpTick, 0, halign, valign, wmax, hmax); + } + + gh_mgr.get_object (props.get_xlabel ()).set ("visible", "on"); + } + else + gh_mgr.get_object (props.get_xlabel ()).set ("visible", "off"); #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 (); + 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_surface (const surface::properties& props) - { +} + +void +opengl_renderer::draw_axes_y_grid (const axes::properties& props) +{ #if defined (HAVE_OPENGL) - bool draw_all = m_selecting && props.pickableparts_is ("all"); - - const Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ()); - const Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ()); - const Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ()); - - int zr = z.rows (); - int zc = z.columns (); - - NDArray c; - const NDArray vn = props.get_vertexnormals ().array_value (); - dim_vector vn_dims = vn.dims (); - bool has_vertex_normals = (vn_dims(0) == zr && vn_dims(1) == zc - && vn_dims(2) == 3); - const NDArray fn = props.get_facenormals ().array_value (); - dim_vector fn_dims = fn.dims (); - bool has_face_normals = (fn_dims(0) == zr - 1 && fn_dims(1) == zc - 1 - && fn_dims(2) == 3); - - // FIXME: handle transparency - Matrix a; - - int fc_mode = (props.facecolor_is_rgb () ? 0 : - (props.facecolor_is ("flat") ? 1 : - (props.facecolor_is ("interp") ? 2 : - (props.facecolor_is ("texturemap") ? 3 : -1)))); - int fl_mode = (props.facelighting_is ("none") ? 0 : - (props.facelighting_is ("flat") ? - (has_face_normals ? 1 : 0) : - (has_vertex_normals ? 2 : 0))); - int fa_mode = (props.facealpha_is_double () ? 0 : - (props.facealpha_is ("flat") ? 1 : 2)); - int ec_mode = (props.edgecolor_is_rgb () ? 0 : - (props.edgecolor_is ("flat") ? 1 : - (props.edgecolor_is ("interp") ? 2 : -1))); - int el_mode = (props.edgelighting_is ("none") ? 0 : - (props.edgelighting_is ("flat") ? - (has_face_normals ? 1 : 0) : - (has_vertex_normals ? 2 : 0))); - int ea_mode = (props.edgealpha_is_double () ? 0 : - (props.edgealpha_is ("flat") ? 1 : 2)); - int bfl_mode = (props.backfacelighting_is ("lit") ? 0 : - (props.backfacelighting_is ("reverselit") ? 1 : 2)); - bool do_lighting = props.get_do_lighting (); - - Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0) - : props.get_facecolor_rgb ()); - Matrix ecolor = props.get_edgecolor_rgb (); - double fa = 1.0; - - float as = props.get_ambientstrength (); - float ds = props.get_diffusestrength (); - float ss = props.get_specularstrength (); - float se = props.get_specularexponent () * 5; // to fit Matlab - float scr = props.get_specularcolorreflectance (); - float cb[4] = { 0.0, 0.0, 0.0, 1.0 }; - - opengl_texture tex (m_glfcns); - - int i1, i2, j1, j2; - bool x_mat = (x.rows () == z.rows ()); - bool y_mat = (y.columns () == z.columns ()); - - i1 = i2 = j1 = j2 = 0; - - if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0) - c = props.get_color_data ().array_value (); - - boolMatrix clip (z.dims (), false); - - for (int i = 0; i < zr; i++) - { - if (x_mat) - i1 = i; - - for (int j = 0; j < zc; j++) - { - if (y_mat) - j1 = j; - - clip(i,j) = is_nan_or_inf (x(i1,j), y(i,j1), z(i,j)); - } - } - - if (fa_mode > 0 || ea_mode > 0) - { - // FIXME: implement alphadata conversion - //a = props.get_alpha_data (); - } - - if (fl_mode > 0 || el_mode > 0) - m_glfcns.glMaterialf (LIGHT_MODE, GL_SHININESS, se); - - // FIXME: good candidate for caching, - // transferring pixel data to OpenGL is time consuming. - if (fc_mode == TEXTURE) - tex = opengl_texture::create (m_glfcns, props.get_color_data ()); - - if (draw_all || ! props.facecolor_is ("none")) - { - if (fa_mode == 0) - { - fa = props.get_facealpha_double (); - cb[3] = fa; - if (fc_mode == UNIFORM || fc_mode == TEXTURE) - { - m_glfcns.glColor4d (fcolor(0), fcolor(1), fcolor(2), fa); - if (fl_mode > 0) - { - for (int i = 0; i < 3; i++) - cb[i] = as * fcolor(i); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int i = 0; i < 3; i++) - cb[i] = ds * fcolor(i); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int i = 0; i < 3; i++) - cb[i] = ss * (scr + (1-scr) * fcolor(i)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - - if ((fl_mode > 0) && do_lighting) - m_glfcns.glEnable (GL_LIGHTING); - m_glfcns.glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD) - ? GL_SMOOTH : GL_FLAT); - set_polygon_offset (true, 1.0); - if (fc_mode == TEXTURE) - m_glfcns.glEnable (GL_TEXTURE_2D); - - for (int i = 1; i < zc; i++) - { - if (y_mat) - { - i1 = i-1; - i2 = i; - } - - for (int j = 1; j < zr; j++) - { - - if (clip(j-1, i-1) || clip(j, i-1) - || clip(j-1, i) || clip(j, i)) - continue; - - if (fc_mode == FLAT) - { - // "flat" only needs color at lower-left vertex - if (! math::isfinite (c(j-1,i-1))) - continue; - } - else if (fc_mode == INTERP) - { - // "interp" needs valid color at all 4 vertices - if (! (math::isfinite (c(j-1, i-1)) - && math::isfinite (c(j, i-1)) - && math::isfinite (c(j-1, i)) - && math::isfinite (c(j, i)))) - continue; - } - - if (x_mat) - { - j1 = j-1; - j2 = j; - } - - m_glfcns.glBegin (GL_QUADS); - - // Vertex 1 - if (fc_mode == TEXTURE) - tex.tex_coord (double (i-1) / (zc-1), - double (j-1) / (zr-1)); - else if (fc_mode > 0) - { - // FIXME: is there a smarter way to do this? - for (int k = 0; k < 3; k++) - cb[k] = c(j-1, i-1, k); - m_glfcns.glColor4fv (cb); - - if (fl_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j-1, i-1, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j-1, i-1, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - if (fl_mode > 0) - set_normal (bfl_mode, (fl_mode == GOURAUD ? vn : fn), - j-1, i-1); - - m_glfcns.glVertex3d (x(j1,i-1), y(j-1,i1), z(j-1,i-1)); - - // Vertex 2 - if (fc_mode == TEXTURE) - tex.tex_coord (double (i) / (zc-1), - double (j-1) / (zr-1)); - else if (fc_mode == INTERP) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j-1, i, k); - m_glfcns.glColor4fv (cb); - - if (fl_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j-1, i, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j-1, i, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - - if (fl_mode == GOURAUD) - set_normal (bfl_mode, vn, j-1, i); - - m_glfcns.glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i)); - - // Vertex 3 - if (fc_mode == TEXTURE) - tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1)); - else if (fc_mode == INTERP) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j, i, k); - m_glfcns.glColor4fv (cb); - - if (fl_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j, i, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j, i, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - if (fl_mode == GOURAUD) - set_normal (bfl_mode, vn, j, i); - - m_glfcns.glVertex3d (x(j2,i), y(j,i2), z(j,i)); - - // Vertex 4 - if (fc_mode == TEXTURE) - tex.tex_coord (double (i-1) / (zc-1), - double (j) / (zr-1)); - else if (fc_mode == INTERP) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j, i-1, k); - m_glfcns.glColor4fv (cb); - - if (fl_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j, i-1, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j, i-1, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - if (fl_mode == GOURAUD) - set_normal (bfl_mode, vn, j, i-1); - - m_glfcns.glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1)); - - m_glfcns.glEnd (); - } - } - - set_polygon_offset (false); - if (fc_mode == TEXTURE) - m_glfcns.glDisable (GL_TEXTURE_2D); - - if ((fl_mode > 0) && do_lighting) - m_glfcns.glDisable (GL_LIGHTING); - } - else - { - // FIXME: implement flat, interp and texturemap transparency - } - } - - if (! props.edgecolor_is ("none") && ! props.linestyle_is ("none")) - { - if (props.get_edgealpha_double () == 1) - { - cb[3] = 1.0; // edgealpha isn't implemented yet - if (ec_mode == UNIFORM) - { - m_glfcns.glColor3dv (ecolor.data ()); - if (el_mode > 0) - { - for (int i = 0; i < 3; i++) - cb[i] = as * ecolor(i); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int i = 0; i < 3; i++) - cb[i] = ds * ecolor(i); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int i = 0; i < 3; i++) - cb[i] = ss * (scr + (1-scr) * ecolor(i)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - - if ((el_mode > 0) && do_lighting) - m_glfcns.glEnable (GL_LIGHTING); - m_glfcns.glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD) - ? GL_SMOOTH : GL_FLAT); - - set_linestyle (props.get_linestyle (), false, - props.get_linewidth ()); - set_linewidth (props.get_linewidth ()); - set_linecap ("butt"); - set_linejoin ("miter"); - - // Mesh along Y-axis - - if (props.meshstyle_is ("both") || props.meshstyle_is ("column")) - { - for (int i = 0; i < zc; i++) - { - if (y_mat) - { - i1 = i-1; - i2 = i; - } - - for (int j = 1; j < zr; j++) - { - if (clip(j-1,i) || clip(j,i)) - continue; - - if (ec_mode == FLAT) - { - // "flat" only needs color at lower-left vertex - if (! math::isfinite (c(j-1,i))) - continue; - } - else if (ec_mode == INTERP) - { - // "interp" needs valid color at both vertices - if (! (math::isfinite (c(j-1, i)) - && math::isfinite (c(j, i)))) - continue; - } - - if (x_mat) - { - j1 = j-1; - j2 = j; - } - - m_glfcns.glBegin (GL_LINES); - - // Vertex 1 - if (ec_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j-1, i, k); - m_glfcns.glColor3fv (cb); - - if (el_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j-1, i, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j-1, i, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, - cb); - } - } - if (el_mode > 0) - { - if (el_mode == GOURAUD) - set_normal (bfl_mode, vn, j-1, i); - else - set_normal (bfl_mode, fn, j-1, std::min (i, zc-2)); - } - - m_glfcns.glVertex3d (x(j1,i), y(j-1,i2), z(j-1,i)); - - // Vertex 2 - if (ec_mode == INTERP) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j, i, k); - m_glfcns.glColor3fv (cb); - - if (el_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j, i, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j, i, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, - cb); - } - } - if (el_mode == GOURAUD) - set_normal (bfl_mode, vn, j, i); - - m_glfcns.glVertex3d (x(j2,i), y(j,i2), z(j,i)); - - m_glfcns.glEnd (); - } - } - } - - // Mesh along X-axis - - if (props.meshstyle_is ("both") || props.meshstyle_is ("row")) - { - for (int j = 0; j < zr; j++) - { - if (x_mat) - { - j1 = j-1; - j2 = j; - } - - for (int i = 1; i < zc; i++) - { - if (clip(j,i-1) || clip(j,i)) - continue; - - if (ec_mode == FLAT) - { - // "flat" only needs color at lower-left vertex - if (! math::isfinite (c(j,i-1))) - continue; - } - else if (ec_mode == INTERP) - { - // "interp" needs valid color at both vertices - if (! (math::isfinite (c(j, i-1)) - && math::isfinite (c(j, i)))) - continue; - } - - if (y_mat) - { - i1 = i-1; - i2 = i; - } - - m_glfcns.glBegin (GL_LINES); - - // Vertex 1 - if (ec_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j, i-1, k); - m_glfcns.glColor3fv (cb); - - if (el_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j, i-1, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j, i-1, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, - cb); - } - } - if (el_mode > 0) - { - if (el_mode == GOURAUD) - set_normal (bfl_mode, vn, j, i-1); - else - set_normal (bfl_mode, fn, std::min (j, zr-2), i-1); - } - - m_glfcns.glVertex3d (x(j2,i-1), y(j,i1), z(j,i-1)); - - // Vertex 2 - if (ec_mode == INTERP) - { - for (int k = 0; k < 3; k++) - cb[k] = c(j, i, k); - m_glfcns.glColor3fv (cb); - - if (el_mode > 0) - { - for (int k = 0; k < 3; k++) - cb[k] *= as; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ds * c(j, i, k); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, - cb); - - for (int k = 0; k < 3; k++) - cb[k] = ss * (scr + (1-scr) * c(j, i, k)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, - cb); - } - } - if (el_mode == GOURAUD) - set_normal (bfl_mode, vn, j, i); - - m_glfcns.glVertex3d (x(j2,i), y(j,i2), z(j,i)); - - m_glfcns.glEnd (); - } - } - } - - set_linestyle ("-"); // Disable LineStipple - set_linewidth (0.5f); - - if ((el_mode > 0) && do_lighting) - m_glfcns.glDisable (GL_LIGHTING); - } - else - { - // FIXME: implement transparency - } - } - - if (! props.marker_is ("none") - && ! (props.markeredgecolor_is ("none") - && props.markerfacecolor_is ("none"))) - { - // FIXME: check how transparency should be handled in markers - // FIXME: check what to do with marker facecolor set to auto - // and facecolor set to none. - - bool do_edge = draw_all || ! props.markeredgecolor_is ("none"); - bool do_face = draw_all || ! props.markerfacecolor_is ("none"); - - 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 ()); - Matrix cc (1, 3, 0.0); - - if (mecolor.isempty () && props.markeredgecolor_is ("auto")) - { - mecolor = props.get_edgecolor_rgb (); - do_edge = ! props.edgecolor_is ("none"); - } - - if (mfcolor.isempty () && props.markerfacecolor_is ("auto")) - { - mfcolor = props.get_facecolor_rgb (); - do_face = ! props.facecolor_is ("none"); - } - - if ((mecolor.isempty () || mfcolor.isempty ()) && c.isempty ()) - c = props.get_color_data ().array_value (); - - init_marker (props.get_marker (), props.get_markersize (), - props.get_linewidth ()); - - uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40); - uint8_t clip_ok = 0x40; - - for (int i = 0; i < zc; i++) - { - if (y_mat) - i1 = i; - - for (int j = 0; j < zr; j++) - { - if (x_mat) - j1 = j; - - if ((clip_code (x(j1,i), y(j,i1), z(j,i)) & clip_mask) - != clip_ok) - continue; - - if ((do_edge && mecolor.isempty ()) - || (do_face && mfcolor.isempty ())) - { - if (! math::isfinite (c(j,i))) - continue; // Skip NaNs in color data - - for (int k = 0; k < 3; k++) - cc(k) = c(j,i,k); - } - - Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor) - : Matrix ()); - Matrix fc = (do_face ? (mfcolor.isempty () ? cc : mfcolor) - : Matrix ()); - - draw_marker (x(j1,i), y(j,i1), z(j,i), lc, fc); - } - } - - end_marker (); - } + gh_manager& gh_mgr = __get_gh_manager__ (); + + int ystate = props.get_ystate (); + + if (ystate != AXE_DEPTH_DIR && props.is_visible () + && (props.is_visible () + || (m_selecting && props.pickableparts_is ("all")))) + { + int zstate = props.get_zstate (); + bool y2Dright = props.get_y2Dright (); + bool layer2Dtop = props.get_layer2Dtop (); + bool xyzSym = props.get_xyzSym (); + bool nearhoriz = props.get_nearhoriz (); + double yticklen = props.get_yticklen (); + double ytickoffset = props.get_ytickoffset (); + double fx = props.get_fx (); + double fz = props.get_fz (); + double xPlane = props.get_xPlane (); + double xPlaneN = props.get_xPlaneN (); + double xpTick = props.get_xpTick (); + double xpTickN = props.get_xpTickN (); + double y_min = props.get_y_min (); + double y_max = props.get_y_max (); + double x_min = props.get_x_min (); + double x_max = props.get_x_max (); + double zPlane = props.get_zPlane (); + double zPlaneN = props.get_zPlaneN (); + double zpTick = props.get_zpTick (); + double zpTickN = props.get_zpTickN (); + + // Y ticks and grid properties + Matrix yticks = m_xform.yscale (props.get_ytick ().matrix_value ()); + Matrix ymticks = m_xform.yscale (props.get_yminortickvalues ().matrix_value ()); + bool do_yminortick = props.is_yminortick () && ! yticks.isempty (); + string_vector yticklabels = props.get_yticklabel ().string_vector_value (); + int wmax = 0; + int hmax = 0; + bool tick_along_z = nearhoriz || math::isinf (fx); + double linewidth = props.get_linewidth (); + std::string gridstyle = props.get_gridlinestyle (); + std::string minorgridstyle = props.get_minorgridlinestyle (); + Matrix gridcolor = props.get_gridcolor_rgb (); + Matrix minorgridcolor = props.get_minorgridcolor_rgb (); + double gridalpha = props.get_gridalpha (); + double minorgridalpha = props.get_minorgridalpha (); + bool do_ygrid = (props.is_ygrid () && (gridstyle != "none")); + bool do_yminorgrid = (props.is_yminorgrid () + && (minorgridstyle != "none") + && ! yticks.isempty ()); + bool is_origin = props.yaxislocation_is ("origin") && props.get_is2D () + && ! props.xscale_is ("log"); + bool is_origin_low = is_origin && (x_min + x_max) < 0; + bool mirror = props.is_box () && ystate != AXE_ANY_DIR + && (! props.has_property ("__plotyy_axes__")); + + // Y grid + + // possibly use axis color for gridcolor & minorgridcolor + if (props.gridcolormode_is ("auto")) + if (props.ycolormode_is ("manual") && ! props.ycolor_is ("none")) + gridcolor = props.get_ycolor_rgb (); + + if (props.minorgridcolormode_is ("auto")) + if (props.ycolormode_is ("manual") && ! props.ycolor_is ("none")) + minorgridcolor = props.get_ycolor_rgb (); + + if (gridcolor.isempty ()) + do_ygrid = false; + + if (minorgridcolor.isempty ()) + do_yminorgrid = false; + + // set styles when drawing only minor grid + if (do_yminorgrid && ! do_ygrid) + { + gridstyle = minorgridstyle; + gridcolor = minorgridcolor; + gridalpha = minorgridalpha; + do_ygrid = true; + } + + // minor grid lines + if (do_yminorgrid) + render_grid (linewidth, + minorgridstyle, minorgridcolor, minorgridalpha, + ymticks, y_min, y_max, + xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 1, (zstate != AXE_DEPTH_DIR)); + + // grid lines + if (do_ygrid) + render_grid (linewidth, + gridstyle, gridcolor, gridalpha, + yticks, y_min, y_max, + xPlane, xPlaneN, layer2Dtop ? zPlaneN : zPlane, zPlaneN, + 1, (zstate != AXE_DEPTH_DIR)); + + // Skip drawing axis, ticks, and ticklabels when color is "none" + if (props.ycolor_is ("none")) + return; + + set_color (props.get_ycolor_rgb ()); + + // axis line + double x_axis_pos = 0.; + if (is_origin) + { + x_axis_pos = math::max (math::min (0., x_max), x_min); + m_glfcns.glBegin (GL_LINES); + set_color (props.get_ycolor_rgb ()); + m_glfcns.glVertex3d (x_axis_pos, y_min, zpTick); + m_glfcns.glVertex3d (x_axis_pos, y_max, zpTick); + m_glfcns.glEnd (); + } + + // minor tick marks + if (do_yminortick) + { + if (tick_along_z) + render_tickmarks (ymticks, y_min, y_max, + is_origin ? x_axis_pos : xpTick, xpTick, + zpTick, zpTickN, 0., 0., + (is_origin_low ? -1. : 1.) * + math::signum (zpTick-zpTickN)*fz*yticklen/2, + 1, ! is_origin && mirror); + else + render_tickmarks (ymticks, y_min, y_max, + is_origin ? x_axis_pos : xpTick, xpTickN, + zpTick, zpTick, + (is_origin_low ? -1. : 1.) * + math::signum (xpTick-xpTickN)*fx*yticklen/2, + 0., 0., 1, ! is_origin && mirror); + } + + // tick marks + if (tick_along_z) + render_tickmarks (yticks, y_min, y_max, + is_origin ? x_axis_pos : xpTick, xpTick, + zpTick, zpTickN, 0., 0., + (is_origin_low ? -1. : 1.) * + math::signum (zpTick-zpTickN)*fz*yticklen, + 1, ! is_origin && mirror); + else + render_tickmarks (yticks, y_min, y_max, + is_origin ? x_axis_pos : xpTick, xpTickN, + zpTick, zpTick, + (is_origin_low ? -1. : 1.) * + math::signum (xPlaneN-xPlane)*fx*yticklen, + 0., 0., 1, ! is_origin && mirror); + + // tick texts + if (yticklabels.numel () > 0) + { + int halign = (ystate == AXE_HORZ_DIR + ? 1 + : (! xyzSym || y2Dright || is_origin_low ? 0 : 2)); + int valign = (ystate == AXE_VERT_DIR + ? 1 + : (is_origin_low ? 0 : 2)); + + if (tick_along_z) + render_ticktexts (yticks, yticklabels, y_min, y_max, + is_origin ? x_axis_pos : xpTick, + zpTick + + (is_origin_low ? -1. : 1.) * + math::signum (zpTick-zpTickN)*fz*ytickoffset, + 1, halign, valign, wmax, hmax); + else + render_ticktexts (yticks, yticklabels, y_min, y_max, + (is_origin ? x_axis_pos : xpTick) + + (is_origin_low ? -1. : 1.) * + math::signum (xpTick-xpTickN)*fx*ytickoffset, + zpTick, 1, halign, valign, wmax, hmax); + } + + gh_mgr.get_object (props.get_ylabel ()).set ("visible", "on"); + } + else + gh_mgr.get_object (props.get_ylabel ()).set ("visible", "off"); + +#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_axes_z_grid (const axes::properties& props) +{ + gh_manager& gh_mgr = __get_gh_manager__ (); + + int zstate = props.get_zstate (); + + if (zstate != AXE_DEPTH_DIR && props.is_visible () + && (props.is_visible () + || (m_selecting && props.pickableparts_is ("all")))) + { + bool xySym = props.get_xySym (); + bool zSign = props.get_zSign (); + double zticklen = props.get_zticklen (); + double ztickoffset = props.get_ztickoffset (); + double fx = props.get_fx (); + double fy = props.get_fy (); + double xPlane = props.get_xPlane (); + double xPlaneN = props.get_xPlaneN (); + double yPlane = props.get_yPlane (); + double yPlaneN = props.get_yPlaneN (); + double z_min = props.get_z_min (); + double z_max = props.get_z_max (); + + // Z ticks and grid properties + Matrix zticks = m_xform.zscale (props.get_ztick ().matrix_value ()); + Matrix zmticks = m_xform.zscale (props.get_zminortickvalues ().matrix_value ()); + bool do_zminortick = props.is_zminortick () && ! zticks.isempty (); + string_vector zticklabels = props.get_zticklabel ().string_vector_value (); + int wmax = 0; + int hmax = 0; + double linewidth = props.get_linewidth (); + std::string gridstyle = props.get_gridlinestyle (); + std::string minorgridstyle = props.get_minorgridlinestyle (); + Matrix gridcolor = props.get_gridcolor_rgb (); + Matrix minorgridcolor = props.get_minorgridcolor_rgb (); + double gridalpha = props.get_gridalpha (); + double minorgridalpha = props.get_minorgridalpha (); + bool do_zgrid = (props.is_zgrid () && (gridstyle != "none")); + bool do_zminorgrid = (props.is_zminorgrid () + && (minorgridstyle != "none") + && ! zticks.isempty ()); + bool mirror = props.is_box () && zstate != AXE_ANY_DIR; + + // Z grid + + // possibly use axis color for gridcolor & minorgridcolor + if (props.gridcolormode_is ("auto")) + if (props.zcolormode_is ("manual") && ! props.zcolor_is ("none")) + gridcolor = props.get_zcolor_rgb (); + + if (props.minorgridcolormode_is ("auto")) + if (props.zcolormode_is ("manual") && ! props.zcolor_is ("none")) + minorgridcolor = props.get_zcolor_rgb (); + + if (gridcolor.isempty ()) + do_zgrid = false; + + if (minorgridcolor.isempty ()) + do_zminorgrid = false; + + // set styles when drawing only minor grid + if (do_zminorgrid && ! do_zgrid) + { + gridstyle = minorgridstyle; + gridcolor = minorgridcolor; + gridalpha = minorgridalpha; + do_zgrid = true; + } + + // minor grid lines + if (do_zminorgrid) + render_grid (linewidth, + minorgridstyle, minorgridcolor, minorgridalpha, + zmticks, z_min, z_max, + xPlane, xPlaneN, yPlane, yPlaneN, 2, true); + + // grid lines + if (do_zgrid) + render_grid (linewidth, + gridstyle, gridcolor, gridalpha, + zticks, z_min, z_max, + xPlane, xPlaneN, yPlane, yPlaneN, 2, true); + + // Skip drawing axis, ticks, and ticklabels when color is "none" + if (props.zcolor_is ("none")) + return; + + set_color (props.get_zcolor_rgb ()); + + // minor tick marks + if (do_zminortick) + { + if (xySym) + { + if (math::isinf (fy)) + render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane, + yPlane, yPlane, + math::signum (xPlaneN-xPlane)*fx*zticklen/2, + 0., 0., 2, mirror); + else + render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN, + yPlane, yPlane, 0., + math::signum (yPlane-yPlaneN)*fy*zticklen/2, + 0., 2, false); + } + else + { + if (math::isinf (fx)) + render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane, + yPlaneN, yPlane, 0., + math::signum (yPlaneN-yPlane)*fy*zticklen/2, + 0., 2, mirror); + else + render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane, + yPlaneN, yPlaneN, + math::signum (xPlane-xPlaneN)*fx*zticklen/2, + 0., 0., 2, false); + } + } + + // tick marks + if (xySym) + { + if (math::isinf (fy)) + render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane, + yPlane, yPlane, + math::signum (xPlaneN-xPlane)*fx*zticklen, + 0., 0., 2, mirror); + else + render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN, + yPlane, yPlane, 0., + math::signum (yPlane-yPlaneN)*fy*zticklen, + 0., 2, false); + } + else + { + if (math::isinf (fx)) + render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlane, + yPlaneN, yPlane, 0., + math::signum (yPlaneN-yPlane)*fy*zticklen, + 0., 2, mirror); + else + render_tickmarks (zticks, z_min, z_max, xPlane, xPlane, + yPlaneN, yPlane, + math::signum (xPlane-xPlaneN)*fx*zticklen, + 0., 0., 2, false); + } + + // tick texts + if (zticklabels.numel () > 0) + { + int halign = 2; + int valign = (zstate == AXE_VERT_DIR ? 1 : (zSign ? 3 : 2)); + + if (xySym) + { + if (math::isinf (fy)) + render_ticktexts (zticks, zticklabels, z_min, z_max, + xPlaneN + math::signum (xPlaneN-xPlane)*fx*ztickoffset, + yPlane, 2, halign, valign, wmax, hmax); + else + render_ticktexts (zticks, zticklabels, z_min, z_max, xPlaneN, + yPlane + math::signum (yPlane-yPlaneN)*fy*ztickoffset, + 2, halign, valign, wmax, hmax); + } + else + { + if (math::isinf (fx)) + render_ticktexts (zticks, zticklabels, z_min, z_max, xPlane, + yPlaneN + math::signum (yPlaneN-yPlane)*fy*ztickoffset, + 2, halign, valign, wmax, hmax); + else + render_ticktexts (zticks, zticklabels, z_min, z_max, + xPlane + math::signum (xPlane-xPlaneN)*fx*ztickoffset, + yPlaneN, 2, halign, valign, wmax, hmax); + } + } + + gh_mgr.get_object (props.get_zlabel ()).set ("visible", "on"); + } + else + gh_mgr.get_object (props.get_zlabel ()).set ("visible", "off"); +} + +void +opengl_renderer::draw_axes_grids (const axes::properties& props) +{ +#if defined (HAVE_OPENGL) + // Disable line smoothing for axes + GLboolean antialias; + + m_glfcns.glGetBooleanv (GL_LINE_SMOOTH, &antialias); + + if (antialias == GL_TRUE) + m_glfcns.glDisable (GL_LINE_SMOOTH); + + set_linecap ("butt"); + set_linewidth (props.get_linewidth ()); + set_font (props); + set_interpreter (props.get_ticklabelinterpreter ()); + + draw_axes_x_grid (props); + draw_axes_y_grid (props); + draw_axes_z_grid (props); + + if (antialias == GL_TRUE) + m_glfcns.glEnable (GL_LINE_SMOOTH); +#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_all_lights (const base_properties& props, + std::list& obj_list) +{ +#if defined (HAVE_OPENGL) + gh_manager& gh_mgr = __get_gh_manager__ (); + + Matrix children = props.get_all_children (); + + for (octave_idx_type i = children.numel () - 1; i >= 0; i--) + { + graphics_object go = gh_mgr.get_object (children(i)); + + base_properties p = go.get_properties (); + + if (p.is_visible () + || (m_selecting && p.pickableparts_is ("all"))) + { + if (go.isa ("light") && ! m_selecting) + { + if (m_current_light-GL_LIGHT0 < m_max_lights) + { + set_clipping (p.is_clipping ()); + draw (go); + m_current_light++; + } + } + else if (go.isa ("hggroup") + && ! (m_selecting && p.pickableparts_is ("none"))) + draw_all_lights (go.get_properties (), obj_list); + else if (! (m_selecting && p.pickableparts_is ("none"))) + obj_list.push_back (go); + } + } +#else + + octave_unused_parameter (props); + octave_unused_parameter (obj_list); + + // 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_axes_children (const axes::properties& props) +{ +#if defined (HAVE_OPENGL) + // list for non-light child objects + std::list obj_list; + std::list::iterator it; + + // 1st pass: draw light objects + + // FIXME: max_lights only needs to be set once. + // It would be better if this could be in the constructor for gl_renderer + // but this seems to lead to calls of OpenGL functions before the context + // is actually initialized. See bug #48669. + // Check actual maximum number of lights possible + init_maxlights (); + + // Start with the last element of the array of child objects to + // display them in the order they were added to the array. + + if (props.get_num_lights () > m_max_lights) + warning_with_id ("Octave:max-lights-exceeded", + "light: Maximum number of lights (%d) in these axes is " + "exceeded.", m_max_lights); + + m_current_light = GL_LIGHT0; + draw_all_lights (props, obj_list); + + // disable other OpenGL lights + for (unsigned int i = props.get_num_lights (); i < m_max_lights; i++) + m_glfcns.glDisable (GL_LIGHT0 + i); + + // save camera position and set ambient light color before drawing + // other objects + m_view_vector = props.get_cameraposition ().matrix_value (); + + float cb[4] = { 1.0, 1.0, 1.0, 1.0 }; + ColumnVector ambient_color = props.get_ambientlightcolor_rgb (); + for (int i = 0; i < 3; i++) + cb[i] = ambient_color(i); + m_glfcns.glLightfv (GL_LIGHT0, GL_AMBIENT, cb); + + // 2nd pass: draw other objects (with units set to "data") + + it = obj_list.begin (); + while (it != obj_list.end ()) + { + graphics_object go = (*it); + + // FIXME: check whether object has "units" property and it is set + // to "data" + if (! go.isa ("text") || go.get ("units").string_value () == "data") + { + set_clipping (go.get_properties ().is_clipping ()); + draw (go); + + it = obj_list.erase (it); + } + else + it++; + } + + // 3rd pass: draw remaining objects + + m_glfcns.glDisable (GL_DEPTH_TEST); + + for (it = obj_list.begin (); it != obj_list.end (); it++) + { + graphics_object go = (*it); + + set_clipping (go.get_properties ().is_clipping ()); + draw (go); + } + + set_clipping (false); + + // FIXME: finalize rendering (transparency processing) + // FIXME: draw zoom box, if needed + +#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_axes (const axes::properties& props) +{ +#if defined (HAVE_OPENGL) + + // Legends are not drawn when "visible" is "off". + if (! props.is_visible () && props.get_tag () == "legend") + return; + + // Don't draw the axes and its children if we are in selection and + // pickable parts is "none". + if (m_selecting && props.pickableparts_is ("none")) + return; + + static double floatmax = std::numeric_limits::max (); + + double x_min = props.get_x_min (); + double x_max = props.get_x_max (); + double y_min = props.get_y_min (); + double y_max = props.get_y_max (); + double z_min = props.get_z_min (); + double z_max = props.get_z_max (); + + if (x_max > floatmax || y_max > floatmax || z_max > floatmax + || x_min < -floatmax || y_min < -floatmax || z_min < -floatmax) + { + warning ("opengl_renderer: data values greater than float capacity. (1) Scale data, or (2) Use gnuplot"); + return; + } + + setup_opengl_transformation (props); + + // For 2D axes with only 2D primitives, draw from back to front without + // depth sorting + bool is2D = props.get_is2D (true); + if (is2D) + m_glfcns.glDisable (GL_DEPTH_TEST); + else + m_glfcns.glEnable (GL_DEPTH_TEST); + + draw_axes_planes (props); + + if (! is2D || props.layer_is ("bottom")) + { + draw_axes_grids (props); + if (props.get_tag () != "legend" || props.get_box () != "off") + draw_axes_boxes (props); + } + + set_clipbox (x_min, x_max, y_min, y_max, z_min, z_max); + + draw_axes_children (props); + + if (is2D && props.layer_is ("top")) + { + draw_axes_grids (props); + if (props.get_tag () != "legend" || props.get_box () != "off") + draw_axes_boxes (props); + } #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 (); + 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_line (const line::properties& props) +{ +#if defined (HAVE_OPENGL) + + bool draw_all = m_selecting && props.pickableparts_is ("all"); + + Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ()); + Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ()); + Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ()); + + bool has_z = (z.numel () > 0); + int n = static_cast (std::min (std::min (x.numel (), y.numel ()), + (has_z ? z.numel () + : std::numeric_limits::max ()))); + uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40); + uint8_t clip_ok = 0x40; + + std::vector clip (n); + + if (has_z) + for (int i = 0; i < n; i++) + clip[i] = (clip_code (x(i), y(i), z(i)) & clip_mask); + else + { + double z_mid = (m_zmin+m_zmax)/2; + + for (int i = 0; i < n; i++) + clip[i] = (clip_code (x(i), y(i), z_mid) & clip_mask); + } + + if (! props.linestyle_is ("none") && ! props.color_is ("none")) + { + set_color (props.get_color_rgb ()); + set_linestyle (props.get_linestyle (), false, props.get_linewidth ()); + set_linewidth (props.get_linewidth ()); + set_linecap ("butt"); + set_linejoin (props.get_linejoin ()); + + if (has_z) + { + bool flag = false; + + for (int i = 1; i < n; i++) + { + if ((clip[i-1] & clip[i]) == clip_ok) + { + if (! flag) + { + flag = true; + m_glfcns.glBegin (GL_LINE_STRIP); + m_glfcns.glVertex3d (x(i-1), y(i-1), z(i-1)); + } + m_glfcns.glVertex3d (x(i), y(i), z(i)); + } + else if (flag) + { + flag = false; + m_glfcns.glEnd (); + } + } + + if (flag) + m_glfcns.glEnd (); + } + else + { + bool flag = false; + + for (int i = 1; i < n; i++) + { + if ((clip[i-1] & clip[i]) == clip_ok) + { + if (! flag) + { + flag = true; + m_glfcns.glBegin (GL_LINE_STRIP); + m_glfcns.glVertex2d (x(i-1), y(i-1)); + } + m_glfcns.glVertex2d (x(i), y(i)); + } + else if (flag) + { + flag = false; + m_glfcns.glEnd (); + } + } + + if (flag) + m_glfcns.glEnd (); + } + + set_linewidth (0.5f); + set_linestyle ("-"); + } + + set_clipping (false); + + if (! props.marker_is ("none") + && ! (props.markeredgecolor_is ("none") + && props.markerfacecolor_is ("none"))) + { + Matrix lc, fc; + + if (draw_all) + lc = Matrix (1, 3, 0.0); + else if (props.markeredgecolor_is ("auto")) + lc = props.get_color_rgb (); + else if (! props.markeredgecolor_is ("none")) + lc = props.get_markeredgecolor_rgb (); + + if (draw_all) + fc = Matrix (1, 3, 0.0); + if (props.markerfacecolor_is ("auto")) + fc = props.get_color_rgb (); + else if (! props.markerfacecolor_is ("none")) + fc = props.get_markerfacecolor_rgb (); + + init_marker (props.get_marker (), props.get_markersize (), + props.get_linewidth ()); + + for (int i = 0; i < n; i++) + { + if (clip[i] == clip_ok) + draw_marker (x(i), y(i), + has_z ? z(i) : 0.0, + lc, fc); + } + + end_marker (); + } + + set_clipping (props.is_clipping ()); + +#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 - } - - // FIXME: global optimization (rendering, data structures...), - // there is probably a smarter/faster/less-memory-consuming way to do this. - void - opengl_renderer::draw_patch (const patch::properties& props) - { +} + +void +opengl_renderer::draw_surface (const surface::properties& props) +{ #if defined (HAVE_OPENGL) - // Do not render if the patch 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 = m_selecting && props.pickableparts_is ("all"); - const Matrix f = props.get_faces ().matrix_value (); - const Matrix v = m_xform.scale (props.get_vertices ().matrix_value ()); - Matrix c; - Matrix a; - double fa = 1.0; - - int nv = v.rows (); - int nf = f.rows (); - int fcmax = f.columns (); - - bool has_z = (v.columns () > 2); - bool has_facecolor = false; - bool has_facealpha = false; - - int fc_mode = ((props.facecolor_is ("none") - || props.facecolor_is_rgb () || draw_all) ? 0 : - (props.facecolor_is ("flat") ? 1 : 2)); - int fl_mode = (props.facelighting_is ("none") ? 0 : - (props.facelighting_is ("flat") ? 1 : 2)); - int fa_mode = (props.facealpha_is_double () ? 0 : - (props.facealpha_is ("flat") ? 1 : 2)); - int ec_mode = ((props.edgecolor_is ("none") - || props.edgecolor_is_rgb ()) ? 0 : - (props.edgecolor_is ("flat") ? 1 : 2)); - int el_mode = (props.edgelighting_is ("none") ? 0 : - (props.edgelighting_is ("flat") ? 1 : 2)); - int ea_mode = (props.edgealpha_is_double () ? 0 : - (props.edgealpha_is ("flat") ? 1 : 2)); - int bfl_mode = (props.backfacelighting_is ("lit") ? 0 : - (props.backfacelighting_is ("reverselit") ? 1 : 2)); - bool do_lighting = props.get_do_lighting (); - - Matrix fcolor = props.get_facecolor_rgb (); - Matrix ecolor = props.get_edgecolor_rgb (); - - float as = props.get_ambientstrength (); - float ds = props.get_diffusestrength (); - float ss = props.get_specularstrength (); - float se = props.get_specularexponent () * 5; // to fit Matlab - float scr = props.get_specularcolorreflectance (); - - const Matrix vn = props.get_vertexnormals ().matrix_value (); - bool has_vertex_normals = (vn.rows () == nv); - const Matrix fn = props.get_facenormals ().matrix_value (); - bool has_face_normals = (fn.rows () == nf); - - boolMatrix clip (1, nv, false); - - if (has_z) - for (int i = 0; i < nv; i++) - clip(i) = is_nan_or_inf (v(i,0), v(i,1), v(i,2)); - else - for (int i = 0; i < nv; i++) - clip(i) = is_nan_or_inf (v(i,0), v(i,1), 0); - - boolMatrix clip_f (1, nf, false); - Array count_f (dim_vector (nf, 1), 0); - - for (int i = 0; i < nf; i++) - { - bool fclip = false; - int count = 0; - - for (int j = 0; j < fcmax && ! math::isnan (f(i,j)); j++, count++) - fclip = (fclip || clip(int (f(i,j) - 1))); - - clip_f(i) = fclip; - count_f(i) = count; - } - - if (draw_all || fc_mode > 0 || ec_mode > 0) - { - if (draw_all) - c = Matrix (1, 3, 0.0); - else - c = props.get_color_data ().matrix_value (); - - if (c.rows () == 1) - { - // Single color specifications, we can simplify a little bit - - if (draw_all || fc_mode > 0) - { - fcolor = c; - fc_mode = UNIFORM; - } - - if (draw_all || ec_mode > 0) - { - ecolor = c; - ec_mode = UNIFORM; - } - - c = Matrix (); - } - else - has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ())); - } - - if (fa_mode > 0 || ea_mode > 0) - { - // FIXME: retrieve alpha data from patch object - //a = props.get_alpha_data (); - has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ())); - } - - if (fa_mode == 0) - fa = props.get_facealpha_double (); - - octave_idx_type fr = f.rows (); - std::vector vdata (f.numel ()); - - for (int i = 0; i < nf; i++) - for (int j = 0; j < count_f(i); j++) + bool draw_all = m_selecting && props.pickableparts_is ("all"); + + const Matrix x = m_xform.xscale (props.get_xdata ().matrix_value ()); + const Matrix y = m_xform.yscale (props.get_ydata ().matrix_value ()); + const Matrix z = m_xform.zscale (props.get_zdata ().matrix_value ()); + + int zr = z.rows (); + int zc = z.columns (); + + NDArray c; + const NDArray vn = props.get_vertexnormals ().array_value (); + dim_vector vn_dims = vn.dims (); + bool has_vertex_normals = (vn_dims(0) == zr && vn_dims(1) == zc + && vn_dims(2) == 3); + const NDArray fn = props.get_facenormals ().array_value (); + dim_vector fn_dims = fn.dims (); + bool has_face_normals = (fn_dims(0) == zr - 1 && fn_dims(1) == zc - 1 + && fn_dims(2) == 3); + + // FIXME: handle transparency + Matrix a; + + int fc_mode = (props.facecolor_is_rgb () ? 0 : + (props.facecolor_is ("flat") ? 1 : + (props.facecolor_is ("interp") ? 2 : + (props.facecolor_is ("texturemap") ? 3 : -1)))); + int fl_mode = (props.facelighting_is ("none") ? 0 : + (props.facelighting_is ("flat") ? + (has_face_normals ? 1 : 0) : + (has_vertex_normals ? 2 : 0))); + int fa_mode = (props.facealpha_is_double () ? 0 : + (props.facealpha_is ("flat") ? 1 : 2)); + int ec_mode = (props.edgecolor_is_rgb () ? 0 : + (props.edgecolor_is ("flat") ? 1 : + (props.edgecolor_is ("interp") ? 2 : -1))); + int el_mode = (props.edgelighting_is ("none") ? 0 : + (props.edgelighting_is ("flat") ? + (has_face_normals ? 1 : 0) : + (has_vertex_normals ? 2 : 0))); + int ea_mode = (props.edgealpha_is_double () ? 0 : + (props.edgealpha_is ("flat") ? 1 : 2)); + int bfl_mode = (props.backfacelighting_is ("lit") ? 0 : + (props.backfacelighting_is ("reverselit") ? 1 : 2)); + bool do_lighting = props.get_do_lighting (); + + Matrix fcolor = (fc_mode == TEXTURE ? Matrix (1, 3, 1.0) + : props.get_facecolor_rgb ()); + Matrix ecolor = props.get_edgecolor_rgb (); + double fa = 1.0; + + float as = props.get_ambientstrength (); + float ds = props.get_diffusestrength (); + float ss = props.get_specularstrength (); + float se = props.get_specularexponent () * 5; // to fit Matlab + float scr = props.get_specularcolorreflectance (); + float cb[4] = { 0.0, 0.0, 0.0, 1.0 }; + + opengl_texture tex (m_glfcns); + + int i1, i2, j1, j2; + bool x_mat = (x.rows () == z.rows ()); + bool y_mat = (y.columns () == z.columns ()); + + i1 = i2 = j1 = j2 = 0; + + if ((fc_mode > 0 && fc_mode < 3) || ec_mode > 0) + c = props.get_color_data ().array_value (); + + boolMatrix clip (z.dims (), false); + + for (int i = 0; i < zr; i++) + { + if (x_mat) + i1 = i; + + for (int j = 0; j < zc; j++) + { + if (y_mat) + j1 = j; + + clip(i, j) = is_nan_or_inf (x(i1, j), y(i, j1), z(i, j)); + } + } + + if (fa_mode > 0 || ea_mode > 0) + { + // FIXME: implement alphadata conversion + //a = props.get_alpha_data (); + } + + if (fl_mode > 0 || el_mode > 0) + m_glfcns.glMaterialf (LIGHT_MODE, GL_SHININESS, se); + + // FIXME: good candidate for caching, + // transferring pixel data to OpenGL is time consuming. + if (fc_mode == TEXTURE) + tex = opengl_texture::create (m_glfcns, props.get_color_data ()); + + if (draw_all || ! props.facecolor_is ("none")) + { + if (fa_mode == 0) { - int idx = int (f(i,j) - 1); - - Matrix vv (1, 3, 0.0); - Matrix cc; - Matrix vnn (1, 3, 0.0); - Matrix fnn (1, 3, 0.0); - double aa = 1.0; - - vv(0) = v(idx,0); vv(1) = v(idx,1); - if (has_z) - vv(2) = v(idx,2); - if (((fl_mode == FLAT) || (el_mode == FLAT)) && has_face_normals) + fa = props.get_facealpha_double (); + cb[3] = fa; + if (fc_mode == UNIFORM || fc_mode == TEXTURE) { - double dir = 1.0; - if (bfl_mode > 0) - dir = ((fn(i,0) * m_view_vector(0) - + fn(i,1) * m_view_vector(1) - + fn(i,2) * m_view_vector(2) < 0) - ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); - fnn(0) = dir * fn(i,0); - fnn(1) = dir * fn(i,1); - fnn(2) = dir * fn(i,2); + m_glfcns.glColor4d (fcolor(0), fcolor(1), fcolor(2), fa); + if (fl_mode > 0) + { + for (int i = 0; i < 3; i++) + cb[i] = as * fcolor(i); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int i = 0; i < 3; i++) + cb[i] = ds * fcolor(i); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int i = 0; i < 3; i++) + cb[i] = ss * (scr + (1-scr) * fcolor(i)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } } - if ((fl_mode == GOURAUD || el_mode == GOURAUD) && has_vertex_normals) + + if ((fl_mode > 0) && do_lighting) + m_glfcns.glEnable (GL_LIGHTING); + m_glfcns.glShadeModel ((fc_mode == INTERP || fl_mode == GOURAUD) + ? GL_SMOOTH : GL_FLAT); + set_polygon_offset (true, 1.0); + if (fc_mode == TEXTURE) + m_glfcns.glEnable (GL_TEXTURE_2D); + + for (int i = 1; i < zc; i++) { - double dir = 1.0; - if (bfl_mode > 0) - dir = ((vn(idx,0) * m_view_vector(0) - + vn(idx,1) * m_view_vector(1) - + vn(idx,2) * m_view_vector(2) < 0) - ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); - vnn(0) = dir * vn(idx,0); - vnn(1) = dir * vn(idx,1); - vnn(2) = dir * vn(idx,2); + if (y_mat) + { + i1 = i-1; + i2 = i; + } + + for (int j = 1; j < zr; j++) + { + + if (clip(j-1, i-1) || clip(j, i-1) + || clip(j-1, i) || clip(j, i)) + continue; + + if (fc_mode == FLAT) + { + // "flat" only needs color at lower-left vertex + if (! math::isfinite (c(j-1, i-1))) + continue; + } + else if (fc_mode == INTERP) + { + // "interp" needs valid color at all 4 vertices + if (! (math::isfinite (c(j-1, i-1)) + && math::isfinite (c(j, i-1)) + && math::isfinite (c(j-1, i)) + && math::isfinite (c(j, i)))) + continue; + } + + if (x_mat) + { + j1 = j-1; + j2 = j; + } + + m_glfcns.glBegin (GL_QUADS); + + // Vertex 1 + if (fc_mode == TEXTURE) + tex.tex_coord (double (i-1) / (zc-1), + double (j-1) / (zr-1)); + else if (fc_mode > 0) + { + // FIXME: is there a smarter way to do this? + for (int k = 0; k < 3; k++) + cb[k] = c(j-1, i-1, k); + m_glfcns.glColor4fv (cb); + + if (fl_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j-1, i-1, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j-1, i-1, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } + } + if (fl_mode > 0) + set_normal (bfl_mode, (fl_mode == GOURAUD ? vn : fn), + j-1, i-1); + + m_glfcns.glVertex3d (x(j1, i-1), y(j-1, i1), z(j-1, i-1)); + + // Vertex 2 + if (fc_mode == TEXTURE) + tex.tex_coord (double (i) / (zc-1), + double (j-1) / (zr-1)); + else if (fc_mode == INTERP) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j-1, i, k); + m_glfcns.glColor4fv (cb); + + if (fl_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j-1, i, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j-1, i, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } + } + + if (fl_mode == GOURAUD) + set_normal (bfl_mode, vn, j-1, i); + + m_glfcns.glVertex3d (x(j1, i), y(j-1, i2), z(j-1, i)); + + // Vertex 3 + if (fc_mode == TEXTURE) + tex.tex_coord (double (i) / (zc-1), double (j) / (zr-1)); + else if (fc_mode == INTERP) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j, i, k); + m_glfcns.glColor4fv (cb); + + if (fl_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j, i, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j, i, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } + } + if (fl_mode == GOURAUD) + set_normal (bfl_mode, vn, j, i); + + m_glfcns.glVertex3d (x(j2, i), y(j, i2), z(j, i)); + + // Vertex 4 + if (fc_mode == TEXTURE) + tex.tex_coord (double (i-1) / (zc-1), + double (j) / (zr-1)); + else if (fc_mode == INTERP) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j, i-1, k); + m_glfcns.glColor4fv (cb); + + if (fl_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j, i-1, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j, i-1, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } + } + if (fl_mode == GOURAUD) + set_normal (bfl_mode, vn, j, i-1); + + m_glfcns.glVertex3d (x(j2, i-1), y(j, i1), z(j, i-1)); + + m_glfcns.glEnd (); + } } - if (c.numel () > 0) - { - cc.resize (1, 3); - if (has_facecolor) - cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2); - else - cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2); - } - if (fa_mode == 0) - aa = fa; - else if (a.numel () > 0) - { - if (has_facealpha) - aa = a(i); - else - aa = a(idx); - } - - vdata[i+j*fr] - = vertex_data (vv, cc, vnn, fnn, aa, as, ds, ss, se, scr); + + set_polygon_offset (false); + if (fc_mode == TEXTURE) + m_glfcns.glDisable (GL_TEXTURE_2D); + + if ((fl_mode > 0) && do_lighting) + m_glfcns.glDisable (GL_LIGHTING); + } + else + { + // FIXME: implement flat, interp and texturemap transparency } - - if (fl_mode > 0 || el_mode > 0) - m_glfcns.glMaterialf (LIGHT_MODE, GL_SHININESS, se); - - if (draw_all || ! props.facecolor_is ("none")) - { - // FIXME: adapt to double-radio property - if (fa_mode == 0) - { - if (fc_mode == UNIFORM) - { - m_glfcns.glColor4d (fcolor(0), fcolor(1), fcolor(2), fa); - if (fl_mode > 0) - { - float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f };; - - for (int i = 0; i < 3; i++) - cb[i] = as * fcolor(i); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - - for (int i = 0; i < 3; i++) - cb[i] = ds * fcolor(i); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int i = 0; i < 3; i++) - cb[i] = ss * (scr + (1-scr) * fcolor(i)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - } - } - - if ((fl_mode > 0) && do_lighting) - m_glfcns.glEnable (GL_LIGHTING); - - // NOTE: Push filled part of patch backwards to avoid Z-fighting - // with tessellator outline. A value of 1.0 seems to work fine. - // Value can't be too large or the patch will be pushed below the - // axes planes at +2.5. - patch_tessellator tess (this, fc_mode, fl_mode, true, 1.0); - - std::vector::const_iterator it; - octave_idx_type i_start, i_end; - - for (int i = 0; i < nf; i++) - { - if (clip_f(i)) - continue; - - bool is_non_planar = false; - if (props.m_coplanar_last_idx.size () > 0 - && props.m_coplanar_last_idx[i].size () > 1) - { - is_non_planar = true; - it = props.m_coplanar_last_idx[i].end (); - it--; - } - - // loop over planar subsets of face - do - { - if (is_non_planar) - { - i_end = *it; - if (it == props.m_coplanar_last_idx[i].begin ()) - i_start = 0; - else - { - it--; - i_start = *it - 1; - } - } - else - { - i_end = count_f(i) - 1; - i_start = 0; - } - - tess.begin_polygon (true); - tess.begin_contour (); - - // Add vertices in reverse order for Matlab compatibility - for (int j = i_end; j > i_start; j--) - { - vertex_data::vertex_data_rep *vv - = vdata[i+j*fr].get_rep (); - - tess.add_vertex (vv->m_coords.fortran_vec (), vv); - } - - if (count_f(i) > 0) - { - vertex_data::vertex_data_rep *vv = vdata[i].get_rep (); - - if (fc_mode == FLAT) - { - // For "flat" shading, use color of 1st vertex. - Matrix col = vv->m_color; - - if (col.numel () == 3) - { - m_glfcns.glColor4d (col(0), col(1), col(2), fa); - if (fl_mode > 0) - { - float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - - for (int k = 0; k < 3; k++) - cb[k] = (vv->m_ambient * col(k)); - m_glfcns.glMaterialfv (LIGHT_MODE, - GL_AMBIENT, cb); - - for (int k = 0; k < 3; k++) - cb[k] = (vv->m_diffuse * col(k)); - m_glfcns.glMaterialfv (LIGHT_MODE, - GL_DIFFUSE, cb); - - for (int k = 0; k < 3; k++) - cb[k] = vv->m_specular * - (vv->m_specular_color_refl - + (1-vv->m_specular_color_refl) * - col(k)); - m_glfcns.glMaterialfv (LIGHT_MODE, - GL_SPECULAR, cb); - } - } - } - - tess.add_vertex (vv->m_coords.fortran_vec (), vv); - } - - tess.end_contour (); - tess.end_polygon (); - } while (i_start > 0); - } - - if ((fl_mode > 0) && do_lighting) - m_glfcns.glDisable (GL_LIGHTING); - } - else - { - // FIXME: implement flat and interp transparency - } - } - - if (draw_all - || (! props.edgecolor_is ("none") && ! props.linestyle_is ("none"))) - { - // FIXME: adapt to double-radio property - if (props.get_edgealpha_double () == 1) - { - if (ec_mode == UNIFORM) - { - m_glfcns.glColor3dv (ecolor.data ()); - if (el_mode > 0) - { - // edge lighting only uses ambient light - float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); - - for (int i = 0; i < 3; i++) - cb[i] = (as * ecolor(i)); - m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); - } - } - - if ((el_mode > 0) && do_lighting) - m_glfcns.glEnable (GL_LIGHTING); - - double linewidth = props.get_linewidth (); - set_linestyle (props.get_linestyle (), false, linewidth); - set_linewidth (linewidth); - set_linecap ("butt"); - set_linejoin ("miter"); - - // NOTE: patch contour cannot be offset. Offset must occur with - // the filled portion of the patch above. The tessellator uses - // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL - // automatically sets the glType to GL_LINE_LOOP. This primitive is - // not supported by glPolygonOffset which is used to do Z offsets. - patch_tessellator tess (this, ec_mode, el_mode, false); - - for (int i = 0; i < nf; i++) - { - bool is_non_planar = false; - if (props.m_coplanar_last_idx.size () > 0 - && props.m_coplanar_last_idx[i].size () > 1) - is_non_planar = true; - if (clip_f(i) || is_non_planar) - { - // This is an unclosed contour or a non-planar face. - // Draw it as a line. - bool flag = false; - - m_glfcns.glShadeModel ((ec_mode == INTERP - || el_mode == GOURAUD) - ? GL_SMOOTH : GL_FLAT); - - // Add vertices in reverse order for Matlab compatibility - for (int j = count_f(i)-1; j >= 0; j--) - { - if (! clip(int (f(i,j) - 1))) - { - vertex_data::vertex_data_rep *vv - = vdata[i+j*fr].get_rep (); - const Matrix m = vv->m_coords; - if (! flag) - { - flag = true; - m_glfcns.glBegin (GL_LINE_STRIP); - } - if (ec_mode != UNIFORM) - { - Matrix col = vv->m_color; - - if (col.numel () == 3) - m_glfcns.glColor3dv (col.data ()); - } - m_glfcns.glVertex3d (m(0), m(1), m(2)); - } - else if (flag) - { - flag = false; - m_glfcns.glEnd (); - } - } - // Do loop body with vertex N to "close" GL_LINE_STRIP - // from vertex 0 to vertex N. - int j = count_f(i)-1; - if (flag && ! clip(int (f(i,j) - 1))) - { - vertex_data::vertex_data_rep *vv - = vdata[i+j*fr].get_rep (); - const Matrix m = vv->m_coords; - if (ec_mode != UNIFORM) - { - Matrix col = vv->m_color; - - if (col.numel () == 3) - m_glfcns.glColor3dv (col.data ()); - } - m_glfcns.glVertex3d (m(0), m(1), m(2)); - } - - if (flag) + } + + if (! props.edgecolor_is ("none") && ! props.linestyle_is ("none")) + { + if (props.get_edgealpha_double () == 1) + { + cb[3] = 1.0; // edgealpha isn't implemented yet + if (ec_mode == UNIFORM) + { + m_glfcns.glColor3dv (ecolor.data ()); + if (el_mode > 0) + { + for (int i = 0; i < 3; i++) + cb[i] = as * ecolor(i); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int i = 0; i < 3; i++) + cb[i] = ds * ecolor(i); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int i = 0; i < 3; i++) + cb[i] = ss * (scr + (1-scr) * ecolor(i)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } + } + + if ((el_mode > 0) && do_lighting) + m_glfcns.glEnable (GL_LIGHTING); + m_glfcns.glShadeModel ((ec_mode == INTERP || el_mode == GOURAUD) + ? GL_SMOOTH : GL_FLAT); + + set_linestyle (props.get_linestyle (), false, + props.get_linewidth ()); + set_linewidth (props.get_linewidth ()); + set_linecap ("butt"); + set_linejoin ("miter"); + + // Mesh along Y-axis + + if (props.meshstyle_is ("both") || props.meshstyle_is ("column")) + { + for (int i = 0; i < zc; i++) + { + if (y_mat) + { + i1 = i-1; + i2 = i; + } + + for (int j = 1; j < zr; j++) + { + if (clip(j-1, i) || clip(j, i)) + continue; + + if (ec_mode == FLAT) + { + // "flat" only needs color at lower-left vertex + if (! math::isfinite (c(j-1, i))) + continue; + } + else if (ec_mode == INTERP) + { + // "interp" needs valid color at both vertices + if (! (math::isfinite (c(j-1, i)) + && math::isfinite (c(j, i)))) + continue; + } + + if (x_mat) + { + j1 = j-1; + j2 = j; + } + + m_glfcns.glBegin (GL_LINES); + + // Vertex 1 + if (ec_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j-1, i, k); + m_glfcns.glColor3fv (cb); + + if (el_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j-1, i, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j-1, i, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, + cb); + } + } + if (el_mode > 0) + { + if (el_mode == GOURAUD) + set_normal (bfl_mode, vn, j-1, i); + else + set_normal (bfl_mode, fn, j-1, std::min (i, zc-2)); + } + + m_glfcns.glVertex3d (x(j1, i), y(j-1, i2), z(j-1, i)); + + // Vertex 2 + if (ec_mode == INTERP) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j, i, k); + m_glfcns.glColor3fv (cb); + + if (el_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j, i, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j, i, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, + cb); + } + } + if (el_mode == GOURAUD) + set_normal (bfl_mode, vn, j, i); + + m_glfcns.glVertex3d (x(j2, i), y(j, i2), z(j, i)); + m_glfcns.glEnd (); - } - else // Normal edge contour drawn with tessellator - { - tess.begin_polygon (false); - tess.begin_contour (); - - for (int j = count_f(i)-1; j >= 0; j--) - { - vertex_data::vertex_data_rep *vv - = vdata[i+j*fr].get_rep (); - tess.add_vertex (vv->m_coords.fortran_vec (), vv); - } - - tess.end_contour (); - tess.end_polygon (); - } - } - - set_linestyle ("-"); // Disable LineStipple - set_linewidth (0.5f); - - if ((el_mode > 0) && do_lighting) - m_glfcns.glDisable (GL_LIGHTING); - } - else - { - // FIXME: implement transparency - } - } - - if (! 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"); - - 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 ()); - - bool has_markerfacecolor = draw_all || false; - - if ((mecolor.isempty () && ! props.markeredgecolor_is ("none")) - || (mfcolor.isempty () && ! props.markerfacecolor_is ("none"))) - { - Matrix mc = props.get_color_data ().matrix_value (); - - if (mc.rows () == 1) - { - // Single color specifications, we can simplify a little bit - if (mfcolor.isempty () && ! props.markerfacecolor_is ("none")) - mfcolor = mc; - - if (mecolor.isempty () && ! props.markeredgecolor_is ("none")) - mecolor = mc; - } - else - { - if (c.isempty ()) - c = props.get_color_data ().matrix_value (); - has_markerfacecolor = ((c.numel () > 0) - && (c.rows () == f.rows ())); - } - } - - init_marker (props.get_marker (), props.get_markersize (), - props.get_linewidth ()); - - uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40); - uint8_t clip_ok = 0x40; - - for (int i = 0; i < nf; i++) - for (int j = 0; j < count_f(i); j++) + } + } + } + + // Mesh along X-axis + + if (props.meshstyle_is ("both") || props.meshstyle_is ("row")) { - int idx = int (f(i,j) - 1); - - if ((clip_code (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0)) - & clip_mask) != clip_ok) + for (int j = 0; j < zr; j++) + { + if (x_mat) + { + j1 = j-1; + j2 = j; + } + + for (int i = 1; i < zc; i++) + { + if (clip(j, i-1) || clip(j, i)) + continue; + + if (ec_mode == FLAT) + { + // "flat" only needs color at lower-left vertex + if (! math::isfinite (c(j, i-1))) + continue; + } + else if (ec_mode == INTERP) + { + // "interp" needs valid color at both vertices + if (! (math::isfinite (c(j, i-1)) + && math::isfinite (c(j, i)))) + continue; + } + + if (y_mat) + { + i1 = i-1; + i2 = i; + } + + m_glfcns.glBegin (GL_LINES); + + // Vertex 1 + if (ec_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j, i-1, k); + m_glfcns.glColor3fv (cb); + + if (el_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j, i-1, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j, i-1, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, + cb); + } + } + if (el_mode > 0) + { + if (el_mode == GOURAUD) + set_normal (bfl_mode, vn, j, i-1); + else + set_normal (bfl_mode, fn, std::min (j, zr-2), i-1); + } + + m_glfcns.glVertex3d (x(j2, i-1), y(j, i1), z(j, i-1)); + + // Vertex 2 + if (ec_mode == INTERP) + { + for (int k = 0; k < 3; k++) + cb[k] = c(j, i, k); + m_glfcns.glColor3fv (cb); + + if (el_mode > 0) + { + for (int k = 0; k < 3; k++) + cb[k] *= as; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ds * c(j, i, k); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, + cb); + + for (int k = 0; k < 3; k++) + cb[k] = ss * (scr + (1-scr) * c(j, i, k)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, + cb); + } + } + if (el_mode == GOURAUD) + set_normal (bfl_mode, vn, j, i); + + m_glfcns.glVertex3d (x(j2, i), y(j, i2), z(j, i)); + + m_glfcns.glEnd (); + } + } + } + + set_linestyle ("-"); // Disable LineStipple + set_linewidth (0.5f); + + if ((el_mode > 0) && do_lighting) + m_glfcns.glDisable (GL_LIGHTING); + } + else + { + // FIXME: implement transparency + } + } + + if (! props.marker_is ("none") + && ! (props.markeredgecolor_is ("none") + && props.markerfacecolor_is ("none"))) + { + // FIXME: check how transparency should be handled in markers + // FIXME: check what to do with marker facecolor set to auto + // and facecolor set to none. + + bool do_edge = draw_all || ! props.markeredgecolor_is ("none"); + bool do_face = draw_all || ! props.markerfacecolor_is ("none"); + + 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 ()); + Matrix cc (1, 3, 0.0); + + if (mecolor.isempty () && props.markeredgecolor_is ("auto")) + { + mecolor = props.get_edgecolor_rgb (); + do_edge = ! props.edgecolor_is ("none"); + } + + if (mfcolor.isempty () && props.markerfacecolor_is ("auto")) + { + mfcolor = props.get_facecolor_rgb (); + do_face = ! props.facecolor_is ("none"); + } + + if ((mecolor.isempty () || mfcolor.isempty ()) && c.isempty ()) + c = props.get_color_data ().array_value (); + + init_marker (props.get_marker (), props.get_markersize (), + props.get_linewidth ()); + + uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40); + uint8_t clip_ok = 0x40; + + for (int i = 0; i < zc; i++) + { + if (y_mat) + i1 = i; + + for (int j = 0; j < zr; j++) + { + if (x_mat) + j1 = j; + + if ((clip_code (x(j1, i), y(j, i1), z(j, i)) & clip_mask) + != clip_ok) continue; - Matrix cc; - if (c.numel () > 0) + if ((do_edge && mecolor.isempty ()) + || (do_face && mfcolor.isempty ())) { - cc.resize (1, 3); - if (has_markerfacecolor) - cc(0) = c(i,0), cc(1) = c(i,1), cc(2) = c(i,2); - else - cc(0) = c(idx,0), cc(1) = c(idx,1), cc(2) = c(idx,2); + if (! math::isfinite (c(j, i))) + continue; // Skip NaNs in color data + + for (int k = 0; k < 3; k++) + cc(k) = c(j, i, k); } Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor) - : Matrix ()); + : Matrix ()); Matrix fc = (do_face ? (mfcolor.isempty () ? cc : mfcolor) - : Matrix ()); - - draw_marker (v(idx,0), v(idx,1), (has_z ? v(idx,2) : 0), lc, fc); + : Matrix ()); + + draw_marker (x(j1, i), y(j, i1), z(j, i), lc, fc); } - - end_marker (); - } + } + + 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 (); + 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_scatter (const scatter::properties& props) - { +} + +// FIXME: global optimization (rendering, data structures...), +// there is probably a smarter/faster/less-memory-consuming way to do this. +void +opengl_renderer::draw_patch (const patch::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 = m_selecting; - - if (draw_all || (! props.marker_is ("none") - && ! (props.markeredgecolor_is ("none") - && props.markerfacecolor_is ("none")))) + // Do not render if the patch 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 = m_selecting && props.pickableparts_is ("all"); + const Matrix f = props.get_faces ().matrix_value (); + const Matrix v = m_xform.scale (props.get_vertices ().matrix_value ()); + Matrix c; + Matrix a; + double fa = 1.0; + + int nv = v.rows (); + int nf = f.rows (); + int fcmax = f.columns (); + + bool has_z = (v.columns () > 2); + bool has_facecolor = false; + bool has_facealpha = false; + + int fc_mode = ((props.facecolor_is ("none") + || props.facecolor_is_rgb () || draw_all) ? 0 : + (props.facecolor_is ("flat") ? 1 : 2)); + int fl_mode = (props.facelighting_is ("none") ? 0 : + (props.facelighting_is ("flat") ? 1 : 2)); + int fa_mode = (props.facealpha_is_double () ? 0 : + (props.facealpha_is ("flat") ? 1 : 2)); + int ec_mode = ((props.edgecolor_is ("none") + || props.edgecolor_is_rgb ()) ? 0 : + (props.edgecolor_is ("flat") ? 1 : 2)); + int el_mode = (props.edgelighting_is ("none") ? 0 : + (props.edgelighting_is ("flat") ? 1 : 2)); + int ea_mode = (props.edgealpha_is_double () ? 0 : + (props.edgealpha_is ("flat") ? 1 : 2)); + int bfl_mode = (props.backfacelighting_is ("lit") ? 0 : + (props.backfacelighting_is ("reverselit") ? 1 : 2)); + bool do_lighting = props.get_do_lighting (); + + Matrix fcolor = props.get_facecolor_rgb (); + Matrix ecolor = props.get_edgecolor_rgb (); + + float as = props.get_ambientstrength (); + float ds = props.get_diffusestrength (); + float ss = props.get_specularstrength (); + float se = props.get_specularexponent () * 5; // to fit Matlab + float scr = props.get_specularcolorreflectance (); + + const Matrix vn = props.get_vertexnormals ().matrix_value (); + bool has_vertex_normals = (vn.rows () == nv); + const Matrix fn = props.get_facenormals ().matrix_value (); + bool has_face_normals = (fn.rows () == nf); + + boolMatrix clip (1, nv, false); + + if (has_z) + for (int i = 0; i < nv; i++) + clip(i) = is_nan_or_inf (v(i, 0), v(i, 1), v(i, 2)); + else + for (int i = 0; i < nv; i++) + clip(i) = is_nan_or_inf (v(i, 0), v(i, 1), 0); + + boolMatrix clip_f (1, nf, false); + Array count_f (dim_vector (nf, 1), 0); + + for (int i = 0; i < nf; i++) + { + bool fclip = false; + int count = 0; + + for (int j = 0; j < fcmax && ! math::isnan (f(i, j)); j++, count++) + fclip = (fclip || clip(int (f(i, j) - 1))); + + clip_f(i) = fclip; + count_f(i) = count; + } + + if (draw_all || fc_mode > 0 || ec_mode > 0) + { + if (draw_all) + c = Matrix (1, 3, 0.0); + else + c = props.get_color_data ().matrix_value (); + + if (c.rows () == 1) + { + // Single color specifications, we can simplify a little bit + + if (draw_all || fc_mode > 0) + { + fcolor = c; + fc_mode = UNIFORM; + } + + if (draw_all || ec_mode > 0) + { + ecolor = c; + ec_mode = UNIFORM; + } + + c = Matrix (); + } + else + has_facecolor = ((c.numel () > 0) && (c.rows () == f.rows ())); + } + + if (fa_mode > 0 || ea_mode > 0) + { + // FIXME: retrieve alpha data from patch object + //a = props.get_alpha_data (); + has_facealpha = ((a.numel () > 0) && (a.rows () == f.rows ())); + } + + if (fa_mode == 0) + fa = props.get_facealpha_double (); + + octave_idx_type fr = f.rows (); + std::vector vdata (f.numel ()); + + for (int i = 0; i < nf; i++) + for (int j = 0; j < count_f(i); j++) { - 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")) + int idx = int (f(i, j) - 1); + + Matrix vv (1, 3, 0.0); + Matrix cc; + Matrix vnn (1, 3, 0.0); + Matrix fnn (1, 3, 0.0); + double aa = 1.0; + + vv(0) = v(idx, 0); vv(1) = v(idx, 1); + if (has_z) + vv(2) = v(idx, 2); + if (((fl_mode == FLAT) || (el_mode == FLAT)) && has_face_normals) + { + double dir = 1.0; + if (bfl_mode > 0) + dir = ((fn(i, 0) * m_view_vector(0) + + fn(i, 1) * m_view_vector(1) + + fn(i, 2) * m_view_vector(2) < 0) + ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); + fnn(0) = dir * fn(i, 0); + fnn(1) = dir * fn(i, 1); + fnn(2) = dir * fn(i, 2); + } + if ((fl_mode == GOURAUD || el_mode == GOURAUD) && has_vertex_normals) + { + double dir = 1.0; + if (bfl_mode > 0) + dir = ((vn(idx, 0) * m_view_vector(0) + + vn(idx, 1) * m_view_vector(1) + + vn(idx, 2) * m_view_vector(2) < 0) + ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); + vnn(0) = dir * vn(idx, 0); + vnn(1) = dir * vn(idx, 1); + vnn(2) = dir * vn(idx, 2); + } + if (c.numel () > 0) + { + cc.resize (1, 3); + if (has_facecolor) + cc(0) = c(i, 0), cc(1) = c(i, 1), cc(2) = c(i, 2); + else + cc(0) = c(idx, 0), cc(1) = c(idx, 1), cc(2) = c(idx, 2); + } + if (fa_mode == 0) + aa = fa; + else if (a.numel () > 0) { - gh_manager& gh_mgr = __get_gh_manager__ (); - graphics_object go = gh_mgr.get_object (props.get___myhandle__ ()); - graphics_object ax = go.get_ancestor ("axes"); - const axes::properties& ax_props - = dynamic_cast (ax.get_properties ()); - - mfcolor = ax_props.get_color ().matrix_value (); + if (has_facealpha) + aa = a(i); + else + aa = a(idx); } - 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 ()) + vdata[i+j*fr] + = vertex_data (vv, cc, vnn, fnn, aa, as, ds, ss, se, scr); + } + + if (fl_mode > 0 || el_mode > 0) + m_glfcns.glMaterialf (LIGHT_MODE, GL_SHININESS, se); + + if (draw_all || ! props.facecolor_is ("none")) + { + // FIXME: adapt to double-radio property + if (fa_mode == 0) + { + if (fc_mode == UNIFORM) + { + m_glfcns.glColor4d (fcolor(0), fcolor(1), fcolor(2), fa); + if (fl_mode > 0) + { + float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f };; + + for (int i = 0; i < 3; i++) + cb[i] = as * fcolor(i); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + + for (int i = 0; i < 3; i++) + cb[i] = ds * fcolor(i); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int i = 0; i < 3; i++) + cb[i] = ss * (scr + (1-scr) * fcolor(i)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + } + } + + if ((fl_mode > 0) && do_lighting) + m_glfcns.glEnable (GL_LIGHTING); + + // NOTE: Push filled part of patch backwards to avoid Z-fighting + // with tessellator outline. A value of 1.0 seems to work fine. + // Value can't be too large or the patch will be pushed below the + // axes planes at +2.5. + patch_tessellator tess (this, fc_mode, fl_mode, true, 1.0); + + std::vector::const_iterator it; + octave_idx_type i_start, i_end; + + for (int i = 0; i < nf; i++) + { + if (clip_f(i)) + continue; + + bool is_non_planar = false; + if (props.m_coplanar_last_idx.size () > 0 + && props.m_coplanar_last_idx[i].size () > 1) + { + is_non_planar = true; + it = props.m_coplanar_last_idx[i].end (); + it--; + } + + // loop over planar subsets of face + do + { + if (is_non_planar) + { + i_end = *it; + if (it == props.m_coplanar_last_idx[i].begin ()) + i_start = 0; + else + { + it--; + i_start = *it - 1; + } + } + else + { + i_end = count_f(i) - 1; + i_start = 0; + } + + tess.begin_polygon (true); + tess.begin_contour (); + + // Add vertices in reverse order for Matlab compatibility + for (int j = i_end; j > i_start; j--) + { + vertex_data::vertex_data_rep *vv + = vdata[i+j*fr].get_rep (); + + tess.add_vertex (vv->m_coords.fortran_vec (), vv); + } + + if (count_f(i) > 0) + { + vertex_data::vertex_data_rep *vv = vdata[i].get_rep (); + + if (fc_mode == FLAT) + { + // For "flat" shading, use color of 1st vertex. + Matrix col = vv->m_color; + + if (col.numel () == 3) + { + m_glfcns.glColor4d (col(0), col(1), col(2), fa); + if (fl_mode > 0) + { + float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + + for (int k = 0; k < 3; k++) + cb[k] = (vv->m_ambient * col(k)); + m_glfcns.glMaterialfv (LIGHT_MODE, + GL_AMBIENT, cb); + + for (int k = 0; k < 3; k++) + cb[k] = (vv->m_diffuse * col(k)); + m_glfcns.glMaterialfv (LIGHT_MODE, + GL_DIFFUSE, cb); + + for (int k = 0; k < 3; k++) + cb[k] = vv->m_specular * + (vv->m_specular_color_refl + + (1-vv->m_specular_color_refl) * + col(k)); + m_glfcns.glMaterialfv (LIGHT_MODE, + GL_SPECULAR, cb); + } + } + } + + tess.add_vertex (vv->m_coords.fortran_vec (), vv); + } + + tess.end_contour (); + tess.end_polygon (); + } + while (i_start > 0); + } + + if ((fl_mode > 0) && do_lighting) + m_glfcns.glDisable (GL_LIGHTING); + } + else + { + // FIXME: implement flat and interp transparency + } + } + + if (draw_all + || (! props.edgecolor_is ("none") && ! props.linestyle_is ("none"))) + { + // FIXME: adapt to double-radio property + if (props.get_edgealpha_double () == 1) + { + if (ec_mode == UNIFORM) + { + m_glfcns.glColor3dv (ecolor.data ()); + if (el_mode > 0) + { + // edge lighting only uses ambient light + float cb[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + m_glfcns.glMaterialfv (LIGHT_MODE, GL_SPECULAR, cb); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_DIFFUSE, cb); + + for (int i = 0; i < 3; i++) + cb[i] = (as * ecolor(i)); + m_glfcns.glMaterialfv (LIGHT_MODE, GL_AMBIENT, cb); + } + } + + if ((el_mode > 0) && do_lighting) + m_glfcns.glEnable (GL_LIGHTING); + + double linewidth = props.get_linewidth (); + set_linestyle (props.get_linestyle (), false, linewidth); + set_linewidth (linewidth); + set_linecap ("butt"); + set_linejoin ("miter"); + + // NOTE: patch contour cannot be offset. Offset must occur with + // the filled portion of the patch above. The tessellator uses + // GLU_TESS_BOUNDARY_ONLY to get the outline of the patch and OpenGL + // automatically sets the glType to GL_LINE_LOOP. This primitive is + // not supported by glPolygonOffset which is used to do Z offsets. + patch_tessellator tess (this, ec_mode, el_mode, false); + + for (int i = 0; i < nf; i++) + { + bool is_non_planar = false; + if (props.m_coplanar_last_idx.size () > 0 + && props.m_coplanar_last_idx[i].size () > 1) + is_non_planar = true; + if (clip_f(i) || is_non_planar) + { + // This is an unclosed contour or a non-planar face. + // Draw it as a line. + bool flag = false; + + m_glfcns.glShadeModel ((ec_mode == INTERP + || el_mode == GOURAUD) + ? GL_SMOOTH : GL_FLAT); + + // Add vertices in reverse order for Matlab compatibility + for (int j = count_f(i)-1; j >= 0; j--) + { + if (! clip(int (f(i, j) - 1))) + { + vertex_data::vertex_data_rep *vv + = vdata[i+j*fr].get_rep (); + const Matrix m = vv->m_coords; + if (! flag) + { + flag = true; + m_glfcns.glBegin (GL_LINE_STRIP); + } + if (ec_mode != UNIFORM) + { + Matrix col = vv->m_color; + + if (col.numel () == 3) + m_glfcns.glColor3dv (col.data ()); + } + m_glfcns.glVertex3d (m(0), m(1), m(2)); + } + else if (flag) + { + flag = false; + m_glfcns.glEnd (); + } + } + // Do loop body with vertex N to "close" GL_LINE_STRIP + // from vertex 0 to vertex N. + int j = count_f(i)-1; + if (flag && ! clip(int (f(i, j) - 1))) + { + vertex_data::vertex_data_rep *vv + = vdata[i+j*fr].get_rep (); + const Matrix m = vv->m_coords; + if (ec_mode != UNIFORM) + { + Matrix col = vv->m_color; + + if (col.numel () == 3) + m_glfcns.glColor3dv (col.data ()); + } + m_glfcns.glVertex3d (m(0), m(1), m(2)); + } + + if (flag) + m_glfcns.glEnd (); + } + else // Normal edge contour drawn with tessellator + { + tess.begin_polygon (false); + tess.begin_contour (); + + for (int j = count_f(i)-1; j >= 0; j--) + { + vertex_data::vertex_data_rep *vv + = vdata[i+j*fr].get_rep (); + tess.add_vertex (vv->m_coords.fortran_vec (), vv); + } + + tess.end_contour (); + tess.end_polygon (); + } + } + + set_linestyle ("-"); // Disable LineStipple + set_linewidth (0.5f); + + if ((el_mode > 0) && do_lighting) + m_glfcns.glDisable (GL_LIGHTING); + } + else + { + // FIXME: implement transparency + } + } + + if (! 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"); + + 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 ()); + + bool has_markerfacecolor = draw_all || false; + + if ((mecolor.isempty () && ! props.markeredgecolor_is ("none")) + || (mfcolor.isempty () && ! props.markerfacecolor_is ("none"))) + { + Matrix mc = props.get_color_data ().matrix_value (); + + if (mc.rows () == 1) + { + // Single color specifications, we can simplify a little bit + if (mfcolor.isempty () && ! props.markerfacecolor_is ("none")) + mfcolor = mc; + + if (mecolor.isempty () && ! props.markeredgecolor_is ("none")) + mecolor = mc; + } + else + { + if (c.isempty ()) + c = props.get_color_data ().matrix_value (); + has_markerfacecolor = ((c.numel () > 0) + && (c.rows () == f.rows ())); + } + } + + init_marker (props.get_marker (), props.get_markersize (), + props.get_linewidth ()); + + uint8_t clip_mask = (props.is_clipping () ? 0x7F : 0x40); + uint8_t clip_ok = 0x40; + + for (int i = 0; i < nf; i++) + for (int j = 0; j < count_f(i); j++) { - if (c.rows () == 1) - cc = c; - else + int idx = int (f(i, j) - 1); + + if ((clip_code (v(idx, 0), v(idx, 1), (has_z ? v(idx, 2) : 0)) + & clip_mask) != clip_ok) + continue; + + Matrix cc; + if (c.numel () > 0) { 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); + if (has_markerfacecolor) + cc(0) = c(i, 0), cc(1) = c(i, 1), cc(2) = c(i, 2); + else + cc(0) = c(idx, 0), cc(1) = c(idx, 1), cc(2) = c(idx, 2); } Matrix lc = (do_edge ? (mecolor.isempty () ? cc : mecolor) - : Matrix ()); + : 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); + : Matrix ()); + + draw_marker (v(idx, 0), v(idx, 1), (has_z ? v(idx, 2) : 0), lc, fc); } - end_marker (); - } + 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) - - // enable light source - m_glfcns.glEnable (m_current_light); - - // light position - float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,infinite/local - Matrix lpos = props.get_position ().matrix_value (); - for (int i = 0; i < 3; i++) - pos[i] = lpos(i); - if (props.style_is ("local")) - pos[3] = 1; - m_glfcns.glLightfv (m_current_light, GL_POSITION, pos); - - // light color - float col[4] = { 1, 1, 1, 1 }; // R,G,B,ALPHA (the latter has no meaning) - Matrix lcolor = props.get_color ().matrix_value (); - for (int i = 0; i < 3; i++) - col[i] = lcolor(i); - m_glfcns.glLightfv (m_current_light, GL_DIFFUSE, col); - m_glfcns.glLightfv (m_current_light, GL_SPECULAR, col); - -#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 (); + 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_hggroup (const hggroup::properties& props) - { - draw (props.get_children ()); - } - - void - opengl_renderer::set_ortho_coordinates (void) - { +} + +void +opengl_renderer::draw_scatter (const scatter::properties& props) +{ #if defined (HAVE_OPENGL) - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glPushMatrix (); - m_glfcns.glLoadIdentity (); - - Matrix vp = get_viewport_scaled (); - m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2); - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glPushMatrix (); - m_glfcns.glLoadIdentity (); + // 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 = m_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 = __get_gh_manager__ (); + graphics_object go = gh_mgr.get_object (props.get___myhandle__ ()); + graphics_object ax = go.get_ancestor ("axes"); + const axes::properties& ax_props + = dynamic_cast (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 - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + 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::restore_previous_coordinates (void) - { +} + +void +opengl_renderer::draw_light (const light::properties& props) +{ #if defined (HAVE_OPENGL) - // Restore previous coordinate system - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glPopMatrix(); - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glPopMatrix(); + // enable light source + m_glfcns.glEnable (m_current_light); + + // light position + float pos[4] = { 0, 0, 0, 0 }; // X,Y,Z,infinite/local + Matrix lpos = props.get_position ().matrix_value (); + for (int i = 0; i < 3; i++) + pos[i] = lpos(i); + if (props.style_is ("local")) + pos[3] = 1; + m_glfcns.glLightfv (m_current_light, GL_POSITION, pos); + + // light color + float col[4] = { 1, 1, 1, 1 }; // R,G,B,ALPHA (the latter has no meaning) + Matrix lcolor = props.get_color ().matrix_value (); + for (int i = 0; i < 3; i++) + col[i] = lcolor(i); + m_glfcns.glLightfv (m_current_light, GL_DIFFUSE, col); + m_glfcns.glLightfv (m_current_light, GL_SPECULAR, col); #else - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + 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_text (const text::properties& props) - { +} + +void +opengl_renderer::draw_hggroup (const hggroup::properties& props) +{ + draw (props.get_children ()); +} + +void +opengl_renderer::set_ortho_coordinates (void) +{ #if defined (HAVE_OPENGL) - if (props.get_string ().isempty () || props.color_is ("none")) - return; - - Matrix pos = m_xform.scale (props.get_data_position ()); - - // Handle clipping manually when drawing text in ortho coordinates - if (! props.is_clipping () - || (clip_code (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0) == 0x40)) - { - set_clipping (false); - - draw_text_background (props); - - set_font (props); - - render_text (props.get_pixels (), props.get_extent_matrix (), - pos(0), pos(1), pos(2), props.get_rotation ()); - - set_clipping (props.is_clipping ()); - } + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glPushMatrix (); + m_glfcns.glLoadIdentity (); + + Matrix vp = get_viewport_scaled (); + m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2); + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glPushMatrix (); + m_glfcns.glLoadIdentity (); #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 (); + // 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::restore_previous_coordinates (void) +{ +#if defined (HAVE_OPENGL) + + // Restore previous coordinate system + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glPopMatrix(); + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glPopMatrix(); + +#else + + // 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_text_background (const text::properties& props, - bool /*do_rotate*/) - { +} + +void +opengl_renderer::draw_text (const text::properties& props) +{ #if defined (HAVE_OPENGL) - Matrix bgcol = props.get_backgroundcolor_rgb (); - Matrix ecol = props.get_edgecolor_rgb (); - - if (bgcol.isempty () && ecol.isempty ()) - return; - - Matrix pos = props.get_data_position (); - ColumnVector pixpos = get_transform ().transform (pos(0), pos(1), - pos(2), true); - - // Save current transform matrices and set orthogonal window coordinates - set_ortho_coordinates (); - - // Translate coordinates so that the text anchor is (0,0) - m_glfcns.glTranslated (pixpos(0), pixpos(1), -pixpos(2)); - - // FIXME: Only multiples of 90° are handled by the text renderer. - // Handle others here. - double rotation = props.get_rotation (); - - m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0); - - double m = points_to_pixels (props.get_margin ()); - const Matrix bbox = props.get_extent_matrix (); - double x0 = bbox (0) / m_devpixratio - m; - double x1 = x0 + bbox(2) / m_devpixratio + 2 * m; - double y0 = -(bbox (1) / m_devpixratio - m); - double y1 = y0 - (bbox(3) / m_devpixratio + 2 * m); - - if (! bgcol.isempty ()) - { - m_glfcns.glColor3f (bgcol(0), bgcol(1), bgcol(2)); - - bool depth_test = m_glfcns.glIsEnabled (GL_DEPTH_TEST); - if (depth_test) - set_polygon_offset (true, 4.0); - - m_glfcns.glBegin (GL_QUADS); - m_glfcns.glVertex2d (x0, y0); - m_glfcns.glVertex2d (x1, y0); - m_glfcns.glVertex2d (x1, y1); - m_glfcns.glVertex2d (x0, y1); - m_glfcns.glEnd (); - - if (depth_test) - set_polygon_offset (false); - } - - if (! ecol.isempty ()) - { - m_glfcns.glColor3f (ecol(0), ecol(1), ecol(2)); - - set_linestyle (props.get_linestyle (), false, props.get_linewidth ()); - set_linewidth (props.get_linewidth ()); - - m_glfcns.glBegin (GL_LINE_STRIP); - m_glfcns.glVertex2d (x0, y0); - m_glfcns.glVertex2d (x1, y0); - m_glfcns.glVertex2d (x1, y1); - m_glfcns.glVertex2d (x0, y1); - m_glfcns.glVertex2d (x0, y0); - m_glfcns.glEnd (); - - set_linestyle ("-"); - } - - restore_previous_coordinates (); + if (props.get_string ().isempty () || props.color_is ("none")) + return; + + Matrix pos = m_xform.scale (props.get_data_position ()); + + // Handle clipping manually when drawing text in ortho coordinates + if (! props.is_clipping () + || (clip_code (pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0) == 0x40)) + { + set_clipping (false); + + draw_text_background (props); + + set_font (props); + + render_text (props.get_pixels (), props.get_extent_matrix (), + pos(0), pos(1), pos(2), props.get_rotation ()); + + set_clipping (props.is_clipping ()); + } #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 (); + 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_image (const image::properties& props) - { +} + +void +opengl_renderer::draw_text_background (const text::properties& props, + bool /*do_rotate*/) +{ #if defined (HAVE_OPENGL) - octave_value cdata = props.get_color_data (); - Matrix x = props.get_xdata ().matrix_value (); - Matrix y = props.get_ydata ().matrix_value (); - - draw_texture_image (cdata, x, y); + Matrix bgcol = props.get_backgroundcolor_rgb (); + Matrix ecol = props.get_edgecolor_rgb (); + + if (bgcol.isempty () && ecol.isempty ()) + return; + + Matrix pos = props.get_data_position (); + ColumnVector pixpos = get_transform ().transform (pos(0), pos(1), + pos(2), true); + + // Save current transform matrices and set orthogonal window coordinates + set_ortho_coordinates (); + + // Translate coordinates so that the text anchor is (0,0) + m_glfcns.glTranslated (pixpos(0), pixpos(1), -pixpos(2)); + + // FIXME: Only multiples of 90° are handled by the text renderer. + // Handle others here. + double rotation = props.get_rotation (); + + m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0); + + double m = points_to_pixels (props.get_margin ()); + const Matrix bbox = props.get_extent_matrix (); + double x0 = bbox (0) / m_devpixratio - m; + double x1 = x0 + bbox(2) / m_devpixratio + 2 * m; + double y0 = -(bbox (1) / m_devpixratio - m); + double y1 = y0 - (bbox(3) / m_devpixratio + 2 * m); + + if (! bgcol.isempty ()) + { + m_glfcns.glColor3f (bgcol(0), bgcol(1), bgcol(2)); + + bool depth_test = m_glfcns.glIsEnabled (GL_DEPTH_TEST); + if (depth_test) + set_polygon_offset (true, 4.0); + + m_glfcns.glBegin (GL_QUADS); + m_glfcns.glVertex2d (x0, y0); + m_glfcns.glVertex2d (x1, y0); + m_glfcns.glVertex2d (x1, y1); + m_glfcns.glVertex2d (x0, y1); + m_glfcns.glEnd (); + + if (depth_test) + set_polygon_offset (false); + } + + if (! ecol.isempty ()) + { + m_glfcns.glColor3f (ecol(0), ecol(1), ecol(2)); + + set_linestyle (props.get_linestyle (), false, props.get_linewidth ()); + set_linewidth (props.get_linewidth ()); + + m_glfcns.glBegin (GL_LINE_STRIP); + m_glfcns.glVertex2d (x0, y0); + m_glfcns.glVertex2d (x1, y0); + m_glfcns.glVertex2d (x1, y1); + m_glfcns.glVertex2d (x0, y1); + m_glfcns.glVertex2d (x0, y0); + m_glfcns.glEnd (); + + set_linestyle ("-"); + } + + restore_previous_coordinates (); #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 (); + 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_texture_image (const octave_value cdata, Matrix x, - Matrix y, bool ortho) - { +} + +void +opengl_renderer::draw_image (const image::properties& props) +{ #if defined (HAVE_OPENGL) - dim_vector dv (cdata.dims ()); - int h = dv(0); - int w = dv(1); - double x0, x1, y0, y1; - - double dx = 1.0; - if (w > 1) - dx = (x(1) - x(0)) / (w - 1); - - x0 = x(0)-dx/2; - x1 = x(1)+dx/2; - - double dy = 1.0; - if (h > 1) - dy = (y(1) - y(0)) / (h - 1); - - y0 = y(0)-dy/2; - y1 = y(1)+dy/2; - - // Expect RGB data - if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4)) - { - opengl_texture tex = opengl_texture::create (m_glfcns, cdata); - if (tex.is_valid ()) - { - m_glfcns.glColor4d (1.0, 1.0, 1.0, 1.0); - - m_glfcns.glEnable (GL_TEXTURE_2D); - - m_glfcns.glBegin (GL_QUADS); - - tex.tex_coord (0.0, 0.0); - if (ortho) - m_glfcns.glVertex2d (x0, y0); - else - m_glfcns.glVertex3d (x0, y0, 0.0); - - tex.tex_coord (1.0, 0.0); - if (ortho) - m_glfcns.glVertex2d (x1, y0); - else - m_glfcns.glVertex3d (x1, y0, 0.0); - - tex.tex_coord (1.0, 1.0); - if (ortho) - m_glfcns.glVertex2d (x1, y1); - else - m_glfcns.glVertex3d (x1, y1, 0.0); - - tex.tex_coord (0.0, 1.0); - if (ortho) - m_glfcns.glVertex2d (x0, y1); - else - m_glfcns.glVertex3d (x0, y1, 0.0); - - m_glfcns.glEnd (); - m_glfcns.glDisable (GL_TEXTURE_2D); - } - } - else - warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)"); + octave_value cdata = props.get_color_data (); + Matrix x = props.get_xdata ().matrix_value (); + Matrix y = props.get_ydata ().matrix_value (); + + draw_texture_image (cdata, x, y); #else - octave_unused_parameter (cdata); - octave_unused_parameter (x); - octave_unused_parameter (y); - octave_unused_parameter (ortho); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + 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 (const Matrix& hlist, bool toplevel) - { - int len = hlist.numel (); - - gh_manager& gh_mgr = __get_gh_manager__ (); - - for (int i = len-1; i >= 0; i--) - { - graphics_object obj = gh_mgr.get_object (hlist(i)); - - if (obj) - draw (obj, toplevel); - } - } - - void - opengl_renderer::set_viewport (int w, int h) - { +} + +void +opengl_renderer::draw_texture_image (const octave_value cdata, Matrix x, + Matrix y, bool ortho) +{ #if defined (HAVE_OPENGL) - m_glfcns.glViewport (0, 0, w, h); + dim_vector dv (cdata.dims ()); + int h = dv(0); + int w = dv(1); + double x0, x1, y0, y1; + + double dx = 1.0; + if (w > 1) + dx = (x(1) - x(0)) / (w - 1); + + x0 = x(0)-dx/2; + x1 = x(1)+dx/2; + + double dy = 1.0; + if (h > 1) + dy = (y(1) - y(0)) / (h - 1); + + y0 = y(0)-dy/2; + y1 = y(1)+dy/2; + + // Expect RGB data + if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4)) + { + opengl_texture tex = opengl_texture::create (m_glfcns, cdata); + if (tex.is_valid ()) + { + m_glfcns.glColor4d (1.0, 1.0, 1.0, 1.0); + + m_glfcns.glEnable (GL_TEXTURE_2D); + + m_glfcns.glBegin (GL_QUADS); + + tex.tex_coord (0.0, 0.0); + if (ortho) + m_glfcns.glVertex2d (x0, y0); + else + m_glfcns.glVertex3d (x0, y0, 0.0); + + tex.tex_coord (1.0, 0.0); + if (ortho) + m_glfcns.glVertex2d (x1, y0); + else + m_glfcns.glVertex3d (x1, y0, 0.0); + + tex.tex_coord (1.0, 1.0); + if (ortho) + m_glfcns.glVertex2d (x1, y1); + else + m_glfcns.glVertex3d (x1, y1, 0.0); + + tex.tex_coord (0.0, 1.0); + if (ortho) + m_glfcns.glVertex2d (x0, y1); + else + m_glfcns.glVertex3d (x0, y1, 0.0); + + m_glfcns.glEnd (); + m_glfcns.glDisable (GL_TEXTURE_2D); + } + } + else + warning ("opengl_renderer: invalid image size (expected MxNx3 or MxN)"); #else - octave_unused_parameter (w); - octave_unused_parameter (h); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (cdata); + octave_unused_parameter (x); + octave_unused_parameter (y); + octave_unused_parameter (ortho); + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); #endif - } - - Matrix - opengl_renderer::get_viewport_scaled (void) const - { - Matrix retval (1, 4, 0.0); +} + +void opengl_renderer::draw (const Matrix& hlist, bool toplevel) +{ + int len = hlist.numel (); + + gh_manager& gh_mgr = __get_gh_manager__ (); + + for (int i = len-1; i >= 0; i--) + { + graphics_object obj = gh_mgr.get_object (hlist(i)); + + if (obj) + draw (obj, toplevel); + } +} + +void +opengl_renderer::set_viewport (int w, int h) +{ +#if defined (HAVE_OPENGL) + + m_glfcns.glViewport (0, 0, w, h); + +#else + + octave_unused_parameter (w); + octave_unused_parameter (h); + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); + +#endif +} + +Matrix +opengl_renderer::get_viewport_scaled (void) const +{ + Matrix retval (1, 4, 0.0); #if defined (HAVE_OPENGL) #if defined (HAVE_FRAMEWORK_OPENGL) - GLint vp[4]; + GLint vp[4]; #else - int vp[4]; + int vp[4]; #endif - m_glfcns.glGetIntegerv (GL_VIEWPORT, vp); - - for (int i = 0; i < 4; i++) - retval(i) = static_cast (vp[i]) / m_devpixratio; + m_glfcns.glGetIntegerv (GL_VIEWPORT, vp); + + for (int i = 0; i < 4; i++) + retval(i) = static_cast (vp[i]) / m_devpixratio; #else - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); #endif - return retval; - } - - void - opengl_renderer::set_color (const Matrix& c) - { + return retval; +} + +void +opengl_renderer::set_color (const Matrix& c) +{ #if defined (HAVE_OPENGL) - m_glfcns.glColor3dv (c.data ()); - - if (! c.isempty ()) - m_txt_renderer.set_color (c); + m_glfcns.glColor3dv (c.data ()); + + if (! c.isempty ()) + m_txt_renderer.set_color (c); #else - octave_unused_parameter (c); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (c); + + // 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::set_font (const base_properties& props) - { - bool do_anti_alias = props.get ("fontsmoothing").string_value () == "on"; - m_txt_renderer.set_anti_aliasing (do_anti_alias); - m_txt_renderer.set_font (props.get ("fontname").string_value (), - props.get ("fontweight").string_value (), - props.get ("fontangle").string_value (), - props.get ("__fontsize_points__").double_value () - * m_devpixratio); - } - - void - opengl_renderer::set_polygon_offset (bool on, float offset) - { +} + +void +opengl_renderer::set_font (const base_properties& props) +{ + bool do_anti_alias = props.get ("fontsmoothing").string_value () == "on"; + m_txt_renderer.set_anti_aliasing (do_anti_alias); + m_txt_renderer.set_font (props.get ("fontname").string_value (), + props.get ("fontweight").string_value (), + props.get ("fontangle").string_value (), + props.get ("__fontsize_points__").double_value () + * m_devpixratio); +} + +void +opengl_renderer::set_polygon_offset (bool on, float offset) +{ #if defined (HAVE_OPENGL) - if (on) - { - m_glfcns.glEnable (GL_POLYGON_OFFSET_FILL); - m_glfcns.glEnable (GL_POLYGON_OFFSET_LINE); - m_glfcns.glPolygonOffset (offset, offset); - } - else - { - m_glfcns.glDisable (GL_POLYGON_OFFSET_FILL); - m_glfcns.glDisable (GL_POLYGON_OFFSET_LINE); - } + if (on) + { + m_glfcns.glEnable (GL_POLYGON_OFFSET_FILL); + m_glfcns.glEnable (GL_POLYGON_OFFSET_LINE); + m_glfcns.glPolygonOffset (offset, offset); + } + else + { + m_glfcns.glDisable (GL_POLYGON_OFFSET_FILL); + m_glfcns.glDisable (GL_POLYGON_OFFSET_LINE); + } #else - octave_unused_parameter (on); - octave_unused_parameter (offset); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (on); + octave_unused_parameter (offset); + + // 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::set_linewidth (float w) - { +} + +void +opengl_renderer::set_linewidth (float w) +{ #if defined (HAVE_OPENGL) - // Measure LineWidth in points. See bug #53056. - m_glfcns.glLineWidth (points_to_pixels (w) * m_devpixratio); + // Measure LineWidth in points. See bug #53056. + m_glfcns.glLineWidth (points_to_pixels (w) * m_devpixratio); #else - octave_unused_parameter (w); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (w); + + // 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::set_linestyle (const std::string& s, bool use_stipple, - double linewidth) - { +} + +void +opengl_renderer::set_linestyle (const std::string& s, bool use_stipple, + double linewidth) +{ #if defined (HAVE_OPENGL) - // Measure LineWidth in points. See bug #53056. - int factor = math::round (points_to_pixels (linewidth) * m_devpixratio); - if (factor < 1) - factor = 1; - - uint16_t pattern = 0xFFFF; - - bool solid = false; - - if (s == "-") - solid = true; - else if (s == ":") - { - if (factor > 1) - pattern = 0x5555; - else - pattern = 0x1111; - } - else if (s == "--") - { - if (factor > 1) - pattern = 0x0F0F; - else - pattern = 0x01FF; - } - else if (s == "-.") - { - if (factor > 1) - pattern = 0x6F6F; - else - pattern = 0x18FF; - } - else - pattern = 0x0000; - - m_glfcns.glLineStipple (factor, pattern); - - if (solid && ! use_stipple) - m_glfcns.glDisable (GL_LINE_STIPPLE); - else - m_glfcns.glEnable (GL_LINE_STIPPLE); + // Measure LineWidth in points. See bug #53056. + int factor = math::round (points_to_pixels (linewidth) * m_devpixratio); + if (factor < 1) + factor = 1; + + uint16_t pattern = 0xFFFF; + + bool solid = false; + + if (s == "-") + solid = true; + else if (s == ":") + { + if (factor > 1) + pattern = 0x5555; + else + pattern = 0x1111; + } + else if (s == "--") + { + if (factor > 1) + pattern = 0x0F0F; + else + pattern = 0x01FF; + } + else if (s == "-.") + { + if (factor > 1) + pattern = 0x6F6F; + else + pattern = 0x18FF; + } + else + pattern = 0x0000; + + m_glfcns.glLineStipple (factor, pattern); + + if (solid && ! use_stipple) + m_glfcns.glDisable (GL_LINE_STIPPLE); + else + m_glfcns.glEnable (GL_LINE_STIPPLE); #else - octave_unused_parameter (s); - octave_unused_parameter (use_stipple); - octave_unused_parameter (linewidth); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (s); + octave_unused_parameter (use_stipple); + octave_unused_parameter (linewidth); + + // 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::set_clipbox (double x1, double x2, double y1, double y2, - double z1, double z2) - { +} + +void +opengl_renderer::set_clipbox (double x1, double x2, double y1, double y2, + double z1, double z2) +{ #if defined (HAVE_OPENGL) - double dx = (x2-x1); - double dy = (y2-y1); - double dz = (z2-z1); - - x1 -= 0.001*dx; x2 += 0.001*dx; - y1 -= 0.001*dy; y2 += 0.001*dy; - z1 -= 0.001*dz; z2 += 0.001*dz; - - ColumnVector p (4, 0.0); - - p(0) = -1; p(3) = x2; - m_glfcns.glClipPlane (GL_CLIP_PLANE0, p.data ()); - p(0) = 1; p(3) = -x1; - m_glfcns.glClipPlane (GL_CLIP_PLANE1, p.data ()); - p(0) = 0; p(1) = -1; p(3) = y2; - m_glfcns.glClipPlane (GL_CLIP_PLANE2, p.data ()); - p(1) = 1; p(3) = -y1; - m_glfcns.glClipPlane (GL_CLIP_PLANE3, p.data ()); - p(1) = 0; p(2) = -1; p(3) = z2; - m_glfcns.glClipPlane (GL_CLIP_PLANE4, p.data ()); - p(2) = 1; p(3) = -z1; - m_glfcns.glClipPlane (GL_CLIP_PLANE5, p.data ()); - - m_xmin = x1; m_xmax = x2; - m_ymin = y1; m_ymax = y2; - m_zmin = z1; m_zmax = z2; + double dx = (x2-x1); + double dy = (y2-y1); + double dz = (z2-z1); + + x1 -= 0.001*dx; x2 += 0.001*dx; + y1 -= 0.001*dy; y2 += 0.001*dy; + z1 -= 0.001*dz; z2 += 0.001*dz; + + ColumnVector p (4, 0.0); + + p(0) = -1; p(3) = x2; + m_glfcns.glClipPlane (GL_CLIP_PLANE0, p.data ()); + p(0) = 1; p(3) = -x1; + m_glfcns.glClipPlane (GL_CLIP_PLANE1, p.data ()); + p(0) = 0; p(1) = -1; p(3) = y2; + m_glfcns.glClipPlane (GL_CLIP_PLANE2, p.data ()); + p(1) = 1; p(3) = -y1; + m_glfcns.glClipPlane (GL_CLIP_PLANE3, p.data ()); + p(1) = 0; p(2) = -1; p(3) = z2; + m_glfcns.glClipPlane (GL_CLIP_PLANE4, p.data ()); + p(2) = 1; p(3) = -z1; + m_glfcns.glClipPlane (GL_CLIP_PLANE5, p.data ()); + + m_xmin = x1; m_xmax = x2; + m_ymin = y1; m_ymax = y2; + m_zmin = z1; m_zmax = z2; #else - octave_unused_parameter (x1); - octave_unused_parameter (x2); - octave_unused_parameter (y1); - octave_unused_parameter (y2); - octave_unused_parameter (z1); - octave_unused_parameter (z2); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (x1); + octave_unused_parameter (x2); + octave_unused_parameter (y1); + octave_unused_parameter (y2); + octave_unused_parameter (z1); + octave_unused_parameter (z2); + + // 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::set_clipping (bool enable) - { +} + +void +opengl_renderer::set_clipping (bool enable) +{ #if defined (HAVE_OPENGL) - bool has_clipping = (m_glfcns.glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE); - - if (enable != has_clipping) - { - if (enable) - for (int i = 0; i < 6; i++) - m_glfcns.glEnable (GL_CLIP_PLANE0+i); - else - for (int i = 0; i < 6; i++) - m_glfcns.glDisable (GL_CLIP_PLANE0+i); - } + bool has_clipping = (m_glfcns.glIsEnabled (GL_CLIP_PLANE0) == GL_TRUE); + + if (enable != has_clipping) + { + if (enable) + for (int i = 0; i < 6; i++) + m_glfcns.glEnable (GL_CLIP_PLANE0+i); + else + for (int i = 0; i < 6; i++) + m_glfcns.glDisable (GL_CLIP_PLANE0+i); + } #else - octave_unused_parameter (enable); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (enable); + + // 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::init_marker (const std::string& m, double size, float width) - { +} + +void +opengl_renderer::init_marker (const std::string& m, double size, float width) +{ #if defined (HAVE_OPENGL) - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glPushMatrix (); - m_glfcns.glLoadIdentity (); - - Matrix vp = get_viewport_scaled (); - m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2); - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glPushMatrix (); - - set_clipping (false); - set_linewidth (width); - - m_marker_id = make_marker_list (m, size, false); - m_filled_marker_id = make_marker_list (m, size, true); + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glPushMatrix (); + m_glfcns.glLoadIdentity (); + + Matrix vp = get_viewport_scaled (); + m_glfcns.glOrtho (0, vp(2), vp(3), 0, m_xZ1, m_xZ2); + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glPushMatrix (); + + set_clipping (false); + set_linewidth (width); + + m_marker_id = make_marker_list (m, size, false); + m_filled_marker_id = make_marker_list (m, size, true); #else - octave_unused_parameter (m); - octave_unused_parameter (size); - octave_unused_parameter (width); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (m); + octave_unused_parameter (size); + octave_unused_parameter (width); + + // 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::change_marker (const std::string& m, double size) - { +} + +void +opengl_renderer::change_marker (const std::string& m, double size) +{ #if defined (HAVE_OPENGL) - m_marker_id = make_marker_list (m, size, false); - m_filled_marker_id = make_marker_list (m, size, true); + m_marker_id = make_marker_list (m, size, false); + m_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 (); + 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) - { +} + +void +opengl_renderer::end_marker (void) +{ #if defined (HAVE_OPENGL) - m_glfcns.glDeleteLists (m_marker_id, 1); - m_glfcns.glDeleteLists (m_filled_marker_id, 1); - - m_glfcns.glMatrixMode (GL_MODELVIEW); - m_glfcns.glPopMatrix (); - m_glfcns.glMatrixMode (GL_PROJECTION); - m_glfcns.glPopMatrix (); - set_linewidth (0.5f); + m_glfcns.glDeleteLists (m_marker_id, 1); + m_glfcns.glDeleteLists (m_filled_marker_id, 1); + + m_glfcns.glMatrixMode (GL_MODELVIEW); + m_glfcns.glPopMatrix (); + m_glfcns.glMatrixMode (GL_PROJECTION); + m_glfcns.glPopMatrix (); + set_linewidth (0.5f); #else - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + // 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_marker (double x, double y, double z, - const Matrix& lc, const Matrix& fc, - const double la, const double fa) - { +} + +void +opengl_renderer::draw_marker (double x, double y, double z, + const Matrix& lc, const Matrix& fc, + const double la, const double fa) +{ #if defined (HAVE_OPENGL) - ColumnVector tmp = m_xform.transform (x, y, z, false); - - m_glfcns.glLoadIdentity (); - m_glfcns.glTranslated (tmp(0), tmp(1), -tmp(2)); - - if (m_filled_marker_id > 0 && fc.numel () > 0) - { - m_glfcns.glColor4d (fc(0), fc(1), fc(2), fa); - set_polygon_offset (true, -1.0); - m_glfcns.glCallList (m_filled_marker_id); - if (lc.numel () > 0) - { - 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); - m_glfcns.glCallList (m_filled_marker_id); - m_glfcns.glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - } - set_polygon_offset (false); - } - else if (m_marker_id > 0 && lc.numel () > 0) - { - m_glfcns.glColor4d (lc(0), lc(1), lc(2), la); - m_glfcns.glCallList (m_marker_id); - } + ColumnVector tmp = m_xform.transform (x, y, z, false); + + m_glfcns.glLoadIdentity (); + m_glfcns.glTranslated (tmp(0), tmp(1), -tmp(2)); + + if (m_filled_marker_id > 0 && fc.numel () > 0) + { + m_glfcns.glColor4d (fc(0), fc(1), fc(2), fa); + set_polygon_offset (true, -1.0); + m_glfcns.glCallList (m_filled_marker_id); + if (lc.numel () > 0) + { + 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); + m_glfcns.glCallList (m_filled_marker_id); + m_glfcns.glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + } + set_polygon_offset (false); + } + else if (m_marker_id > 0 && lc.numel () > 0) + { + m_glfcns.glColor4d (lc(0), lc(1), lc(2), la); + m_glfcns.glCallList (m_marker_id); + } #else - octave_unused_parameter (x); - octave_unused_parameter (y); - 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. - - panic_impossible (); + octave_unused_parameter (x); + octave_unused_parameter (y); + 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. + + panic_impossible (); #endif - } - - void - opengl_renderer::init_maxlights (void) - { +} + +void +opengl_renderer::init_maxlights (void) +{ #if defined (HAVE_OPENGL) - // Check actual maximum number of lights possible - if (m_max_lights == 0) - { - GLint max_lights; - m_glfcns.glGetIntegerv (GL_MAX_LIGHTS, &max_lights); - m_max_lights = max_lights; - } + // Check actual maximum number of lights possible + if (m_max_lights == 0) + { + GLint max_lights; + m_glfcns.glGetIntegerv (GL_MAX_LIGHTS, &max_lights); + m_max_lights = max_lights; + } #else - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); #endif - } - - std::string - opengl_renderer::get_string (unsigned int id) const - { +} + +std::string +opengl_renderer::get_string (unsigned int id) const +{ #if defined (HAVE_OPENGL) - // This is kind of ugly, but glGetString returns a pointer to GLubyte - // and there is no std::string constructor that matches. Is there a - // better way? - - std::ostringstream buf; - - buf << m_glfcns.glGetString (static_cast (id)); - - return std::string (buf.str ()); + // This is kind of ugly, but glGetString returns a pointer to GLubyte + // and there is no std::string constructor that matches. Is there a + // better way? + + std::ostringstream buf; + + buf << m_glfcns.glGetString (static_cast (id)); + + return std::string (buf.str ()); #else - octave_unused_parameter (id); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); - return std::string (); + octave_unused_parameter (id); + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); + return std::string (); #endif - } - - void - opengl_renderer::set_normal (int bfl_mode, const NDArray& n, int j, int i) - { +} + +void +opengl_renderer::set_normal (int bfl_mode, const NDArray& n, int j, int i) +{ #if defined (HAVE_OPENGL) - double x = n(j,i,0); - double y = n(j,i,1); - double z = n(j,i,2); - - double d = sqrt (x*x + y*y + z*z); - - double dir = 1.0; - - if (bfl_mode > 0) - dir = ((x*m_view_vector(0) + y*m_view_vector(1) + z*m_view_vector(2) < 0) - ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); - - m_glfcns.glNormal3d (dir*x/d, dir*y/d, dir*z/d); + double x = n(j, i, 0); + double y = n(j, i, 1); + double z = n(j, i, 2); + + double d = sqrt (x*x + y*y + z*z); + + double dir = 1.0; + + if (bfl_mode > 0) + dir = ((x*m_view_vector(0) + y*m_view_vector(1) + z*m_view_vector(2) < 0) + ? ((bfl_mode > 1) ? 0.0 : -1.0) : 1.0); + + m_glfcns.glNormal3d (dir*x/d, dir*y/d, dir*z/d); #else - octave_unused_parameter (bfl_mode); - octave_unused_parameter (n); - octave_unused_parameter (j); - octave_unused_parameter (i); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (bfl_mode); + octave_unused_parameter (n); + octave_unused_parameter (j); + octave_unused_parameter (i); + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); #endif - } - - double - opengl_renderer::points_to_pixels (const double val) const - { - gh_manager& gh_mgr = __get_gh_manager__ (); - - // FIXME: Does making this static cause problems if figure is moved to a - // 2nd monitor with a different value for "screenpixelsperinch"? - static const double pix_per_pts = - gh_mgr.get_object (0).get ("screenpixelsperinch").double_value () / 72.0; - - double retval = val; - - if (! m_printing) - retval *= pix_per_pts; - - return retval; - } - - unsigned int - opengl_renderer::make_marker_list (const std::string& marker, double size, - bool filled) const - { +} + +double +opengl_renderer::points_to_pixels (const double val) const +{ + gh_manager& gh_mgr = __get_gh_manager__ (); + + // FIXME: Does making this static cause problems if figure is moved to a + // 2nd monitor with a different value for "screenpixelsperinch"? + static const double pix_per_pts = + gh_mgr.get_object (0).get ("screenpixelsperinch").double_value () / 72.0; + + double retval = val; + + if (! m_printing) + retval *= pix_per_pts; + + return retval; +} + +unsigned int +opengl_renderer::make_marker_list (const std::string& marker, double size, + bool filled) const +{ #if defined (HAVE_OPENGL) - char c = marker[0]; - - if (filled && (c == '+' || c == 'x' || c == '*' || c == '.' - || c == '|' || c == '_')) - return 0; - - unsigned int ID = m_glfcns.glGenLists (1); - - // FIXME: See bug #53056 (measure LineWidth in points). - double sz = points_to_pixels (size); - - // constants for the * marker - const double sqrt2d4 = 0.35355339059327; - double tt = sz*sqrt2d4; - - m_glfcns.glNewList (ID, GL_COMPILE); - - switch (marker[0]) + char c = marker[0]; + + if (filled && (c == '+' || c == 'x' || c == '*' || c == '.' + || c == '|' || c == '_')) + return 0; + + unsigned int ID = m_glfcns.glGenLists (1); + + // FIXME: See bug #53056 (measure LineWidth in points). + double sz = points_to_pixels (size); + + // constants for the * marker + const double sqrt2d4 = 0.35355339059327; + double tt = sz*sqrt2d4; + + m_glfcns.glNewList (ID, GL_COMPILE); + + switch (marker[0]) + { + case '+': + m_glfcns.glBegin (GL_LINES); + m_glfcns.glVertex2d (-sz/2, 0); + m_glfcns.glVertex2d (sz/2, 0); + m_glfcns.glVertex2d (0, -sz/2); + m_glfcns.glVertex2d (0, sz/2); + m_glfcns.glEnd (); + break; + case '|': + m_glfcns.glBegin (GL_LINES); + m_glfcns.glVertex2d (0, -sz/2); + m_glfcns.glVertex2d (0, sz/2); + m_glfcns.glEnd (); + break; + case '_': + m_glfcns.glBegin (GL_LINES); + m_glfcns.glVertex2d (-sz/2, 0); + m_glfcns.glVertex2d (sz/2, 0); + m_glfcns.glEnd (); + break; + case 'x': + m_glfcns.glBegin (GL_LINES); + m_glfcns.glVertex2d (-sz/2, -sz/2); + m_glfcns.glVertex2d (sz/2, sz/2); + m_glfcns.glVertex2d (-sz/2, sz/2); + m_glfcns.glVertex2d (sz/2, -sz/2); + m_glfcns.glEnd (); + break; + case '*': + m_glfcns.glBegin (GL_LINES); + m_glfcns.glVertex2d (-sz/2, 0); + m_glfcns.glVertex2d (sz/2, 0); + m_glfcns.glVertex2d (0, -sz/2); + m_glfcns.glVertex2d (0, sz/2); + m_glfcns.glVertex2d (-tt, -tt); + m_glfcns.glVertex2d (+tt, +tt); + m_glfcns.glVertex2d (-tt, +tt); + m_glfcns.glVertex2d (+tt, -tt); + m_glfcns.glEnd (); + break; + case '.': { - case '+': - m_glfcns.glBegin (GL_LINES); - m_glfcns.glVertex2d (-sz/2, 0); - m_glfcns.glVertex2d (sz/2, 0); - m_glfcns.glVertex2d (0, -sz/2); - m_glfcns.glVertex2d (0, sz/2); - m_glfcns.glEnd (); - break; - case '|': - m_glfcns.glBegin (GL_LINES); - m_glfcns.glVertex2d (0, -sz/2); - m_glfcns.glVertex2d (0, sz/2); - m_glfcns.glEnd (); - break; - case '_': - m_glfcns.glBegin (GL_LINES); - m_glfcns.glVertex2d (-sz/2, 0); - m_glfcns.glVertex2d (sz/2, 0); - m_glfcns.glEnd (); - break; - case 'x': - m_glfcns.glBegin (GL_LINES); - m_glfcns.glVertex2d (-sz/2, -sz/2); - m_glfcns.glVertex2d (sz/2, sz/2); - m_glfcns.glVertex2d (-sz/2, sz/2); - m_glfcns.glVertex2d (sz/2, -sz/2); - m_glfcns.glEnd (); - break; - case '*': - m_glfcns.glBegin (GL_LINES); - m_glfcns.glVertex2d (-sz/2, 0); - m_glfcns.glVertex2d (sz/2, 0); - m_glfcns.glVertex2d (0, -sz/2); - m_glfcns.glVertex2d (0, sz/2); - m_glfcns.glVertex2d (-tt, -tt); - m_glfcns.glVertex2d (+tt, +tt); - m_glfcns.glVertex2d (-tt, +tt); - m_glfcns.glVertex2d (+tt, -tt); + // The dot marker is special and is drawn at 1/3rd the specified size + + // Ensure that something is drawn even at very small markersizes + if (sz > 0 && sz < 3) + sz = 3; + + int div = static_cast (M_PI * sz / 12); + if (! (div % 2)) + div += 1; // ensure odd number for left/right symmetry + div = std::max (div, 3); // ensure at least a few vertices are drawn + double ang_step = M_PI / div; + + m_glfcns.glBegin (GL_POLYGON); + for (double ang = 0; ang < 2*M_PI; ang += ang_step) + m_glfcns.glVertex2d (sz/6* cos (ang), sz/6*sin (ang)); m_glfcns.glEnd (); - break; - case '.': - { - // The dot marker is special and is drawn at 1/3rd the specified size - - // Ensure that something is drawn even at very small markersizes - if (sz > 0 && sz < 3) - sz = 3; - - int div = static_cast (M_PI * sz / 12); - if (! (div % 2)) - div += 1; // ensure odd number for left/right symmetry - div = std::max (div, 3); // ensure at least a few vertices are drawn - double ang_step = M_PI / div; - - m_glfcns.glBegin (GL_POLYGON); - for (double ang = 0; ang < 2*M_PI; ang += ang_step) - m_glfcns.glVertex2d (sz/6*cos (ang), sz/6*sin (ang)); - m_glfcns.glEnd (); - } - break; - case 's': + } + break; + case 's': + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + m_glfcns.glVertex2d (-sz/2, -sz/2); + m_glfcns.glVertex2d (-sz/2, sz/2); + m_glfcns.glVertex2d (sz/2, sz/2); + m_glfcns.glVertex2d (sz/2, -sz/2); + m_glfcns.glEnd (); + break; + case 'o': + { + int div = static_cast (M_PI * sz / 4); + if (! (div % 2)) + div += 1; // ensure odd number for left/right symmetry + div = std::max (div, 5); // ensure at least a few vertices are drawn + double ang_step = M_PI / div; + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - m_glfcns.glVertex2d (-sz/2, -sz/2); - m_glfcns.glVertex2d (-sz/2, sz/2); - m_glfcns.glVertex2d (sz/2, sz/2); - m_glfcns.glVertex2d (sz/2, -sz/2); - m_glfcns.glEnd (); - break; - case 'o': - { - int div = static_cast (M_PI * sz / 4); - if (! (div % 2)) - div += 1; // ensure odd number for left/right symmetry - div = std::max (div, 5); // ensure at least a few vertices are drawn - double ang_step = M_PI / div; - - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - for (double ang = 0; ang < 2*M_PI; ang += ang_step) - m_glfcns.glVertex2d (sz/2*cos (ang), sz/2*sin (ang)); - m_glfcns.glEnd (); - } - break; - case 'd': - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - m_glfcns.glVertex2d (0, -sz/2); - m_glfcns.glVertex2d (sz/2, 0); - m_glfcns.glVertex2d (0, sz/2); - m_glfcns.glVertex2d (-sz/2, 0); - m_glfcns.glEnd (); - break; - case 'v': - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - m_glfcns.glVertex2d (0, sz/2); - m_glfcns.glVertex2d (sz/2, -sz/2); - m_glfcns.glVertex2d (-sz/2, -sz/2); + for (double ang = 0; ang < 2*M_PI; ang += ang_step) + m_glfcns.glVertex2d (sz/2* cos (ang), sz/2*sin (ang)); m_glfcns.glEnd (); - break; - case '^': - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - m_glfcns.glVertex2d (0, -sz/2); - m_glfcns.glVertex2d (-sz/2, sz/2); - m_glfcns.glVertex2d (sz/2, sz/2); - m_glfcns.glEnd (); - break; - case '>': + } + break; + case 'd': + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + m_glfcns.glVertex2d (0, -sz/2); + m_glfcns.glVertex2d (sz/2, 0); + m_glfcns.glVertex2d (0, sz/2); + m_glfcns.glVertex2d (-sz/2, 0); + m_glfcns.glEnd (); + break; + case 'v': + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + m_glfcns.glVertex2d (0, sz/2); + m_glfcns.glVertex2d (sz/2, -sz/2); + m_glfcns.glVertex2d (-sz/2, -sz/2); + m_glfcns.glEnd (); + break; + case '^': + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + m_glfcns.glVertex2d (0, -sz/2); + m_glfcns.glVertex2d (-sz/2, sz/2); + m_glfcns.glVertex2d (sz/2, sz/2); + m_glfcns.glEnd (); + break; + case '>': + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + m_glfcns.glVertex2d (sz/2, 0); + m_glfcns.glVertex2d (-sz/2, sz/2); + m_glfcns.glVertex2d (-sz/2, -sz/2); + m_glfcns.glEnd (); + break; + case '<': + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + m_glfcns.glVertex2d (-sz/2, 0); + m_glfcns.glVertex2d (sz/2, -sz/2); + m_glfcns.glVertex2d (sz/2, sz/2); + m_glfcns.glEnd (); + break; + case 'p': + { + double ang, r, dr; + dr = 1.0 - sin (M_PI/10)/sin (3*M_PI/10)*1.02; + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - m_glfcns.glVertex2d (sz/2, 0); - m_glfcns.glVertex2d (-sz/2, sz/2); - m_glfcns.glVertex2d (-sz/2, -sz/2); - m_glfcns.glEnd (); - break; - case '<': - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - m_glfcns.glVertex2d (-sz/2, 0); - m_glfcns.glVertex2d (sz/2, -sz/2); - m_glfcns.glVertex2d (sz/2, sz/2); + for (int i = 0; i < 2*5; i++) + { + ang = (-0.5 + double (i+1) / 5) * M_PI; + r = 1.0 - (dr * fmod (double (i+1), 2.0)); + m_glfcns.glVertex2d (sz/2*r* cos (ang), sz/2*r*sin (ang)); + } m_glfcns.glEnd (); - break; - case 'p': - { - double ang, r, dr; - dr = 1.0 - sin (M_PI/10)/sin (3*M_PI/10)*1.02; - - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - for (int i = 0; i < 2*5; i++) - { - ang = (-0.5 + double (i+1) / 5) * M_PI; - r = 1.0 - (dr * fmod (double (i+1), 2.0)); - m_glfcns.glVertex2d (sz/2*r*cos (ang), sz/2*r*sin (ang)); - } - m_glfcns.glEnd (); - } - break; - case 'h': - { - double ang, r, dr; - dr = 1.0 - 0.5/sin (M_PI/3)*1.02; - - m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); - for (int i = 0; i < 2*6; i++) - { - ang = (0.5 + double (i+1) / 6.0) * M_PI; - r = 1.0 - (dr * fmod (double (i+1), 2.0)); - m_glfcns.glVertex2d (sz/2*r*cos (ang), sz/2*r*sin (ang)); - } - m_glfcns.glEnd (); - } - break; - default: - warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ()); - break; } - - m_glfcns.glEndList (); - - return ID; + break; + case 'h': + { + double ang, r, dr; + dr = 1.0 - 0.5/sin (M_PI/3)*1.02; + + m_glfcns.glBegin (filled ? GL_POLYGON : GL_LINE_LOOP); + for (int i = 0; i < 2*6; i++) + { + ang = (0.5 + double (i+1) / 6.0) * M_PI; + r = 1.0 - (dr * fmod (double (i+1), 2.0)); + m_glfcns.glVertex2d (sz/2*r* cos (ang), sz/2*r*sin (ang)); + } + m_glfcns.glEnd (); + } + break; + default: + warning ("opengl_renderer: unsupported marker '%s'", marker.c_str ()); + break; + } + + m_glfcns.glEndList (); + + return ID; #else - octave_unused_parameter (marker); - octave_unused_parameter (size); - octave_unused_parameter (filled); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (marker); + octave_unused_parameter (size); + octave_unused_parameter (filled); + + // 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::text_to_pixels (const std::string& txt, - uint8NDArray& pixels, - Matrix& bbox, - int halign, int valign, double rotation) - { - m_txt_renderer.text_to_pixels (txt, pixels, bbox, halign, valign, - rotation, m_interpreter); - } - - void - opengl_renderer::text_to_strlist (const std::string& txt, - std::list& lst, - Matrix& bbox, - int halign, int valign, double rotation) - { - m_txt_renderer.text_to_strlist (txt, lst, bbox, halign, valign, - rotation, m_interpreter); - } - - Matrix - opengl_renderer::render_text (const std::string& txt, - double x, double y, double z, - int halign, int valign, double rotation) - { +} + +void +opengl_renderer::text_to_pixels (const std::string& txt, + uint8NDArray& pixels, + Matrix& bbox, + int halign, int valign, double rotation) +{ + m_txt_renderer.text_to_pixels (txt, pixels, bbox, halign, valign, + rotation, m_interpreter); +} + +void +opengl_renderer::text_to_strlist (const std::string& txt, + std::list& lst, + Matrix& bbox, + int halign, int valign, double rotation) +{ + m_txt_renderer.text_to_strlist (txt, lst, bbox, halign, valign, + rotation, m_interpreter); +} + +Matrix +opengl_renderer::render_text (const std::string& txt, + double x, double y, double z, + int halign, int valign, double rotation) +{ #if defined (HAVE_OPENGL) - Matrix bbox (1, 4, 0.0); - - if (txt.empty ()) - return bbox; - - if (m_txt_renderer.ok ()) - { - uint8NDArray pixels; - text_to_pixels (txt, pixels, bbox, halign, valign, rotation); - - render_text (pixels, bbox, x, y, z, rotation); - } - + Matrix bbox (1, 4, 0.0); + + if (txt.empty ()) return bbox; + if (m_txt_renderer.ok ()) + { + uint8NDArray pixels; + text_to_pixels (txt, pixels, bbox, halign, valign, rotation); + + render_text (pixels, bbox, x, y, z, rotation); + } + + return bbox; + #else - octave_unused_parameter (txt); - octave_unused_parameter (x); - octave_unused_parameter (y); - octave_unused_parameter (z); - octave_unused_parameter (halign); - octave_unused_parameter (valign); - octave_unused_parameter (rotation); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (txt); + octave_unused_parameter (x); + octave_unused_parameter (y); + octave_unused_parameter (z); + octave_unused_parameter (halign); + octave_unused_parameter (valign); + octave_unused_parameter (rotation); + + // 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::render_text (uint8NDArray pixels, Matrix bbox, - double x, double y, double z, double rotation) - { +} + +void +opengl_renderer::render_text (uint8NDArray pixels, Matrix bbox, + double x, double y, double z, double rotation) +{ #if defined (HAVE_OPENGL) - // Transform data coordinates to screen pixel ortho coordinates - ColumnVector pixpos = get_transform ().transform (x, y, z, false); - Matrix xdata(1, 2, bbox(0) / m_devpixratio); - xdata(1) += (bbox(2) - 1) / m_devpixratio; - Matrix ydata(1, 2, -bbox(1) / m_devpixratio); - ydata(1) -= (bbox(3) - 1) / m_devpixratio; - - bool blend = m_glfcns.glIsEnabled (GL_BLEND); - m_glfcns.glEnable (GL_BLEND); - m_glfcns.glEnable (GL_ALPHA_TEST); - - set_ortho_coordinates (); - - // Translate coordinates so that the text anchor is (0,0) - m_glfcns.glTranslated (pixpos(0), pixpos(1), -pixpos(2)); - - m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0); - - // Permute pixels returned by freetype - Array perm (dim_vector (3, 1)); - perm(0) = 2; - perm(1) = 1; - perm(2) = 0; - draw_texture_image (pixels.permute (perm), - xdata, ydata, true); - - restore_previous_coordinates (); - - m_glfcns.glDisable (GL_ALPHA_TEST); - - if (! blend) - m_glfcns.glDisable (GL_BLEND); + // Transform data coordinates to screen pixel ortho coordinates + ColumnVector pixpos = get_transform ().transform (x, y, z, false); + Matrix xdata(1, 2, bbox(0) / m_devpixratio); + xdata(1) += (bbox(2) - 1) / m_devpixratio; + Matrix ydata(1, 2, -bbox(1) / m_devpixratio); + ydata(1) -= (bbox(3) - 1) / m_devpixratio; + + bool blend = m_glfcns.glIsEnabled (GL_BLEND); + m_glfcns.glEnable (GL_BLEND); + m_glfcns.glEnable (GL_ALPHA_TEST); + + set_ortho_coordinates (); + + // Translate coordinates so that the text anchor is (0,0) + m_glfcns.glTranslated (pixpos(0), pixpos(1), -pixpos(2)); + + m_glfcns.glRotated (-rotation, 0.0, 0.0, 1.0); + + // Permute pixels returned by freetype + Array perm (dim_vector (3, 1)); + perm(0) = 2; + perm(1) = 1; + perm(2) = 0; + draw_texture_image (pixels.permute (perm), + xdata, ydata, true); + + restore_previous_coordinates (); + + m_glfcns.glDisable (GL_ALPHA_TEST); + + if (! blend) + m_glfcns.glDisable (GL_BLEND); #else - octave_unused_parameter (pixels); - octave_unused_parameter (bbox); - octave_unused_parameter (x); - octave_unused_parameter (y); - octave_unused_parameter (z); - octave_unused_parameter (rotation); - - // This shouldn't happen because construction of opengl_renderer - // objects is supposed to be impossible if OpenGL is not available. - - panic_impossible (); + octave_unused_parameter (pixels); + octave_unused_parameter (bbox); + octave_unused_parameter (x); + octave_unused_parameter (y); + octave_unused_parameter (z); + octave_unused_parameter (rotation); + + // This shouldn't happen because construction of opengl_renderer + // objects is supposed to be impossible if OpenGL is not available. + + panic_impossible (); #endif - } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gl-render.h --- a/libinterp/corefcn/gl-render.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gl-render.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,235 +33,235 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class opengl_functions; +class opengl_functions; - class - OCTINTERP_API - opengl_renderer - { - public: +class +OCTINTERP_API +opengl_renderer +{ +public: - opengl_renderer (opengl_functions& glfcns); + opengl_renderer (opengl_functions& glfcns); - // No copying! + // No copying! - opengl_renderer (const opengl_renderer&) = delete; + opengl_renderer (const opengl_renderer&) = delete; - opengl_renderer& operator = (const opengl_renderer&) = delete; + opengl_renderer& operator = (const opengl_renderer&) = delete; - virtual ~opengl_renderer (void) = default; + virtual ~opengl_renderer (void) = default; - opengl_functions& get_opengl_functions (void) const { return m_glfcns; } + opengl_functions& get_opengl_functions (void) const { return m_glfcns; } - virtual void draw (const graphics_object& go, bool toplevel = true); + virtual void draw (const graphics_object& go, bool toplevel = true); - // The following version of the draw method is not declared virtual - // because no derived class overrides it. + // The following version of the draw method is not declared virtual + // because no derived class overrides it. - void draw (const Matrix& hlist, bool toplevel = false); + void draw (const Matrix& hlist, bool toplevel = false); - virtual void set_viewport (int w, int h); - virtual void set_device_pixel_ratio (double dpr) { m_devpixratio = dpr; } - virtual Matrix get_viewport_scaled (void) const; - virtual graphics_xform get_transform (void) const { return m_xform; } - virtual uint8NDArray get_pixels (int width, int height); + virtual void set_viewport (int w, int h); + virtual void set_device_pixel_ratio (double dpr) { m_devpixratio = dpr; } + virtual Matrix get_viewport_scaled (void) const; + virtual graphics_xform get_transform (void) const { return m_xform; } + virtual uint8NDArray get_pixels (int width, int height); - virtual void draw_zoom_box (int width, int height, - int x1, int y1, int x2, int y2, - const Matrix& overlaycolor, - double overlayalpha, - const Matrix& bordercolor, - double borderalpha, double borderwidth); + virtual void draw_zoom_box (int width, int height, + int x1, int y1, int x2, int y2, + const Matrix& overlaycolor, + double overlayalpha, + const Matrix& bordercolor, + double borderalpha, double borderwidth); - virtual void finish (void); + virtual void finish (void); - protected: +protected: - virtual void draw_figure (const figure::properties& props); - virtual void draw_axes (const axes::properties& props); - 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); - virtual void draw_text_background (const text::properties& props, - bool do_rotate = false); - virtual void draw_image (const image::properties& props); - virtual void draw_uipanel (const uipanel::properties& props, - const graphics_object& go); - virtual void draw_uibuttongroup (const uibuttongroup::properties& props, - const graphics_object& go); - virtual void init_gl_context (bool enhanced, const Matrix& backgroundColor); - virtual void setup_opengl_transformation (const axes::properties& props); + virtual void draw_figure (const figure::properties& props); + virtual void draw_axes (const axes::properties& props); + 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); + virtual void draw_text_background (const text::properties& props, + bool do_rotate = false); + virtual void draw_image (const image::properties& props); + virtual void draw_uipanel (const uipanel::properties& props, + const graphics_object& go); + virtual void draw_uibuttongroup (const uibuttongroup::properties& props, + const graphics_object& go); + virtual void init_gl_context (bool enhanced, const Matrix& backgroundColor); + virtual void setup_opengl_transformation (const axes::properties& props); - virtual void set_clipbox (double x1, double x2, double y1, double y2, - double z1, double z2); - virtual void set_clipping (bool on); - virtual void set_font (const base_properties& props); - virtual void set_color (const Matrix& c); - virtual void set_interpreter (const caseless_str& interp) - { - m_interpreter = interp; - } - virtual void set_linewidth (float w); - virtual void set_linestyle (const std::string& s, bool stipple = false, - double linewidth = 0.5); - virtual void set_linecap (const std::string&) { }; - virtual void set_linejoin (const std::string&) { }; - virtual void set_polygon_offset (bool on, float offset = 0.0f); - virtual void set_selecting (bool on) - { - m_selecting = on; - } + virtual void set_clipbox (double x1, double x2, double y1, double y2, + double z1, double z2); + virtual void set_clipping (bool on); + virtual void set_font (const base_properties& props); + virtual void set_color (const Matrix& c); + virtual void set_interpreter (const caseless_str& interp) + { + m_interpreter = interp; + } + virtual void set_linewidth (float w); + virtual void set_linestyle (const std::string& s, bool stipple = false, + double linewidth = 0.5); + virtual void set_linecap (const std::string&) { }; + virtual void set_linejoin (const std::string&) { }; + virtual void set_polygon_offset (bool on, float offset = 0.0f); + virtual void set_selecting (bool on) + { + m_selecting = on; + } - 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 double la = 1.0, const double fa = 1.0); + 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 double la = 1.0, const double fa = 1.0); - virtual void text_to_pixels (const std::string& txt, - uint8NDArray& pixels, - Matrix& bbox, - int halign = 0, int valign = 0, - double rotation = 0.0); + virtual void text_to_pixels (const std::string& txt, + uint8NDArray& pixels, + Matrix& bbox, + int halign = 0, int valign = 0, + double rotation = 0.0); - virtual void text_to_strlist (const std::string& txt, - std::list& lst, - Matrix& bbox, - int halign = 0, int valign = 0, - double rotation = 0.0); + virtual void text_to_strlist (const std::string& txt, + std::list& lst, + Matrix& bbox, + int halign = 0, int valign = 0, + double rotation = 0.0); - virtual Matrix render_text (const std::string& txt, - double x, double y, double z, - int halign, int valign, double rotation = 0.0); + virtual Matrix render_text (const std::string& txt, + double x, double y, double z, + int halign, int valign, double rotation = 0.0); - virtual void render_grid (const double linewidth, - const std::string& gridstyle, - const Matrix& gridcolor, const double gridalpha, - const Matrix& ticks, double lim1, double lim2, - double p1, double p1N, double p2, double p2N, - int xyz, bool is_3D); + virtual void render_grid (const double linewidth, + const std::string& gridstyle, + const Matrix& gridcolor, const double gridalpha, + const Matrix& ticks, double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + int xyz, bool is_3D); - virtual void render_tickmarks (const Matrix& ticks, - double lim1, double lim2, - double p1, double p1N, double p2, double p2N, - double dx, double dy, double dz, - int xyz, bool doubleside); + virtual void render_tickmarks (const Matrix& ticks, + double lim1, double lim2, + double p1, double p1N, double p2, double p2N, + double dx, double dy, double dz, + int xyz, bool doubleside); - virtual void render_ticktexts (const Matrix& ticks, - const string_vector& ticklabels, - double lim1, double lim2, - double p1, double p2, - int xyz, int ha, int va, - int& wmax, int& hmax); + virtual void render_ticktexts (const Matrix& ticks, + const string_vector& ticklabels, + double lim1, double lim2, + double p1, double p2, + int xyz, int ha, int va, + int& wmax, int& hmax); - virtual void draw_zoom_rect (int x1, int y1, int x2, int y2); + virtual void draw_zoom_rect (int x1, int y1, int x2, int y2); - //-------- + //-------- - opengl_functions& m_glfcns; + opengl_functions& m_glfcns; - // axis limits in model scaled coordinate - double m_xmin, m_xmax; - double m_ymin, m_ymax; - double m_zmin, m_zmax; + // axis limits in model scaled coordinate + double m_xmin, m_xmax; + double m_ymin, m_ymax; + double m_zmin, m_zmax; - // Factor used for translating Octave pixels to actual device pixels - double m_devpixratio; + // Factor used for translating Octave pixels to actual device pixels + double m_devpixratio; - // axes transformation data - graphics_xform m_xform; + // axes transformation data + graphics_xform m_xform; - private: +private: - class patch_tessellator; + class patch_tessellator; - void init_maxlights (void); + void init_maxlights (void); - std::string get_string (unsigned int id) const; + std::string get_string (unsigned int id) const; - bool is_nan_or_inf (double x, double y, double z) const - { - return (math::isnan (x) || math::isnan (y) - || math::isnan (z) - || math::isinf (x) || math::isinf (y) - || math::isinf (z)); - } + bool is_nan_or_inf (double x, double y, double z) const + { + return (math::isnan (x) || math::isnan (y) + || math::isnan (z) + || math::isinf (x) || math::isinf (y) + || math::isinf (z)); + } - uint8_t clip_code (double x, double y, double z) const - { - return ((x < m_xmin ? 1 : 0) - | (x > m_xmax ? 1 : 0) << 1 - | (y < m_ymin ? 1 : 0) << 2 - | (y > m_ymax ? 1 : 0) << 3 - | (z < m_zmin ? 1 : 0) << 4 - | (z > m_zmax ? 1 : 0) << 5 - | (is_nan_or_inf (x, y, z) ? 0 : 1) << 6); - } + uint8_t clip_code (double x, double y, double z) const + { + return ((x < m_xmin ? 1 : 0) + | (x > m_xmax ? 1 : 0) << 1 + | (y < m_ymin ? 1 : 0) << 2 + | (y > m_ymax ? 1 : 0) << 3 + | (z < m_zmin ? 1 : 0) << 4 + | (z > m_zmax ? 1 : 0) << 5 + | (is_nan_or_inf (x, y, z) ? 0 : 1) << 6); + } - void render_text (uint8NDArray pixels, Matrix bbox, - double x, double y, double z, double rotation); + void render_text (uint8NDArray pixels, Matrix bbox, + double x, double y, double z, double rotation); - void set_normal (int bfl_mode, const NDArray& n, int j, int i); + void set_normal (int bfl_mode, const NDArray& n, int j, int i); - void set_ortho_coordinates (void); + void set_ortho_coordinates (void); - void restore_previous_coordinates (void); + void restore_previous_coordinates (void); - double points_to_pixels (const double val) const; + double points_to_pixels (const double val) const; - unsigned int make_marker_list (const std::string& m, double size, - bool filled) const; + unsigned int make_marker_list (const std::string& m, double size, + bool filled) const; - void draw_axes_planes (const axes::properties& props); - void draw_axes_boxes (const axes::properties& props); + void draw_axes_planes (const axes::properties& props); + void draw_axes_boxes (const axes::properties& props); - void draw_axes_grids (const axes::properties& props); - void draw_axes_x_grid (const axes::properties& props); - void draw_axes_y_grid (const axes::properties& props); - void draw_axes_z_grid (const axes::properties& props); + void draw_axes_grids (const axes::properties& props); + void draw_axes_x_grid (const axes::properties& props); + void draw_axes_y_grid (const axes::properties& props); + void draw_axes_z_grid (const axes::properties& props); - void draw_axes_children (const axes::properties& props); + void draw_axes_children (const axes::properties& props); - void draw_all_lights (const base_properties& props, - std::list& obj_list); + void draw_all_lights (const base_properties& props, + std::list& obj_list); - void draw_texture_image (const octave_value cdata, - Matrix x, Matrix y, bool ortho = false); + void draw_texture_image (const octave_value cdata, + Matrix x, Matrix y, bool ortho = false); - //-------- + //-------- - // The graphics m_toolkit associated with the figure being rendered. - graphics_toolkit m_toolkit; + // The graphics m_toolkit associated with the figure being rendered. + graphics_toolkit m_toolkit; - // Z projection limits in windows coordinate - double m_xZ1, m_xZ2; + // Z projection limits in windows coordinate + double m_xZ1, m_xZ2; - // call lists identifiers for markers - unsigned int m_marker_id, m_filled_marker_id; + // call lists identifiers for markers + unsigned int m_marker_id, m_filled_marker_id; - // camera information for primitive sorting and lighting - ColumnVector m_camera_pos, m_camera_dir, m_view_vector; + // camera information for primitive sorting and lighting + ColumnVector m_camera_pos, m_camera_dir, m_view_vector; - // interpreter to be used by text_to_pixels - caseless_str m_interpreter; + // interpreter to be used by text_to_pixels + caseless_str m_interpreter; - text_renderer m_txt_renderer; + text_renderer m_txt_renderer; - // light object present and visible - unsigned int m_current_light; - unsigned int m_max_lights; + // light object present and visible + unsigned int m_current_light; + unsigned int m_max_lights; - // Indicate we are drawing for selection purpose - bool m_selecting; + // Indicate we are drawing for selection purpose + bool m_selecting; - // Indicate we are drawing for printing purpose - bool m_printing; - }; + // Indicate we are drawing for printing purpose + bool m_printing; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gl2ps-print.cc --- a/libinterp/corefcn/gl2ps-print.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gl2ps-print.cc Thu Dec 01 20:05:44 2022 -0800 @@ -56,276 +56,40 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTINTERP_API - gl2ps_renderer : public opengl_renderer - { - public: - - gl2ps_renderer (opengl_functions& glfcns, FILE *_fp, - const std::string& _term) - : opengl_renderer (glfcns), m_fp (_fp), m_term (_term), m_fontsize (), - m_fontname (), m_buffer_overflow (false), m_svg_def_index (0) - { } - - ~gl2ps_renderer (void) = default; - - // FIXME: should we import the functions from the base class and - // overload them here, or should we use a different name so we don't - // have to do this? Without the using declaration or a name change, - // the base class functions will be hidden. That may be OK, but it - // can also cause some confusion. - using opengl_renderer::draw; - - void draw (const graphics_object& go, const std::string& print_cmd); - - protected: - - Matrix render_text (const std::string& txt, - double x, double y, double z, - int halign, int valign, double rotation = 0.0); - - void set_font (const base_properties& props); - - static bool has_alpha (const graphics_handle& h) - { - bool retval = false; - - gh_manager& gh_mgr = __get_gh_manager__ (); - - graphics_object go = gh_mgr.get_object (h); - - if (! go.valid_object ()) - return retval; +class +OCTINTERP_API +gl2ps_renderer : public opengl_renderer +{ +public: - if (go.isa ("axes") || go.isa ("hggroup")) - { - Matrix children = go.get ("children").matrix_value (); - for (octave_idx_type ii = 0; ii < children.numel (); ii++) - { - retval = has_alpha (graphics_handle (children(ii))); - if (retval) - break; - } - } - else if (go.isa ("patch") || go.isa ("surface")) - { - octave_value fa = go.get ("facealpha"); - if (fa.is_scalar_type () && fa.is_double_type () - && 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; - } - - void draw_axes (const axes::properties& props) - { - // Initialize a sorting tree (viewport) in gl2ps for each axes - GLint vp[4]; - m_glfcns.glGetIntegerv (GL_VIEWPORT, vp); - gl2psBeginViewport (vp); - + gl2ps_renderer (opengl_functions& glfcns, FILE *_fp, + const std::string& _term) + : opengl_renderer (glfcns), m_fp (_fp), m_term (_term), m_fontsize (), + m_fontname (), m_buffer_overflow (false), m_svg_def_index (0) + { } - // Don't remove hidden primitives when some of them are transparent - GLint opts; - gl2psGetOptions (&opts); - if (has_alpha (props.get___myhandle__ ())) - { - opts &= ~GL2PS_OCCLUSION_CULL; - // FIXME: currently the GL2PS_BLEND (which is more an equivalent of - // GL_ALPHA_TEST than GL_BLEND) is not working on a per primitive - // basis. We thus set it once per viewport. - gl2psEnable (GL2PS_BLEND); - } - else - { - opts |= GL2PS_OCCLUSION_CULL; - gl2psDisable (GL2PS_BLEND); - } - - gl2psSetOptions (opts); - - // Draw and finish () or there may be primitives missing in the gl2ps - // output. - opengl_renderer::draw_axes (props); - finish (); - - // Finalize viewport - GLint state = gl2psEndViewport (); - if (state == GL2PS_NO_FEEDBACK && props.is_visible ()) - warning ("gl2ps_renderer::draw_axes: empty feedback buffer and/or nothing else to print"); - else if (state == GL2PS_ERROR) - error ("gl2ps_renderer::draw_axes: gl2psEndPage returned GL2PS_ERROR"); - - m_buffer_overflow |= (state == GL2PS_OVERFLOW); - - // Don't draw background for subsequent viewports (legends, subplots, - // etc.) - gl2psGetOptions (&opts); - opts &= ~GL2PS_DRAW_BACKGROUND; - gl2psSetOptions (opts); - } - - void draw_text (const text::properties& props); - - void draw_image (const image::properties& props); - void draw_pixels (int w, int h, const float *data); - void draw_pixels (int w, int h, const uint8_t *data); - void draw_pixels (int w, int h, const uint16_t *data); - - void init_marker (const std::string& m, double size, float width) - { - opengl_renderer::init_marker (m, size, width); + ~gl2ps_renderer (void) = default; - // FIXME: gl2ps can't handle closed contours so we set linecap/linejoin - // round to obtain a better looking result for some markers. - if (m == "o" || m == "v" || m == "^" || m == ">" || m == "<" || m == "h" - || m == "hexagram" || m == "p" || m == "pentagram") - { - set_linejoin ("round"); - set_linecap ("round"); - } - else - { - set_linejoin ("miter"); - set_linecap ("square"); - } - } - - void set_linestyle (const std::string& s, bool use_stipple = false, - double linewidth = 0.5) - { - opengl_renderer::set_linestyle (s, use_stipple, linewidth); - - if (s == "-" && ! use_stipple) - gl2psDisable (GL2PS_LINE_STIPPLE); - else - gl2psEnable (GL2PS_LINE_STIPPLE); - } - - void set_linecap (const std::string& s) - { - opengl_renderer::set_linejoin (s); + // FIXME: should we import the functions from the base class and + // overload them here, or should we use a different name so we don't + // have to do this? Without the using declaration or a name change, + // the base class functions will be hidden. That may be OK, but it + // can also cause some confusion. + using opengl_renderer::draw; -#if defined (HAVE_GL2PSLINEJOIN) - if (s == "butt") - gl2psLineCap (GL2PS_LINE_CAP_BUTT); - else if (s == "square") - gl2psLineCap (GL2PS_LINE_CAP_SQUARE); - else if (s == "round") - gl2psLineCap (GL2PS_LINE_CAP_ROUND); -#endif - } - - void set_linejoin (const std::string& s) - { - opengl_renderer::set_linejoin (s); - -#if defined (HAVE_GL2PSLINEJOIN) - if (s == "round") - gl2psLineJoin (GL2PS_LINE_JOIN_ROUND); - else if (s == "miter") - gl2psLineJoin (GL2PS_LINE_JOIN_MITER); - else if (s == "chamfer") - gl2psLineJoin (GL2PS_LINE_JOIN_BEVEL); -#endif - } - - void set_polygon_offset (bool on, float offset = 0.0f) - { - if (on) - { - opengl_renderer::set_polygon_offset (on, offset); - gl2psEnable (GL2PS_POLYGON_OFFSET_FILL); - } - else - { - gl2psDisable (GL2PS_POLYGON_OFFSET_FILL); - opengl_renderer::set_polygon_offset (on, offset); - } - } + void draw (const graphics_object& go, const std::string& print_cmd); - void set_linewidth (float w) - { - gl2psLineWidth (w); - } - - private: - - // Use xform to compute the coordinates of the string list - // that have been parsed by freetype. - void fix_strlist_position (double x, double y, double z, - Matrix box, double rotation, - std::list& lst); - - // Build an svg text element from a list of parsed strings - std::string format_svg_element (std::string str, Matrix bbox, - double rotation, ColumnVector coord_pix, - Matrix color); +protected: - std::string strlist_to_svg (double x, double y, double z, Matrix box, - double rotation, - std::list& lst); - - // Build a list of postscript commands from a list of parsed strings. - std::string strlist_to_ps (double x, double y, double z, Matrix box, - double rotation, - std::list& lst); - - int alignment_to_mode (int ha, int va) const; - - FILE *m_fp; - caseless_str m_term; - double m_fontsize; - std::string m_fontname; - bool m_buffer_overflow; - std::size_t m_svg_def_index; - }; + Matrix render_text (const std::string& txt, + double x, double y, double z, + int halign, int valign, double rotation = 0.0); - static bool - has_2D_axes (const graphics_handle& h) - { - bool retval = true; - - gh_manager& gh_mgr = __get_gh_manager__ (); - - graphics_object go = gh_mgr.get_object (h); - - if (! go.valid_object ()) - return retval; + void set_font (const base_properties& props); - if (go.isa ("figure") || go.isa ("uipanel")) - { - Matrix children = go.get ("children").matrix_value (); - for (octave_idx_type ii = 0; ii < children.numel (); ii++) - { - retval = has_2D_axes (graphics_handle (children(ii))); - if (! retval) - break; - } - } - else if (go.isa ("axes")) - { - axes::properties& ap - = reinterpret_cast (go.get_properties ()); - retval = ap.get_is2D (true); - } - - return retval; - } - - static std::string - get_title (const graphics_handle& h) + static bool has_alpha (const graphics_handle& h) { - std::string retval; + bool retval = false; gh_manager& gh_mgr = __get_gh_manager__ (); @@ -334,1255 +98,1491 @@ if (! go.valid_object ()) return retval; - if (go.isa ("figure")) + if (go.isa ("axes") || go.isa ("hggroup")) + { + Matrix children = go.get ("children").matrix_value (); + for (octave_idx_type ii = 0; ii < children.numel (); ii++) + { + retval = has_alpha (graphics_handle (children(ii))); + if (retval) + break; + } + } + else if (go.isa ("patch") || go.isa ("surface")) { - figure::properties& fp - = reinterpret_cast (go.get_properties ()); - - retval = fp.get_title (); + octave_value fa = go.get ("facealpha"); + if (fa.is_scalar_type () && fa.is_double_type () + && 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; } - void - gl2ps_renderer::draw (const graphics_object& go, const std::string& print_cmd) + void draw_axes (const axes::properties& props) { - static bool in_draw = false; - static std::string old_print_cmd; - static GLint buffsize; - - if (! in_draw) - { - unwind_protect frame; - - frame.protect_var (in_draw); - - in_draw = true; - - GLint gl2ps_term = GL2PS_PS; - if (m_term.find ("eps") != std::string::npos) - gl2ps_term = GL2PS_EPS; - else if (m_term.find ("pdf") != std::string::npos) - gl2ps_term = GL2PS_PDF; - else if (m_term.find ("ps") != std::string::npos) - gl2ps_term = GL2PS_PS; - else if (m_term.find ("svg") != std::string::npos) - gl2ps_term = GL2PS_SVG; - else if (m_term.find ("pgf") != std::string::npos) - gl2ps_term = GL2PS_PGF; - else if (m_term.find ("tex") != std::string::npos) - gl2ps_term = GL2PS_TEX; - else - warning ("gl2ps_renderer::draw: Unknown terminal %s, using 'ps'", - m_term.c_str ()); - - GLint gl2ps_text = 0; - if (m_term.find ("notxt") != std::string::npos) - gl2ps_text = GL2PS_NO_TEXT; - - // Find Title for plot - const graphics_handle& myhandle = go.get ("__myhandle__"); - std::string plot_title = get_title (myhandle); - if (plot_title.empty ()) - plot_title = "Octave plot"; - - // Default sort order optimizes for 3D plots - GLint gl2ps_sort = GL2PS_BSP_SORT; - - // FIXME: gl2ps does not provide a way to change the sorting algorithm - // on a viewport basis, we thus disable sorting only if all axes are 2D - if (has_2D_axes (myhandle)) - gl2ps_sort = GL2PS_NO_SORT; + // Initialize a sorting tree (viewport) in gl2ps for each axes + GLint vp[4]; + m_glfcns.glGetIntegerv (GL_VIEWPORT, vp); + gl2psBeginViewport (vp); - // Use a temporary file in case an overflow happens - std::string tmpfile (sys::tempnam (sys::env::get_temp_directory (), - "oct-")); - FILE *tmpf = sys::fopen_tmp (tmpfile, "w+b"); - - if (! tmpf) - error ("gl2ps_renderer::draw: couldn't open temporary file for printing"); - - frame.add ([=] () { std::fclose (tmpf); }); - - // Reset buffsize, unless this is 2nd pass of a texstandalone print. - if (m_term.find ("tex") == std::string::npos) - buffsize = 2*1024*1024; - else - buffsize /= 2; - - m_buffer_overflow = true; - - while (m_buffer_overflow) - { - m_buffer_overflow = false; - buffsize *= 2; - - std::fseek (tmpf, 0, SEEK_SET); - octave_ftruncate_wrapper (fileno (tmpf), 0); - - // For LaTeX output the print process uses 2 drawnow() commands. - // The first one is for the pdf/ps/eps graph to be included. The - // print_cmd is saved as old_print_cmd. Then the second drawnow() - // outputs the tex-file and the graphic filename to be included is - // extracted from old_print_cmd. - - std::string include_graph; - - std::size_t found_redirect = old_print_cmd.find ('>'); - - if (found_redirect != std::string::npos) - include_graph = old_print_cmd.substr (found_redirect + 1); - else - include_graph = old_print_cmd; - - std::size_t n_begin = include_graph.find_first_not_of (R"( "')"); - - if (n_begin != std::string::npos) - { - // Strip any quote characters characters around filename - std::size_t n_end = include_graph.find_last_not_of (R"( "')"); - include_graph = include_graph.substr (n_begin, - n_end - n_begin + 1); - // Strip path from filename - n_begin = include_graph.find_last_of (sys::file_ops::dir_sep_chars ()); - include_graph = include_graph.substr (n_begin + 1); - } - else - include_graph = "foobar-inc"; - // FIXME: workaround gl2ps drawing 2 background planes, the first - // eventually being black and producing visual artifacts - const figure::properties& fprop - = dynamic_cast (go.get_properties ()); - Matrix c = fprop.get_color_rgb (); - m_glfcns.glClearColor (c(0), c(1), c(2), 1); - - // Allow figures to be printed at arbitrary resolution - set_device_pixel_ratio (fprop.get___device_pixel_ratio__ ()); - - // GL2PS_SILENT was removed to allow gl2ps to print errors on stderr - GLint ret = gl2psBeginPage (plot_title.c_str (), "Octave", - nullptr, gl2ps_term, gl2ps_sort, - (GL2PS_BEST_ROOT - | gl2ps_text - | GL2PS_DRAW_BACKGROUND - | GL2PS_NO_PS3_SHADING - | GL2PS_USE_CURRENT_VIEWPORT), - GL_RGBA, 0, nullptr, 0, 0, 0, - buffsize, tmpf, include_graph.c_str ()); - if (ret == GL2PS_ERROR) - { - old_print_cmd.clear (); - error ("gl2ps_renderer::draw: gl2psBeginPage returned GL2PS_ERROR"); - } - - opengl_renderer::draw (go); - - if (m_buffer_overflow) - warning ("gl2ps_renderer::draw: retrying with buffer size: %.1E B\n", double (2*buffsize)); - - if (! m_buffer_overflow) - old_print_cmd = print_cmd; - - // Don't check return value of gl2psEndPage, it is not meaningful. - // Errors and warnings are checked after gl2psEndViewport in - // gl2ps_renderer::draw_axes instead. - gl2psEndPage (); - } - - // Copy temporary file to pipe - std::fseek (tmpf, 0, SEEK_SET); - char str[8192]; // 8 kB is a common kernel buffersize - std::size_t nread, nwrite; - nread = 1; - - // In EPS terminal read the header line by line and insert a - // new procedure - const char *fcn = "/SRX { gsave FCT moveto rotate xshow grestore } BD\n"; - bool header_found = ! (m_term.find ("eps") != std::string::npos - || m_term.find ("svg") != std::string::npos); - - while (! feof (tmpf) && nread) - { - if (! header_found && std::fgets (str, 8192, tmpf)) - nread = strlen (str); - else - nread = std::fread (str, 1, 8192, tmpf); - - if (nread) - { - if (! header_found && std::strncmp (str, "/SBCR", 5) == 0) - { - header_found = true; - nwrite = std::fwrite (fcn, 1, strlen (fcn), m_fp); - if (nwrite != strlen (fcn)) - { - // FIXME: is this the best thing to do here? - respond_to_pending_signals (); - error ("gl2ps_renderer::draw: internal pipe error"); - } - } - else if (m_term.find ("svg") != std::string::npos) - { - // FIXME: gl2ps uses pixel units for SVG format. - // Modify resulting svg to use points instead. - // Remove this "else if" block, and - // make header_found true for SVG if gl2ps is fixed. - - // Specify number of characters because STR may have - // come from std::fread and not end with a NUL - // character. - std::string srchstr (str, nread); - std::size_t pos = srchstr.find (" "pt" - // Assume the second occurrence is at the same line - pos = srchstr.find ("px", pos); - srchstr[pos+1] = 't'; // "px" -> "pt" - std::strcpy (str, srchstr.c_str ()); - } - } - } - - nwrite = std::fwrite (str, 1, nread, m_fp); - if (nwrite != nread) - { - // FIXME: is this the best thing to do here? - respond_to_pending_signals (); // Clear SIGPIPE signal - error ("gl2ps_renderer::draw: internal pipe error"); - } - } - } + // Don't remove hidden primitives when some of them are transparent + GLint opts; + gl2psGetOptions (&opts); + if (has_alpha (props.get___myhandle__ ())) + { + opts &= ~GL2PS_OCCLUSION_CULL; + // FIXME: currently the GL2PS_BLEND (which is more an equivalent of + // GL_ALPHA_TEST than GL_BLEND) is not working on a per primitive + // basis. We thus set it once per viewport. + gl2psEnable (GL2PS_BLEND); } else - opengl_renderer::draw (go); + { + opts |= GL2PS_OCCLUSION_CULL; + gl2psDisable (GL2PS_BLEND); + } + + gl2psSetOptions (opts); + + // Draw and finish () or there may be primitives missing in the gl2ps + // output. + opengl_renderer::draw_axes (props); + finish (); + + // Finalize viewport + GLint state = gl2psEndViewport (); + if (state == GL2PS_NO_FEEDBACK && props.is_visible ()) + warning ("gl2ps_renderer::draw_axes: empty feedback buffer and/or nothing else to print"); + else if (state == GL2PS_ERROR) + error ("gl2ps_renderer::draw_axes: gl2psEndPage returned GL2PS_ERROR"); + + m_buffer_overflow |= (state == GL2PS_OVERFLOW); + + // Don't draw background for subsequent viewports (legends, subplots, + // etc.) + gl2psGetOptions (&opts); + opts &= ~GL2PS_DRAW_BACKGROUND; + gl2psSetOptions (opts); } - int - gl2ps_renderer::alignment_to_mode (int ha, int va) const - { - int gl2psa = GL2PS_TEXT_BL; + void draw_text (const text::properties& props); + + void draw_image (const image::properties& props); + void draw_pixels (int w, int h, const float *data); + void draw_pixels (int w, int h, const uint8_t *data); + void draw_pixels (int w, int h, const uint16_t *data); - if (ha == 0) - { - if (va == 0 || va == 3) - gl2psa=GL2PS_TEXT_BL; - else if (va == 2) - gl2psa=GL2PS_TEXT_TL; - else if (va == 1) - gl2psa=GL2PS_TEXT_CL; - } - else if (ha == 2) - { - if (va == 0 || va == 3) - gl2psa=GL2PS_TEXT_BR; - else if (va == 2) - gl2psa=GL2PS_TEXT_TR; - else if (va == 1) - gl2psa=GL2PS_TEXT_CR; - } - else if (ha == 1) + void init_marker (const std::string& m, double size, float width) + { + opengl_renderer::init_marker (m, size, width); + + // FIXME: gl2ps can't handle closed contours so we set linecap/linejoin + // round to obtain a better looking result for some markers. + if (m == "o" || m == "v" || m == "^" || m == ">" || m == "<" || m == "h" + || m == "hexagram" || m == "p" || m == "pentagram") { - if (va == 0 || va == 3) - gl2psa=GL2PS_TEXT_B; - else if (va == 2) - gl2psa=GL2PS_TEXT_T; - else if (va == 1) - gl2psa=GL2PS_TEXT_C; + set_linejoin ("round"); + set_linecap ("round"); } - - return gl2psa; - } - - void - gl2ps_renderer::fix_strlist_position (double x, double y, double z, - Matrix box, double rotation, - std::list& lst) - { - for (auto& txtobj : lst) + else { - // Get pixel coordinates - ColumnVector coord_pix = get_transform ().transform (x, y, z, false); - - // Translate and rotate - double rot = rotation * 4.0 * atan (1.0) / 180; - coord_pix(0) += (txtobj.get_x () + box(0))*cos (rot) - - (txtobj.get_y () + box(1))*sin (rot); - coord_pix(1) -= (txtobj.get_y () + box(1))*cos (rot) - + (txtobj.get_x () + box(0))*sin (rot); - - GLint vp[4]; - m_glfcns.glGetIntegerv (GL_VIEWPORT, vp); - - txtobj.set_x (coord_pix(0)); - txtobj.set_y (vp[3] - coord_pix(1)); - txtobj.set_z (coord_pix(2)); + set_linejoin ("miter"); + set_linecap ("square"); } } - static std::string - code_to_symbol (uint32_t code) + void set_linestyle (const std::string& s, bool use_stipple = false, + double linewidth = 0.5) { - std::string retval; - - uint32_t idx = code - 945; - if (idx < 25) - { - std::string characters ("abgdezhqiklmnxoprVstufcyw"); - retval = characters[idx]; - return retval; - } + opengl_renderer::set_linestyle (s, use_stipple, linewidth); - idx = code - 913; - if (idx < 25) - { - std::string characters ("ABGDEZHQIKLMNXOPRVSTUFCYW"); - retval = characters[idx]; - } - else if (code == 978) - retval = "U"; - else if (code == 215) - retval = "\xb4"; - else if (code == 177) - retval = "\xb1"; - else if (code == 8501) - retval = "\xc0"; - else if (code == 8465) - retval = "\xc1"; - else if (code == 8242) - retval = "\xa2"; - else if (code == 8736) - retval = "\xd0"; - else if (code == 172) - retval = "\xd8"; - else if (code == 9829) - retval = "\xa9"; - else if (code == 8472) - retval = "\xc3"; - else if (code == 8706) - retval = "\xb6"; - else if (code == 8704) - retval = "\x22"; - else if (code == 9827) - retval = "\xa7"; - else if (code == 9824) - retval = "\xaa"; - else if (code == 8476) - retval = "\xc2"; - else if (code == 8734) - retval = "\xa5"; - else if (code == 8730) - retval = "\xd6"; - else if (code == 8707) - retval = "\x24"; - else if (code == 9830) - retval = "\xa8"; - else if (code == 8747) - retval = "\xf2"; - else if (code == 8727) - retval = "\x2a"; - else if (code == 8744) - retval = "\xda"; - else if (code == 8855) - retval = "\xc4"; - else if (code == 8901) - retval = "\xd7"; - else if (code == 8728) - retval = "\xb0"; - else if (code == 8745) - retval = "\xc7"; - else if (code == 8743) - retval = "\xd9"; - else if (code == 8856) - retval = "\xc6"; - else if (code == 8729) - retval = "\xb7"; - else if (code == 8746) - retval = "\xc8"; - else if (code == 8853) - retval = "\xc5"; - else if (code == 8804) - retval = "\xa3"; - else if (code == 8712) - retval = "\xce"; - else if (code == 8839) - retval = "\xca"; - else if (code == 8801) - retval = "\xba"; - else if (code == 8773) - retval = "\x40"; - else if (code == 8834) - retval = "\xcc"; - else if (code == 8805) - retval = "\xb3"; - else if (code == 8715) - retval = "\x27"; - else if (code == 8764) - retval = "\x7e"; - else if (code == 8733) - retval = "\xb5"; - else if (code == 8838) - retval = "\xcd"; - else if (code == 8835) - retval = "\xc9"; - else if (code == 8739) - retval = "\xbd"; - else if (code == 8776) - retval = "\xbb"; - else if (code == 8869) - retval = "\x5e"; - else if (code == 8656) - retval = "\xdc"; - else if (code == 8592) - retval = "\xac"; - else if (code == 8658) - retval = "\xde"; - else if (code == 8594) - retval = "\xae"; - else if (code == 8596) - retval = "\xab"; - else if (code == 8593) - retval = "\xad"; - else if (code == 8595) - retval = "\xaf"; - else if (code == 8970) - retval = "\xeb"; - else if (code == 8971) - retval = "\xfb"; - else if (code == 10216) - retval = "\xe1"; - else if (code == 10217) - retval = "\xf1"; - else if (code == 8968) - retval = "\xe9"; - else if (code == 8969) - retval = "\xf9"; - else if (code == 8800) - retval = "\xb9"; - else if (code == 8230) - retval = "\xbc"; - else if (code == 176) - retval = "\xb0"; - else if (code == 8709) - retval = "\xc6"; - else if (code == 169) - retval = "\xd3"; - - if (retval.empty ()) - warning ("print: unhandled symbol %d", code); - - return retval; + if (s == "-" && ! use_stipple) + gl2psDisable (GL2PS_LINE_STIPPLE); + else + gl2psEnable (GL2PS_LINE_STIPPLE); } - static std::string - select_font (caseless_str fn, bool isbold, bool isitalic) + void set_linecap (const std::string& s) { - std::transform (fn.begin (), fn.end (), fn.begin (), ::tolower); - std::string fontname; - if (fn == "times" || fn == "times-roman") - { - if (isitalic && isbold) - fontname = "Times-BoldItalic"; - else if (isitalic) - fontname = "Times-Italic"; - else if (isbold) - fontname = "Times-Bold"; - else - fontname = "Times-Roman"; - } - else if (fn == "courier") - { - if (isitalic && isbold) - fontname = "Courier-BoldOblique"; - else if (isitalic) - fontname = "Courier-Oblique"; - else if (isbold) - fontname = "Courier-Bold"; - else - fontname = "Courier"; - } - else if (fn == "symbol") - fontname = "Symbol"; - else if (fn == "zapfdingbats") - fontname = "ZapfDingbats"; - else - { - if (isitalic && isbold) - fontname = "Helvetica-BoldOblique"; - else if (isitalic) - fontname = "Helvetica-Oblique"; - else if (isbold) - fontname = "Helvetica-Bold"; - else - fontname = "Helvetica"; - } - return fontname; - } + opengl_renderer::set_linejoin (s); - static void - escape_character (const std::string chr, std::string& str) - { - std::size_t idx = str.find (chr); - while (idx != std::string::npos) - { - str.insert (idx, 1, '\\'); - idx = str.find (chr, idx + 2); - } +#if defined (HAVE_GL2PSLINEJOIN) + if (s == "butt") + gl2psLineCap (GL2PS_LINE_CAP_BUTT); + else if (s == "square") + gl2psLineCap (GL2PS_LINE_CAP_SQUARE); + else if (s == "round") + gl2psLineCap (GL2PS_LINE_CAP_ROUND); +#endif } - std::string - gl2ps_renderer::format_svg_element (std::string str, Matrix box, - double rotation, ColumnVector coord_pix, - Matrix color) + void set_linejoin (const std::string& s) { - // Extract elements and change their id to avoid conflict with - // defs coming from another svg string - std::string::size_type n1 = str.find (""); - if (n1 == std::string::npos) - return std::string (); - - std::string id, new_id; - n1 = str.find (""); - n2 = str.find ("") + 7; - - std::string defs = str.substr (n1, n2-n1); - - // Extract the group containing the elements and transform its - // coordinates using the bbox and coordinates info. +#if defined (HAVE_GL2PSLINEJOIN) + if (s == "round") + gl2psLineJoin (GL2PS_LINE_JOIN_ROUND); + else if (s == "miter") + gl2psLineJoin (GL2PS_LINE_JOIN_MITER); + else if (s == "chamfer") + gl2psLineJoin (GL2PS_LINE_JOIN_BEVEL); +#endif + } - // Extract the original viewBox anchor - n1 = str.find ("viewBox='") + 9; - if (n1 == std::string::npos) - return std::string (); - - n2 = str.find (" ", n1); - double original_x0 = std::stod (str.substr (n1, n2-n1)); - - n1 = n2+1; - n2 = str.find (" ", n1); - double original_y0 = std::stod (str.substr (n1, n2-n1)); - - // First look for local transform in the original svg - std::string orig_trans; - n1 = str.find ("", n1) + 4; - - // The first applied transformation is the right-most - // 1* Apply original transform - std::string tform = orig_trans; - - // 2* Move the anchor to the final position - tform = std::string ("translate") - + "(" + std::to_string (box(0) - original_x0 + coord_pix(0)) - + "," + std::to_string (-(box(3) + box(1)) - original_y0 + coord_pix(1)) - + ") " + tform; - - // 3* Rotate around the final position - if (rotation != 0) - tform = std::string ("rotate") - + "(" + std::to_string (-rotation) - + "," + std::to_string (coord_pix(0)) - + "," + std::to_string (coord_pix(1)) - + ") " + tform; - - // Fill color - std::string fill = "fill='rgb(" - + std::to_string (static_cast (color(0) * 255.0)) + "," - + std::to_string (static_cast (color(1) * 255.0)) + "," - + std::to_string (static_cast (color(2) * 255.0)) + ")' "; - - std::string use_group = "& lst) - { - //Use pixel coordinates to conform to gl2ps - ColumnVector coord_pix = get_transform ().transform (x, y, z, false); - - if (lst.empty ()) - return ""; - - // This may already be an svg image. - std::string svg = lst.front ().get_svg_element (); - if (! svg.empty ()) - return format_svg_element (svg, box, rotation, coord_pix, - lst.front ().get_color ()); - - // Rotation and translation are applied to the whole group - std::ostringstream os; - os << R"(get_family (); - std::string weight = p->get_weight (); - std::string angle = p->get_angle (); - double size = p->get_size (); - - os << "font-family=\"" << name << "\" " - << "font-weight=\"" << weight << "\" " - << "font-style=\"" << angle << "\" " - << "font-size=\"" << size << "\">"; - - - // Build a text element for each element in the strlist - for (p = lst.begin (); p != lst.end (); p++) - { - os << "get_family ())) - os << "font-family=\"" << p->get_family () << "\" "; - - if (weight.compare (p->get_weight ())) - os << "font-weight=\"" << p->get_weight () << "\" "; - - if (angle.compare (p->get_angle ())) - os << "font-style=\"" << p->get_angle () << "\" "; - - if (size != p->get_size ()) - os << "font-size=\"" << p->get_size () << "\" "; - - os << "y=\"" << - p->get_y () << "\" "; - - Matrix col = p->get_color (); - os << "fill=\"rgb(" << col(0)*255 << "," - << col(1)*255 << "," << col(2)*255 << ")\" "; - - // provide an x coordinate for each character in the string - os << "x=\""; - std::vector xdata = p->get_xdata (); - for (auto q = xdata.begin (); q != xdata.end (); q++) - os << (*q) << " "; - os << '"'; - - os << '>'; - - // translate unicode and special xml characters - if (p->get_code ()) - os << "&#" << p->get_code () << ";"; - else - { - const std::string str = p->get_string (); - for (auto q = str.begin (); q != str.end (); q++) - { - std::stringstream chr; - chr << *q; - if (chr.str () == "\"") - os << """; - else if (chr.str () == "'") - os << "'"; - else if (chr.str () == "&") - os << "&"; - else if (chr.str () == "<") - os << "<"; - else if (chr.str () == ">") - os << ">"; - else - os << chr.str (); - } - } - os << ""; - } - os << ""; - - return os.str (); - } - - std::string - gl2ps_renderer::strlist_to_ps (double x, double y, double z, - Matrix box, double rotation, - std::list& lst) - { - if (lst.empty ()) - return ""; - else if (lst.size () == 1) - { - static bool warned = false; - // This may be an svg image, not handled in native eps format. - if (! lst.front ().get_svg_element ().empty ()) - { - if (! warned) - { - warned = true; - warning_with_id ("Octave:print:unhandled-svg-content", - "print: unhandled LaTeX strings. " - "Use -svgconvert option or -d*latex* output " - "device."); - } - return ""; - } - } - - // Translate and rotate coordinates in order to use bottom-left alignment - fix_strlist_position (x, y, z, box, rotation, lst); - Matrix prev_color (1, 3, -1); - - std::ostringstream ss; - ss << "gsave\n"; - - static bool warned = false; - - for (const auto& txtobj : lst) - { - // Color - if (txtobj.get_color () != prev_color) - { - prev_color = txtobj.get_color (); - for (int i = 0; i < 3; i++) - ss << prev_color(i) << " "; - - ss << "C\n"; - } - - // String - std::string str; - if (txtobj.get_code ()) - { - m_fontname = "Symbol"; - str = code_to_symbol (txtobj.get_code ()); - } - else - { - m_fontname = select_font (txtobj.get_name (), - txtobj.get_weight () == "bold", - txtobj.get_angle () == "italic"); - - // Check that the string is composed of single byte characters - const std::string tmpstr = txtobj.get_string (); - const uint8_t *c - = reinterpret_cast (tmpstr.c_str ()); - - for (std::size_t i = 0; i < tmpstr.size ();) - { - int mblen = octave_u8_strmblen_wrapper (c + i); - - // Replace multibyte or non ascii characters by a question mark - if (mblen > 1) - { - str += "?"; - if (! warned) - { - warning_with_id ("Octave:print:unsupported-multibyte", - "print: only ASCII characters are " - "supported for EPS and derived " - "formats. Use the '-svgconvert' " - "option for better font support."); - warned = true; - } - } - else if (mblen < 1) - { - mblen = 1; - str += "?"; - if (! warned) - { - warning_with_id ("Octave:print:unhandled-character", - "print: only ASCII characters are " - "supported for EPS and derived " - "formats. Use the '-svgconvert' " - "option for better font support."); - warned = true; - } - } - else - str += tmpstr.at (i); - - i += mblen; - } - } - - escape_character ("\\", str); - escape_character ("(", str); - escape_character (")", str); - - ss << "(" << str << ") ["; - - std::vector xdata = txtobj.get_xdata (); - for (std::size_t i = 1; i < xdata.size (); i++) - ss << xdata[i] - xdata[i-1] << " "; - - ss << "10] " << rotation << " " << txtobj.get_x () - << " " << txtobj.get_y () << " " << txtobj.get_size () - << " /" << m_fontname << " SRX\n"; - } - - ss << "grestore\n"; - - return ss.str (); - } - - Matrix - gl2ps_renderer::render_text (const std::string& txt, - double x, double y, double z, - int ha, int va, double rotation) - { - std::string saved_font = m_fontname; - - if (txt.empty ()) - return Matrix (1, 4, 0.0); - - Matrix bbox; - std::string str = txt; - std::list lst; - - text_to_strlist (str, lst, bbox, ha, va, rotation); - m_glfcns.glRasterPos3d (x, y, z); - - // For svg/eps directly dump a preformated text element into gl2ps output - if (m_term.find ("svg") != std::string::npos) - { - std::string elt = strlist_to_svg (x, y, z, bbox, rotation, lst); - if (! elt.empty ()) - gl2psSpecial (GL2PS_SVG, elt.c_str ()); - } - else if (m_term.find ("eps") != std::string::npos) - { - std::string elt = strlist_to_ps (x, y, z, bbox, rotation, lst); - if (! elt.empty ()) - gl2psSpecial (GL2PS_EPS, elt.c_str ()); - - } - else - gl2psTextOpt (str.c_str (), m_fontname.c_str (), m_fontsize, - alignment_to_mode (ha, va), rotation); - - m_fontname = saved_font; - - return bbox; - } - - void - gl2ps_renderer::set_font (const base_properties& props) - { - opengl_renderer::set_font (props); - - // Set the interpreter so that text_to_pixels can parse strings properly - if (props.has_property ("interpreter")) - set_interpreter (props.get ("interpreter").string_value ()); - - m_fontsize = props.get ("__fontsize_points__").double_value (); - - caseless_str fn = props.get ("fontname").xtolower ().string_value (); - bool isbold - =(props.get ("fontweight").xtolower ().string_value () == "bold"); - bool isitalic - = (props.get ("fontangle").xtolower ().string_value () == "italic"); - - m_fontname = select_font (fn, isbold, isitalic); - } - - void - gl2ps_renderer::draw_image (const image::properties& props) - { - octave_value cdata = props.get_color_data (); - dim_vector dv (cdata.dims ()); - int h = dv(0); - int w = dv(1); - - Matrix x = props.get_xdata ().matrix_value (); - Matrix y = props.get_ydata ().matrix_value (); - - // Someone wants us to draw an empty image? No way. - if (x.isempty () || y.isempty ()) - return; - - // Sort x/ydata and mark flipped dimensions - bool xflip = false; - if (x(0) > x(1)) - { - std::swap (x(0), x(1)); - xflip = true; - } - else if (w > 1 && x(1) == x(0)) - x(1) = x(1) + (w-1); - - bool yflip = false; - if (y(0) > y(1)) - { - std::swap (y(0), y(1)); - yflip = true; - } - else if (h > 1 && y(1) == y(0)) - y(1) = y(1) + (h-1); - - - const ColumnVector p0 = m_xform.transform (x(0), y(0), 0); - const ColumnVector p1 = m_xform.transform (x(1), y(1), 0); - - if (math::isnan (p0(0)) || math::isnan (p0(1)) - || math::isnan (p1(0)) || math::isnan (p1(1))) - { - warning ("opengl_renderer: image X,Y data too large to draw"); - return; - } - - // image pixel size in screen pixel units - float pix_dx, pix_dy; - // image pixel size in normalized units - float nor_dx, nor_dy; - - if (w > 1) - { - pix_dx = (p1(0) - p0(0)) / (w-1); - nor_dx = (x(1) - x(0)) / (w-1); - } - else - { - const ColumnVector p1w = m_xform.transform (x(1) + 1, y(1), 0); - pix_dx = p1w(0) - p0(0); - nor_dx = 1; - } - - if (h > 1) - { - pix_dy = (p1(1) - p0(1)) / (h-1); - nor_dy = (y(1) - y(0)) / (h-1); - } - else - { - const ColumnVector p1h = m_xform.transform (x(1), y(1) + 1, 0); - pix_dy = p1h(1) - p0(1); - nor_dy = 1; - } - - // OpenGL won't draw any of the image if its origin is outside the - // viewport/clipping plane so we must do the clipping ourselves. - - int j0, j1, jj, i0, i1, ii; - j0 = 0, j1 = w; - i0 = 0, i1 = h; - - float im_xmin = x(0) - nor_dx/2; - float im_xmax = x(1) + nor_dx/2; - float im_ymin = y(0) - nor_dy/2; - float im_ymax = y(1) + nor_dy/2; - - // Clip to axes or viewport - bool do_clip = props.is_clipping (); - Matrix vp = get_viewport_scaled (); - - ColumnVector vp_lim_min - = m_xform.untransform (std::numeric_limits ::epsilon (), - std::numeric_limits ::epsilon ()); - ColumnVector vp_lim_max = m_xform.untransform (vp(2), vp(3)); - - if (vp_lim_min(0) > vp_lim_max(0)) - std::swap (vp_lim_min(0), vp_lim_max(0)); - - if (vp_lim_min(1) > vp_lim_max(1)) - std::swap (vp_lim_min(1), vp_lim_max(1)); - - float clip_xmin - = do_clip ? (vp_lim_min(0) > m_xmin ? vp_lim_min(0) : m_xmin) - : vp_lim_min(0); - - float clip_ymin - = do_clip ? (vp_lim_min(1) > m_ymin ? vp_lim_min(1) : m_ymin) - : vp_lim_min(1); - - float clip_xmax - = do_clip ? (vp_lim_max(0) < m_xmax ? vp_lim_max(0) : m_xmax) - : vp_lim_max(0); - - float clip_ymax - = do_clip ? (vp_lim_max(1) < m_ymax ? vp_lim_max(1) : m_ymax) - : vp_lim_max(1); - - if (im_xmin < clip_xmin) - j0 += (clip_xmin - im_xmin)/nor_dx + 1; - - if (im_xmax > clip_xmax) - j1 -= (im_xmax - clip_xmax)/nor_dx; - - if (im_ymin < clip_ymin) - i0 += (clip_ymin - im_ymin)/nor_dy + 1; - - if (im_ymax > clip_ymax) - i1 -= (im_ymax - clip_ymax)/nor_dy; - - if (i0 >= i1 || j0 >= j1) - return; - - float zoom_x; - m_glfcns.glGetFloatv (GL_ZOOM_X, &zoom_x); - float zoom_y; - m_glfcns.glGetFloatv (GL_ZOOM_Y, &zoom_y); - - m_glfcns.glPixelZoom (m_devpixratio * pix_dx, - m_devpixratio * pix_dy); - m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0); - - // Expect RGB data - if (dv.ndims () == 3 && dv(2) == 3) - { - if (cdata.is_double_type ()) - { - const NDArray xcdata = cdata.array_value (); - - OCTAVE_LOCAL_BUFFER (GLfloat, a, - static_cast (3)*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii, jj, 0); - a[idx+1] = xcdata(ii, jj, 1); - a[idx+2] = xcdata(ii, jj, 2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else if (cdata.is_single_type ()) - { - const FloatNDArray xcdata = cdata.float_array_value (); - - OCTAVE_LOCAL_BUFFER (GLfloat, a, - static_cast (3)*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii, jj, 0); - a[idx+1] = xcdata(ii, jj, 1); - a[idx+2] = xcdata(ii, jj, 2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else if (cdata.is_uint8_type ()) - { - const uint8NDArray xcdata = cdata.uint8_array_value (); - - OCTAVE_LOCAL_BUFFER (GLubyte, a, - static_cast (3)*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii, jj, 0); - a[idx+1] = xcdata(ii, jj, 1); - a[idx+2] = xcdata(ii, jj, 2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else if (cdata.is_uint16_type ()) - { - const uint16NDArray xcdata = cdata.uint16_array_value (); - - OCTAVE_LOCAL_BUFFER (GLushort, a, - static_cast (3)*(j1-j0)*(i1-i0)); - - for (int i = i0; i < i1; i++) - { - for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) - { - if (! yflip) - ii = i; - else - ii = h - i - 1; - - if (! xflip) - jj = j; - else - jj = w - j - 1; - - a[idx] = xcdata(ii, jj, 0); - a[idx+1] = xcdata(ii, jj, 1); - a[idx+2] = xcdata(ii, jj, 2); - } - } - - draw_pixels (j1-j0, i1-i0, a); - - } - else - warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)"); - - m_glfcns.glPixelZoom (zoom_x, zoom_y); - + gl2psDisable (GL2PS_POLYGON_OFFSET_FILL); + opengl_renderer::set_polygon_offset (on, offset); } } - void - gl2ps_renderer::draw_pixels (int w, int h, const float *data) - { - // Clip data between 0 and 1 for float values - OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast (3)*w*h); - - for (int i = 0; i < 3*h*w; i++) - tmp_data[i] = (data[i] < 0.0f ? 0.0f : (data[i] > 1.0f ? 1.0f : data[i])); - - gl2psDrawPixels (w, h, 0, 0, GL_RGB, GL_FLOAT, tmp_data); - } - - void - gl2ps_renderer::draw_pixels (int w, int h, const uint8_t *data) + void set_linewidth (float w) { - // gl2psDrawPixels only supports the GL_FLOAT type. - - OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast (3)*w*h); - - static const float maxval = std::numeric_limits::max (); - - for (int i = 0; i < 3*w*h; i++) - tmp_data[i] = data[i] / maxval; - - draw_pixels (w, h, tmp_data); - } - - void - gl2ps_renderer::draw_pixels (int w, int h, const uint16_t *data) - { - // gl2psDrawPixels only supports the GL_FLOAT type. - - OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast (3)*w*h); - - static const float maxval = std::numeric_limits::max (); - - for (int i = 0; i < 3*w*h; i++) - tmp_data[i] = data[i] / maxval; - - draw_pixels (w, h, tmp_data); + gl2psLineWidth (w); } - void - gl2ps_renderer::draw_text (const text::properties& props) - { - if (props.get_string ().isempty ()) - return; +private: + + // Use xform to compute the coordinates of the string list + // that have been parsed by freetype. + void fix_strlist_position (double x, double y, double z, + Matrix box, double rotation, + std::list& lst); + + // Build an svg text element from a list of parsed strings + std::string format_svg_element (std::string str, Matrix bbox, + double rotation, ColumnVector coord_pix, + Matrix color); + + std::string strlist_to_svg (double x, double y, double z, Matrix box, + double rotation, + std::list& lst); + + // Build a list of postscript commands from a list of parsed strings. + std::string strlist_to_ps (double x, double y, double z, Matrix box, + double rotation, + std::list& lst); + + int alignment_to_mode (int ha, int va) const; + + FILE *m_fp; + caseless_str m_term; + double m_fontsize; + std::string m_fontname; + bool m_buffer_overflow; + std::size_t m_svg_def_index; +}; + +static bool +has_2D_axes (const graphics_handle& h) +{ + bool retval = true; + + gh_manager& gh_mgr = __get_gh_manager__ (); + + graphics_object go = gh_mgr.get_object (h); + + if (! go.valid_object ()) + return retval; + + if (go.isa ("figure") || go.isa ("uipanel")) + { + Matrix children = go.get ("children").matrix_value (); + for (octave_idx_type ii = 0; ii < children.numel (); ii++) + { + retval = has_2D_axes (graphics_handle (children(ii))); + if (! retval) + break; + } + } + else if (go.isa ("axes")) + { + axes::properties& ap + = reinterpret_cast (go.get_properties ()); + retval = ap.get_is2D (true); + } + + return retval; +} + +static std::string +get_title (const graphics_handle& h) +{ + std::string retval; + + gh_manager& gh_mgr = __get_gh_manager__ (); + + graphics_object go = gh_mgr.get_object (h); + + if (! go.valid_object ()) + return retval; + + if (go.isa ("figure")) + { + figure::properties& fp + = reinterpret_cast (go.get_properties ()); + + retval = fp.get_title (); + } + + return retval; +} + +void +gl2ps_renderer::draw (const graphics_object& go, const std::string& print_cmd) +{ + static bool in_draw = false; + static std::string old_print_cmd; + static GLint buffsize; + + if (! in_draw) + { + unwind_protect frame; + + frame.protect_var (in_draw); + + in_draw = true; + + GLint gl2ps_term = GL2PS_PS; + if (m_term.find ("eps") != std::string::npos) + gl2ps_term = GL2PS_EPS; + else if (m_term.find ("pdf") != std::string::npos) + gl2ps_term = GL2PS_PDF; + else if (m_term.find ("ps") != std::string::npos) + gl2ps_term = GL2PS_PS; + else if (m_term.find ("svg") != std::string::npos) + gl2ps_term = GL2PS_SVG; + else if (m_term.find ("pgf") != std::string::npos) + gl2ps_term = GL2PS_PGF; + else if (m_term.find ("tex") != std::string::npos) + gl2ps_term = GL2PS_TEX; + else + warning ("gl2ps_renderer::draw: Unknown terminal %s, using 'ps'", + m_term.c_str ()); + + GLint gl2ps_text = 0; + if (m_term.find ("notxt") != std::string::npos) + gl2ps_text = GL2PS_NO_TEXT; + + // Find Title for plot + const graphics_handle& myhandle = go.get ("__myhandle__"); + std::string plot_title = get_title (myhandle); + if (plot_title.empty ()) + plot_title = "Octave plot"; + + // Default sort order optimizes for 3D plots + GLint gl2ps_sort = GL2PS_BSP_SORT; + + // FIXME: gl2ps does not provide a way to change the sorting algorithm + // on a viewport basis, we thus disable sorting only if all axes are 2D + if (has_2D_axes (myhandle)) + gl2ps_sort = GL2PS_NO_SORT; + + // Use a temporary file in case an overflow happens + std::string tmpfile (sys::tempnam (sys::env::get_temp_directory (), + "oct-")); + FILE *tmpf = sys::fopen_tmp (tmpfile, "w+b"); + + if (! tmpf) + error ("gl2ps_renderer::draw: couldn't open temporary file for printing"); + + frame.add ([=] () { std::fclose (tmpf); }); + + // Reset buffsize, unless this is 2nd pass of a texstandalone print. + if (m_term.find ("tex") == std::string::npos) + buffsize = 2*1024*1024; + else + buffsize /= 2; + + m_buffer_overflow = true; - draw_text_background (props, true); + while (m_buffer_overflow) + { + m_buffer_overflow = false; + buffsize *= 2; + + std::fseek (tmpf, 0, SEEK_SET); + octave_ftruncate_wrapper (fileno (tmpf), 0); + + // For LaTeX output the print process uses 2 drawnow() commands. + // The first one is for the pdf/ps/eps graph to be included. The + // print_cmd is saved as old_print_cmd. Then the second drawnow() + // outputs the tex-file and the graphic filename to be included is + // extracted from old_print_cmd. + + std::string include_graph; + + std::size_t found_redirect = old_print_cmd.find ('>'); + + if (found_redirect != std::string::npos) + include_graph = old_print_cmd.substr (found_redirect + 1); + else + include_graph = old_print_cmd; + + std::size_t n_begin = include_graph.find_first_not_of (R"( "')"); + + if (n_begin != std::string::npos) + { + // Strip any quote characters characters around filename + std::size_t n_end = include_graph.find_last_not_of (R"( "')"); + include_graph = include_graph.substr (n_begin, + n_end - n_begin + 1); + // Strip path from filename + n_begin = include_graph.find_last_of (sys::file_ops::dir_sep_chars ()); + include_graph = include_graph.substr (n_begin + 1); + } + else + include_graph = "foobar-inc"; + + // FIXME: workaround gl2ps drawing 2 background planes, the first + // eventually being black and producing visual artifacts + const figure::properties& fprop + = dynamic_cast (go.get_properties ()); + Matrix c = fprop.get_color_rgb (); + m_glfcns.glClearColor (c(0), c(1), c(2), 1); + + // Allow figures to be printed at arbitrary resolution + set_device_pixel_ratio (fprop.get___device_pixel_ratio__ ()); + + // GL2PS_SILENT was removed to allow gl2ps to print errors on stderr + GLint ret = gl2psBeginPage (plot_title.c_str (), "Octave", + nullptr, gl2ps_term, gl2ps_sort, + (GL2PS_BEST_ROOT + | gl2ps_text + | GL2PS_DRAW_BACKGROUND + | GL2PS_NO_PS3_SHADING + | GL2PS_USE_CURRENT_VIEWPORT), + GL_RGBA, 0, nullptr, 0, 0, 0, + buffsize, tmpf, include_graph.c_str ()); + if (ret == GL2PS_ERROR) + { + old_print_cmd.clear (); + error ("gl2ps_renderer::draw: gl2psBeginPage returned GL2PS_ERROR"); + } + + opengl_renderer::draw (go); + + if (m_buffer_overflow) + warning ("gl2ps_renderer::draw: retrying with buffer size: %.1E B\n", double (2*buffsize)); + + if (! m_buffer_overflow) + old_print_cmd = print_cmd; + + // Don't check return value of gl2psEndPage, it is not meaningful. + // Errors and warnings are checked after gl2psEndViewport in + // gl2ps_renderer::draw_axes instead. + gl2psEndPage (); + } + + // Copy temporary file to pipe + std::fseek (tmpf, 0, SEEK_SET); + char str[8192]; // 8 kB is a common kernel buffersize + std::size_t nread, nwrite; + nread = 1; + + // In EPS terminal read the header line by line and insert a + // new procedure + const char *fcn = "/SRX { gsave FCT moveto rotate xshow grestore } BD\n"; + bool header_found = ! (m_term.find ("eps") != std::string::npos + || m_term.find ("svg") != std::string::npos); + + while (! feof (tmpf) && nread) + { + if (! header_found && std::fgets (str, 8192, tmpf)) + nread = strlen (str); + else + nread = std::fread (str, 1, 8192, tmpf); + + if (nread) + { + if (! header_found && std::strncmp (str, "/SBCR", 5) == 0) + { + header_found = true; + nwrite = std::fwrite (fcn, 1, strlen (fcn), m_fp); + if (nwrite != strlen (fcn)) + { + // FIXME: is this the best thing to do here? + respond_to_pending_signals (); + error ("gl2ps_renderer::draw: internal pipe error"); + } + } + else if (m_term.find ("svg") != std::string::npos) + { + // FIXME: gl2ps uses pixel units for SVG format. + // Modify resulting svg to use points instead. + // Remove this "else if" block, and + // make header_found true for SVG if gl2ps is fixed. + + // Specify number of characters because STR may have + // come from std::fread and not end with a NUL + // character. + std::string srchstr (str, nread); + std::size_t pos = srchstr.find (" "pt" + // Assume the second occurrence is at the same line + pos = srchstr.find ("px", pos); + srchstr[pos+1] = 't'; // "px" -> "pt" + std::strcpy (str, srchstr.c_str ()); + } + } + } + + nwrite = std::fwrite (str, 1, nread, m_fp); + if (nwrite != nread) + { + // FIXME: is this the best thing to do here? + respond_to_pending_signals (); // Clear SIGPIPE signal + error ("gl2ps_renderer::draw: internal pipe error"); + } + } + } + } + else + opengl_renderer::draw (go); +} + +int +gl2ps_renderer::alignment_to_mode (int ha, int va) const +{ + int gl2psa = GL2PS_TEXT_BL; - // First set font properties: freetype will use them to compute - // coordinates and gl2ps will retrieve the color directly from the - // feedback buffer - set_font (props); - set_color (props.get_color_rgb ()); + if (ha == 0) + { + if (va == 0 || va == 3) + gl2psa=GL2PS_TEXT_BL; + else if (va == 2) + gl2psa=GL2PS_TEXT_TL; + else if (va == 1) + gl2psa=GL2PS_TEXT_CL; + } + else if (ha == 2) + { + if (va == 0 || va == 3) + gl2psa=GL2PS_TEXT_BR; + else if (va == 2) + gl2psa=GL2PS_TEXT_TR; + else if (va == 1) + gl2psa=GL2PS_TEXT_CR; + } + else if (ha == 1) + { + if (va == 0 || va == 3) + gl2psa=GL2PS_TEXT_B; + else if (va == 2) + gl2psa=GL2PS_TEXT_T; + else if (va == 1) + gl2psa=GL2PS_TEXT_C; + } + + return gl2psa; +} + +void +gl2ps_renderer::fix_strlist_position (double x, double y, double z, + Matrix box, double rotation, + std::list& lst) +{ + for (auto& txtobj : lst) + { + // Get pixel coordinates + ColumnVector coord_pix = get_transform ().transform (x, y, z, false); + + // Translate and rotate + double rot = rotation * 4.0 * atan (1.0) / 180; + coord_pix(0) += (txtobj.get_x () + box(0))* cos (rot) + - (txtobj.get_y () + box(1))* sin (rot); + coord_pix(1) -= (txtobj.get_y () + box(1))* cos (rot) + + (txtobj.get_x () + box(0))* sin (rot); + + GLint vp[4]; + m_glfcns.glGetIntegerv (GL_VIEWPORT, vp); + + txtobj.set_x (coord_pix(0)); + txtobj.set_y (vp[3] - coord_pix(1)); + txtobj.set_z (coord_pix(2)); + } +} + +static std::string +code_to_symbol (uint32_t code) +{ + std::string retval; + + uint32_t idx = code - 945; + if (idx < 25) + { + std::string characters ("abgdezhqiklmnxoprVstufcyw"); + retval = characters[idx]; + return retval; + } - std::string saved_font = m_fontname; + idx = code - 913; + if (idx < 25) + { + std::string characters ("ABGDEZHQIKLMNXOPRVSTUFCYW"); + retval = characters[idx]; + } + else if (code == 978) + retval = "U"; + else if (code == 215) + retval = "\xb4"; + else if (code == 177) + retval = "\xb1"; + else if (code == 8501) + retval = "\xc0"; + else if (code == 8465) + retval = "\xc1"; + else if (code == 8242) + retval = "\xa2"; + else if (code == 8736) + retval = "\xd0"; + else if (code == 172) + retval = "\xd8"; + else if (code == 9829) + retval = "\xa9"; + else if (code == 8472) + retval = "\xc3"; + else if (code == 8706) + retval = "\xb6"; + else if (code == 8704) + retval = "\x22"; + else if (code == 9827) + retval = "\xa7"; + else if (code == 9824) + retval = "\xaa"; + else if (code == 8476) + retval = "\xc2"; + else if (code == 8734) + retval = "\xa5"; + else if (code == 8730) + retval = "\xd6"; + else if (code == 8707) + retval = "\x24"; + else if (code == 9830) + retval = "\xa8"; + else if (code == 8747) + retval = "\xf2"; + else if (code == 8727) + retval = "\x2a"; + else if (code == 8744) + retval = "\xda"; + else if (code == 8855) + retval = "\xc4"; + else if (code == 8901) + retval = "\xd7"; + else if (code == 8728) + retval = "\xb0"; + else if (code == 8745) + retval = "\xc7"; + else if (code == 8743) + retval = "\xd9"; + else if (code == 8856) + retval = "\xc6"; + else if (code == 8729) + retval = "\xb7"; + else if (code == 8746) + retval = "\xc8"; + else if (code == 8853) + retval = "\xc5"; + else if (code == 8804) + retval = "\xa3"; + else if (code == 8712) + retval = "\xce"; + else if (code == 8839) + retval = "\xca"; + else if (code == 8801) + retval = "\xba"; + else if (code == 8773) + retval = "\x40"; + else if (code == 8834) + retval = "\xcc"; + else if (code == 8805) + retval = "\xb3"; + else if (code == 8715) + retval = "\x27"; + else if (code == 8764) + retval = "\x7e"; + else if (code == 8733) + retval = "\xb5"; + else if (code == 8838) + retval = "\xcd"; + else if (code == 8835) + retval = "\xc9"; + else if (code == 8739) + retval = "\xbd"; + else if (code == 8776) + retval = "\xbb"; + else if (code == 8869) + retval = "\x5e"; + else if (code == 8656) + retval = "\xdc"; + else if (code == 8592) + retval = "\xac"; + else if (code == 8658) + retval = "\xde"; + else if (code == 8594) + retval = "\xae"; + else if (code == 8596) + retval = "\xab"; + else if (code == 8593) + retval = "\xad"; + else if (code == 8595) + retval = "\xaf"; + else if (code == 8970) + retval = "\xeb"; + else if (code == 8971) + retval = "\xfb"; + else if (code == 10216) + retval = "\xe1"; + else if (code == 10217) + retval = "\xf1"; + else if (code == 8968) + retval = "\xe9"; + else if (code == 8969) + retval = "\xf9"; + else if (code == 8800) + retval = "\xb9"; + else if (code == 8230) + retval = "\xbc"; + else if (code == 176) + retval = "\xb0"; + else if (code == 8709) + retval = "\xc6"; + else if (code == 169) + retval = "\xd3"; + + if (retval.empty ()) + warning ("print: unhandled symbol %d", code); - // Alignment - int halign = 0; - int valign = 0; + return retval; +} + +static std::string +select_font (caseless_str fn, bool isbold, bool isitalic) +{ + std::transform (fn.begin (), fn.end (), fn.begin (), ::tolower); + std::string fontname; + if (fn == "times" || fn == "times-roman") + { + if (isitalic && isbold) + fontname = "Times-BoldItalic"; + else if (isitalic) + fontname = "Times-Italic"; + else if (isbold) + fontname = "Times-Bold"; + else + fontname = "Times-Roman"; + } + else if (fn == "courier") + { + if (isitalic && isbold) + fontname = "Courier-BoldOblique"; + else if (isitalic) + fontname = "Courier-Oblique"; + else if (isbold) + fontname = "Courier-Bold"; + else + fontname = "Courier"; + } + else if (fn == "symbol") + fontname = "Symbol"; + else if (fn == "zapfdingbats") + fontname = "ZapfDingbats"; + else + { + if (isitalic && isbold) + fontname = "Helvetica-BoldOblique"; + else if (isitalic) + fontname = "Helvetica-Oblique"; + else if (isbold) + fontname = "Helvetica-Bold"; + else + fontname = "Helvetica"; + } + return fontname; +} + +static void +escape_character (const std::string chr, std::string& str) +{ + std::size_t idx = str.find (chr); + while (idx != std::string::npos) + { + str.insert (idx, 1, '\\'); + idx = str.find (chr, idx + 2); + } +} + +std::string +gl2ps_renderer::format_svg_element (std::string str, Matrix box, + double rotation, ColumnVector coord_pix, + Matrix color) +{ + // Extract elements and change their id to avoid conflict with + // defs coming from another svg string + std::string::size_type n1 = str.find (""); + if (n1 == std::string::npos) + return std::string (); + + std::string id, new_id; + n1 = str.find (""); + n2 = str.find ("") + 7; + + std::string defs = str.substr (n1, n2-n1); + + // Extract the group containing the elements and transform its + // coordinates using the bbox and coordinates info. + + // Extract the original viewBox anchor + n1 = str.find ("viewBox='") + 9; + if (n1 == std::string::npos) + return std::string (); + + n2 = str.find (" ", n1); + double original_x0 = std::stod (str.substr (n1, n2-n1)); + + n1 = n2+1; + n2 = str.find (" ", n1); + double original_y0 = std::stod (str.substr (n1, n2-n1)); + + // First look for local transform in the original svg + std::string orig_trans; + n1 = str.find ("", n1) + 4; + + // The first applied transformation is the right-most + // 1* Apply original transform + std::string tform = orig_trans; - if (props.horizontalalignment_is ("center")) - halign = 1; - else if (props.horizontalalignment_is ("right")) - halign = 2; + // 2* Move the anchor to the final position + tform = std::string ("translate") + + "(" + std::to_string (box(0) - original_x0 + coord_pix(0)) + + "," + std::to_string (-(box(3) + box(1)) - original_y0 + coord_pix(1)) + + ") " + tform; + + // 3* Rotate around the final position + if (rotation != 0) + tform = std::string ("rotate") + + "(" + std::to_string (-rotation) + + "," + std::to_string (coord_pix(0)) + + "," + std::to_string (coord_pix(1)) + + ") " + tform; + + // Fill color + std::string fill = "fill='rgb(" + + std::to_string (static_cast (color(0) * 255.0)) + "," + + std::to_string (static_cast (color(1) * 255.0)) + "," + + std::to_string (static_cast (color(2) * 255.0)) + ")' "; + + std::string use_group = "& lst) +{ + //Use pixel coordinates to conform to gl2ps + ColumnVector coord_pix = get_transform ().transform (x, y, z, false); + + if (lst.empty ()) + return ""; + + // This may already be an svg image. + std::string svg = lst.front ().get_svg_element (); + if (! svg.empty ()) + return format_svg_element (svg, box, rotation, coord_pix, + lst.front ().get_color ()); + + // Rotation and translation are applied to the whole group + std::ostringstream os; + os << R"(get_family (); + std::string weight = p->get_weight (); + std::string angle = p->get_angle (); + double size = p->get_size (); + + os << "font-family=\"" << name << "\" " + << "font-weight=\"" << weight << "\" " + << "font-style=\"" << angle << "\" " + << "font-size=\"" << size << "\">"; + + + // Build a text element for each element in the strlist + for (p = lst.begin (); p != lst.end (); p++) + { + os << "get_family ())) + os << "font-family=\"" << p->get_family () << "\" "; + + if (weight.compare (p->get_weight ())) + os << "font-weight=\"" << p->get_weight () << "\" "; + + if (angle.compare (p->get_angle ())) + os << "font-style=\"" << p->get_angle () << "\" "; + + if (size != p->get_size ()) + os << "font-size=\"" << p->get_size () << "\" "; + + os << "y=\"" << - p->get_y () << "\" "; + + Matrix col = p->get_color (); + os << "fill=\"rgb(" << col(0)*255 << "," + << col(1)*255 << "," << col(2)*255 << ")\" "; + + // provide an x coordinate for each character in the string + os << "x=\""; + std::vector xdata = p->get_xdata (); + for (auto q = xdata.begin (); q != xdata.end (); q++) + os << (*q) << " "; + os << '"'; + + os << '>'; + + // translate unicode and special xml characters + if (p->get_code ()) + os << "&#" << p->get_code () << ";"; + else + { + const std::string str = p->get_string (); + for (auto q = str.begin (); q != str.end (); q++) + { + std::stringstream chr; + chr << *q; + if (chr.str () == "\"") + os << """; + else if (chr.str () == "'") + os << "'"; + else if (chr.str () == "&") + os << "&"; + else if (chr.str () == "<") + os << "<"; + else if (chr.str () == ">") + os << ">"; + else + os << chr.str (); + } + } + os << ""; + } + os << ""; + + return os.str (); +} + +std::string +gl2ps_renderer::strlist_to_ps (double x, double y, double z, + Matrix box, double rotation, + std::list& lst) +{ + if (lst.empty ()) + return ""; + else if (lst.size () == 1) + { + static bool warned = false; + // This may be an svg image, not handled in native eps format. + if (! lst.front ().get_svg_element ().empty ()) + { + if (! warned) + { + warned = true; + warning_with_id ("Octave:print:unhandled-svg-content", + "print: unhandled LaTeX strings. " + "Use -svgconvert option or -d*latex* output " + "device."); + } + return ""; + } + } + + // Translate and rotate coordinates in order to use bottom-left alignment + fix_strlist_position (x, y, z, box, rotation, lst); + Matrix prev_color (1, 3, -1); + + std::ostringstream ss; + ss << "gsave\n"; + + static bool warned = false; + + for (const auto& txtobj : lst) + { + // Color + if (txtobj.get_color () != prev_color) + { + prev_color = txtobj.get_color (); + for (int i = 0; i < 3; i++) + ss << prev_color(i) << " "; + + ss << "C\n"; + } + + // String + std::string str; + if (txtobj.get_code ()) + { + m_fontname = "Symbol"; + str = code_to_symbol (txtobj.get_code ()); + } + else + { + m_fontname = select_font (txtobj.get_name (), + txtobj.get_weight () == "bold", + txtobj.get_angle () == "italic"); + + // Check that the string is composed of single byte characters + const std::string tmpstr = txtobj.get_string (); + const uint8_t *c + = reinterpret_cast (tmpstr.c_str ()); + + for (std::size_t i = 0; i < tmpstr.size ();) + { + int mblen = octave_u8_strmblen_wrapper (c + i); + + // Replace multibyte or non ascii characters by a question mark + if (mblen > 1) + { + str += "?"; + if (! warned) + { + warning_with_id ("Octave:print:unsupported-multibyte", + "print: only ASCII characters are " + "supported for EPS and derived " + "formats. Use the '-svgconvert' " + "option for better font support."); + warned = true; + } + } + else if (mblen < 1) + { + mblen = 1; + str += "?"; + if (! warned) + { + warning_with_id ("Octave:print:unhandled-character", + "print: only ASCII characters are " + "supported for EPS and derived " + "formats. Use the '-svgconvert' " + "option for better font support."); + warned = true; + } + } + else + str += tmpstr.at (i); + + i += mblen; + } + } + + escape_character ("\\", str); + escape_character ("(", str); + escape_character (")", str); + + ss << "(" << str << ") ["; + + std::vector xdata = txtobj.get_xdata (); + for (std::size_t i = 1; i < xdata.size (); i++) + ss << xdata[i] - xdata[i-1] << " "; + + ss << "10] " << rotation << " " << txtobj.get_x () + << " " << txtobj.get_y () << " " << txtobj.get_size () + << " /" << m_fontname << " SRX\n"; + } + + ss << "grestore\n"; + + return ss.str (); +} + +Matrix +gl2ps_renderer::render_text (const std::string& txt, + double x, double y, double z, + int ha, int va, double rotation) +{ + std::string saved_font = m_fontname; + + if (txt.empty ()) + return Matrix (1, 4, 0.0); + + Matrix bbox; + std::string str = txt; + std::list lst; + + text_to_strlist (str, lst, bbox, ha, va, rotation); + m_glfcns.glRasterPos3d (x, y, z); + + // For svg/eps directly dump a preformated text element into gl2ps output + if (m_term.find ("svg") != std::string::npos) + { + std::string elt = strlist_to_svg (x, y, z, bbox, rotation, lst); + if (! elt.empty ()) + gl2psSpecial (GL2PS_SVG, elt.c_str ()); + } + else if (m_term.find ("eps") != std::string::npos) + { + std::string elt = strlist_to_ps (x, y, z, bbox, rotation, lst); + if (! elt.empty ()) + gl2psSpecial (GL2PS_EPS, elt.c_str ()); + + } + else + gl2psTextOpt (str.c_str (), m_fontname.c_str (), m_fontsize, + alignment_to_mode (ha, va), rotation); + + m_fontname = saved_font; + + return bbox; +} + +void +gl2ps_renderer::set_font (const base_properties& props) +{ + opengl_renderer::set_font (props); + + // Set the interpreter so that text_to_pixels can parse strings properly + if (props.has_property ("interpreter")) + set_interpreter (props.get ("interpreter").string_value ()); + + m_fontsize = props.get ("__fontsize_points__").double_value (); + + caseless_str fn = props.get ("fontname").xtolower ().string_value (); + bool isbold + =(props.get ("fontweight").xtolower ().string_value () == "bold"); + bool isitalic + = (props.get ("fontangle").xtolower ().string_value () == "italic"); + + m_fontname = select_font (fn, isbold, isitalic); +} + +void +gl2ps_renderer::draw_image (const image::properties& props) +{ + octave_value cdata = props.get_color_data (); + dim_vector dv (cdata.dims ()); + int h = dv(0); + int w = dv(1); + + Matrix x = props.get_xdata ().matrix_value (); + Matrix y = props.get_ydata ().matrix_value (); + + // Someone wants us to draw an empty image? No way. + if (x.isempty () || y.isempty ()) + return; - if (props.verticalalignment_is ("top")) - valign = 2; - else if (props.verticalalignment_is ("baseline")) - valign = 3; - else if (props.verticalalignment_is ("middle")) - valign = 1; + // Sort x/ydata and mark flipped dimensions + bool xflip = false; + if (x(0) > x(1)) + { + std::swap (x(0), x(1)); + xflip = true; + } + else if (w > 1 && x(1) == x(0)) + x(1) = x(1) + (w-1); + + bool yflip = false; + if (y(0) > y(1)) + { + std::swap (y(0), y(1)); + yflip = true; + } + else if (h > 1 && y(1) == y(0)) + y(1) = y(1) + (h-1); + + + const ColumnVector p0 = m_xform.transform (x(0), y(0), 0); + const ColumnVector p1 = m_xform.transform (x(1), y(1), 0); + + if (math::isnan (p0(0)) || math::isnan (p0(1)) + || math::isnan (p1(0)) || math::isnan (p1(1))) + { + warning ("opengl_renderer: image X,Y data too large to draw"); + return; + } + + // image pixel size in screen pixel units + float pix_dx, pix_dy; + // image pixel size in normalized units + float nor_dx, nor_dy; + + if (w > 1) + { + pix_dx = (p1(0) - p0(0)) / (w-1); + nor_dx = (x(1) - x(0)) / (w-1); + } + else + { + const ColumnVector p1w = m_xform.transform (x(1) + 1, y(1), 0); + pix_dx = p1w(0) - p0(0); + nor_dx = 1; + } + + if (h > 1) + { + pix_dy = (p1(1) - p0(1)) / (h-1); + nor_dy = (y(1) - y(0)) / (h-1); + } + else + { + const ColumnVector p1h = m_xform.transform (x(1), y(1) + 1, 0); + pix_dy = p1h(1) - p0(1); + nor_dy = 1; + } + + // OpenGL won't draw any of the image if its origin is outside the + // viewport/clipping plane so we must do the clipping ourselves. + + int j0, j1, jj, i0, i1, ii; + j0 = 0, j1 = w; + i0 = 0, i1 = h; + + float im_xmin = x(0) - nor_dx/2; + float im_xmax = x(1) + nor_dx/2; + float im_ymin = y(0) - nor_dy/2; + float im_ymax = y(1) + nor_dy/2; + + // Clip to axes or viewport + bool do_clip = props.is_clipping (); + Matrix vp = get_viewport_scaled (); + + ColumnVector vp_lim_min + = m_xform.untransform (std::numeric_limits ::epsilon (), + std::numeric_limits ::epsilon ()); + ColumnVector vp_lim_max = m_xform.untransform (vp(2), vp(3)); + + if (vp_lim_min(0) > vp_lim_max(0)) + std::swap (vp_lim_min(0), vp_lim_max(0)); + + if (vp_lim_min(1) > vp_lim_max(1)) + std::swap (vp_lim_min(1), vp_lim_max(1)); + + float clip_xmin + = do_clip ? (vp_lim_min(0) > m_xmin ? vp_lim_min(0) : m_xmin) + : vp_lim_min(0); + + float clip_ymin + = do_clip ? (vp_lim_min(1) > m_ymin ? vp_lim_min(1) : m_ymin) + : vp_lim_min(1); + + float clip_xmax + = do_clip ? (vp_lim_max(0) < m_xmax ? vp_lim_max(0) : m_xmax) + : vp_lim_max(0); + + float clip_ymax + = do_clip ? (vp_lim_max(1) < m_ymax ? vp_lim_max(1) : m_ymax) + : vp_lim_max(1); + + if (im_xmin < clip_xmin) + j0 += (clip_xmin - im_xmin)/nor_dx + 1; + + if (im_xmax > clip_xmax) + j1 -= (im_xmax - clip_xmax)/nor_dx; + + if (im_ymin < clip_ymin) + i0 += (clip_ymin - im_ymin)/nor_dy + 1; + + if (im_ymax > clip_ymax) + i1 -= (im_ymax - clip_ymax)/nor_dy; + + if (i0 >= i1 || j0 >= j1) + return; + + float zoom_x; + m_glfcns.glGetFloatv (GL_ZOOM_X, &zoom_x); + float zoom_y; + m_glfcns.glGetFloatv (GL_ZOOM_Y, &zoom_y); + + m_glfcns.glPixelZoom (m_devpixratio * pix_dx, - m_devpixratio * pix_dy); + m_glfcns.glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0); + + // Expect RGB data + if (dv.ndims () == 3 && dv(2) == 3) + { + if (cdata.is_double_type ()) + { + const NDArray xcdata = cdata.array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, + static_cast (3)*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii, jj, 0); + a[idx+1] = xcdata(ii, jj, 1); + a[idx+2] = xcdata(ii, jj, 2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else if (cdata.is_single_type ()) + { + const FloatNDArray xcdata = cdata.float_array_value (); + + OCTAVE_LOCAL_BUFFER (GLfloat, a, + static_cast (3)*(j1-j0)*(i1-i0)); - // FIXME: handle margin and surrounding box - // Matrix bbox; + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii, jj, 0); + a[idx+1] = xcdata(ii, jj, 1); + a[idx+2] = xcdata(ii, jj, 2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else if (cdata.is_uint8_type ()) + { + const uint8NDArray xcdata = cdata.uint8_array_value (); + + OCTAVE_LOCAL_BUFFER (GLubyte, a, + static_cast (3)*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii, jj, 0); + a[idx+1] = xcdata(ii, jj, 1); + a[idx+2] = xcdata(ii, jj, 2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else if (cdata.is_uint16_type ()) + { + const uint16NDArray xcdata = cdata.uint16_array_value (); + + OCTAVE_LOCAL_BUFFER (GLushort, a, + static_cast (3)*(j1-j0)*(i1-i0)); + + for (int i = i0; i < i1; i++) + { + for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3) + { + if (! yflip) + ii = i; + else + ii = h - i - 1; + + if (! xflip) + jj = j; + else + jj = w - j - 1; + + a[idx] = xcdata(ii, jj, 0); + a[idx+1] = xcdata(ii, jj, 1); + a[idx+2] = xcdata(ii, jj, 2); + } + } + + draw_pixels (j1-j0, i1-i0, a); + + } + else + warning ("opengl_renderer: invalid image data type (expected double, single, uint8, or uint16)"); - const Matrix pos = get_transform ().scale (props.get_data_position ()); - std::string str = props.get_string ().string_vector_value ().join ("\n"); + m_glfcns.glPixelZoom (zoom_x, zoom_y); + + } +} + +void +gl2ps_renderer::draw_pixels (int w, int h, const float *data) +{ + // Clip data between 0 and 1 for float values + OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast (3)*w*h); + + for (int i = 0; i < 3*h*w; i++) + tmp_data[i] = (data[i] < 0.0f ? 0.0f : (data[i] > 1.0f ? 1.0f : data[i])); + + gl2psDrawPixels (w, h, 0, 0, GL_RGB, GL_FLOAT, tmp_data); +} + +void +gl2ps_renderer::draw_pixels (int w, int h, const uint8_t *data) +{ + // gl2psDrawPixels only supports the GL_FLOAT type. + + OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast (3)*w*h); + + static const float maxval = std::numeric_limits::max (); + + for (int i = 0; i < 3*w*h; i++) + tmp_data[i] = data[i] / maxval; + + draw_pixels (w, h, tmp_data); +} + +void +gl2ps_renderer::draw_pixels (int w, int h, const uint16_t *data) +{ + // gl2psDrawPixels only supports the GL_FLOAT type. + + OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast (3)*w*h); + + static const float maxval = std::numeric_limits::max (); + + for (int i = 0; i < 3*w*h; i++) + tmp_data[i] = data[i] / maxval; - render_text (str, pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0, - halign, valign, props.get_rotation ()); - } + draw_pixels (w, h, tmp_data); +} + +void +gl2ps_renderer::draw_text (const text::properties& props) +{ + if (props.get_string ().isempty ()) + return; + + draw_text_background (props, true); + + // First set font properties: freetype will use them to compute + // coordinates and gl2ps will retrieve the color directly from the + // feedback buffer + set_font (props); + set_color (props.get_color_rgb ()); + + std::string saved_font = m_fontname; + + // Alignment + int halign = 0; + int valign = 0; + + if (props.horizontalalignment_is ("center")) + halign = 1; + else if (props.horizontalalignment_is ("right")) + halign = 2; + + if (props.verticalalignment_is ("top")) + valign = 2; + else if (props.verticalalignment_is ("baseline")) + valign = 3; + else if (props.verticalalignment_is ("middle")) + valign = 1; + + // FIXME: handle margin and surrounding box + // Matrix bbox; + + const Matrix pos = get_transform ().scale (props.get_data_position ()); + std::string str = props.get_string ().string_vector_value ().join ("\n"); + + render_text (str, pos(0), pos(1), pos.numel () > 2 ? pos(2) : 0.0, + halign, valign, props.get_rotation ()); +} OCTAVE_END_NAMESPACE(octave) @@ -1590,69 +1590,69 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // If the name of the stream begins with '|', open a pipe to the command - // named by the rest of the string. Otherwise, write to the named file. +// If the name of the stream begins with '|', open a pipe to the command +// named by the rest of the string. Otherwise, write to the named file. - void - gl2ps_print (opengl_functions& glfcns, const graphics_object& fig, - const std::string& stream, const std::string& term) - { +void +gl2ps_print (opengl_functions& glfcns, const graphics_object& fig, + const std::string& stream, const std::string& term) +{ #if defined (HAVE_GL2PS_H) && defined (HAVE_OPENGL) - // FIXME: should we have a way to create a file that begins with the - // character '|'? + // FIXME: should we have a way to create a file that begins with the + // character '|'? - bool have_cmd = stream.length () > 1 && stream[0] == '|'; + bool have_cmd = stream.length () > 1 && stream[0] == '|'; - FILE *m_fp = nullptr; + FILE *m_fp = nullptr; - unwind_protect frame; + unwind_protect frame; - if (have_cmd) - { - // Create process and pipe gl2ps output to it. + if (have_cmd) + { + // Create process and pipe gl2ps output to it. - std::string cmd = stream.substr (1); + std::string cmd = stream.substr (1); - m_fp = popen (cmd.c_str (), "w"); + m_fp = popen (cmd.c_str (), "w"); - if (! m_fp) - error (R"(print: failed to open pipe "%s")", stream.c_str ()); + if (! m_fp) + error (R"(print: failed to open pipe "%s")", stream.c_str ()); - // Need octave:: qualifier here to avoid ambiguity. - frame.add ([=] () { octave::pclose (m_fp); }); - } - else - { - // Write gl2ps output directly to file. + // Need octave:: qualifier here to avoid ambiguity. + frame.add ([=] () { octave::pclose (m_fp); }); + } + else + { + // Write gl2ps output directly to file. - m_fp = sys::fopen (stream.c_str (), "w"); + m_fp = sys::fopen (stream.c_str (), "w"); - if (! m_fp) - error (R"(gl2ps_print: failed to create file "%s")", stream.c_str ()); + if (! m_fp) + error (R"(gl2ps_print: failed to create file "%s")", stream.c_str ()); - frame.add ([=] () { std::fclose (m_fp); }); - } + frame.add ([=] () { std::fclose (m_fp); }); + } - gl2ps_renderer rend (glfcns, m_fp, term); + gl2ps_renderer rend (glfcns, m_fp, term); - Matrix pos = fig.get ("position").matrix_value (); - rend.set_viewport (pos(2), pos(3)); - rend.draw (fig, stream); + Matrix pos = fig.get ("position").matrix_value (); + rend.set_viewport (pos(2), pos(3)); + rend.draw (fig, stream); - // Make sure buffered commands are finished!!! - rend.finish (); + // Make sure buffered commands are finished!!! + rend.finish (); #else - octave_unused_parameter (glfcns); - octave_unused_parameter (fig); - octave_unused_parameter (stream); - octave_unused_parameter (term); + octave_unused_parameter (glfcns); + octave_unused_parameter (fig); + octave_unused_parameter (stream); + octave_unused_parameter (term); - err_disabled_feature ("gl2ps_print", "gl2ps"); + err_disabled_feature ("gl2ps_print", "gl2ps"); #endif - } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gl2ps-print.h --- a/libinterp/corefcn/gl2ps-print.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gl2ps-print.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,11 +34,11 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class opengl_functions; +class opengl_functions; - extern OCTINTERP_API void - gl2ps_print (opengl_functions& glfcns, const graphics_object& fig, - const std::string& stream, const std::string& term); +extern OCTINTERP_API void +gl2ps_print (opengl_functions& glfcns, const graphics_object& fig, + const std::string& stream, const std::string& term); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/graphics-toolkit.cc --- a/libinterp/corefcn/graphics-toolkit.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/graphics-toolkit.cc Thu Dec 01 20:05:44 2022 -0800 @@ -33,34 +33,34 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - base_graphics_toolkit::update (const graphics_handle& h, int id) - { - gh_manager& gh_mgr = __get_gh_manager__ (); +void +base_graphics_toolkit::update (const graphics_handle& h, int id) +{ + gh_manager& gh_mgr = __get_gh_manager__ (); - graphics_object go = gh_mgr.get_object (h); + graphics_object go = gh_mgr.get_object (h); - update (go, id); - } + update (go, id); +} - bool - base_graphics_toolkit::initialize (const graphics_handle& h) - { - gh_manager& gh_mgr = __get_gh_manager__ (); +bool +base_graphics_toolkit::initialize (const graphics_handle& h) +{ + gh_manager& gh_mgr = __get_gh_manager__ (); - graphics_object go = gh_mgr.get_object (h); + graphics_object go = gh_mgr.get_object (h); - return initialize (go); - } + return initialize (go); +} - void - base_graphics_toolkit::finalize (const graphics_handle& h) - { - gh_manager& gh_mgr = __get_gh_manager__ (); +void +base_graphics_toolkit::finalize (const graphics_handle& h) +{ + gh_manager& gh_mgr = __get_gh_manager__ (); - graphics_object go = gh_mgr.get_object (h); + graphics_object go = gh_mgr.get_object (h); - finalize (go); - } + finalize (go); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/graphics-toolkit.h --- a/libinterp/corefcn/graphics-toolkit.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/graphics-toolkit.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,248 +40,248 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class graphics_object; - class graphics_toolkit; +class graphics_object; +class graphics_toolkit; - class base_graphics_toolkit - { - public: +class base_graphics_toolkit +{ +public: - friend class graphics_toolkit; + friend class graphics_toolkit; - public: +public: - base_graphics_toolkit (const std::string& nm) - : m_name (nm) - { } + base_graphics_toolkit (const std::string& nm) + : m_name (nm) + { } - virtual ~base_graphics_toolkit (void) = default; + virtual ~base_graphics_toolkit (void) = default; - std::string get_name (void) const - { - return m_name; - } + std::string get_name (void) const + { + return m_name; + } - virtual bool is_valid (void) const - { - return false; - } + virtual bool is_valid (void) const + { + return false; + } - virtual void redraw_figure (const graphics_object&) const - { - gripe_if_tkit_invalid ("redraw_figure"); - } + virtual void redraw_figure (const graphics_object&) const + { + gripe_if_tkit_invalid ("redraw_figure"); + } - virtual void show_figure (const graphics_object&) const - { - gripe_if_tkit_invalid ("show_figure"); - } + virtual void show_figure (const graphics_object&) const + { + gripe_if_tkit_invalid ("show_figure"); + } - virtual void print_figure (const graphics_object&, const std::string&, - const std::string&, - const std::string& = "") const - { - gripe_if_tkit_invalid ("print_figure"); - } + virtual void print_figure (const graphics_object&, const std::string&, + const std::string&, + const std::string& = "") const + { + gripe_if_tkit_invalid ("print_figure"); + } - virtual uint8NDArray get_pixels (const graphics_object&) const - { - gripe_if_tkit_invalid ("get_pixels"); - return uint8NDArray (); - } + virtual uint8NDArray get_pixels (const graphics_object&) const + { + gripe_if_tkit_invalid ("get_pixels"); + return uint8NDArray (); + } - virtual Matrix get_canvas_size (const graphics_handle&) const - { - gripe_if_tkit_invalid ("get_canvas_size"); - return Matrix (1, 2, 0.0); - } + virtual Matrix get_canvas_size (const graphics_handle&) const + { + gripe_if_tkit_invalid ("get_canvas_size"); + return Matrix (1, 2, 0.0); + } - virtual double get_screen_resolution (void) const - { - gripe_if_tkit_invalid ("get_screen_resolution"); - return 72.0; - } + virtual double get_screen_resolution (void) const + { + gripe_if_tkit_invalid ("get_screen_resolution"); + return 72.0; + } - virtual Matrix get_screen_size (void) const - { - gripe_if_tkit_invalid ("get_screen_size"); - return Matrix (1, 2, 0.0); - } + virtual Matrix get_screen_size (void) const + { + gripe_if_tkit_invalid ("get_screen_size"); + return Matrix (1, 2, 0.0); + } - virtual Matrix get_text_extent (const graphics_object&) const - { - gripe_if_tkit_invalid ("get_text_extent"); - return Matrix (); - } + virtual Matrix get_text_extent (const graphics_object&) const + { + gripe_if_tkit_invalid ("get_text_extent"); + return Matrix (); + } - // Callback function executed when the given graphics object - // changes. This allows the graphics toolkit to act on property - // changes if needed. - virtual void update (const graphics_object&, int) - { - gripe_if_tkit_invalid ("base_graphics_toolkit::update"); - } + // Callback function executed when the given graphics object + // changes. This allows the graphics toolkit to act on property + // changes if needed. + virtual void update (const graphics_object&, int) + { + gripe_if_tkit_invalid ("base_graphics_toolkit::update"); + } - void update (const graphics_handle&, int); + void update (const graphics_handle&, int); - // Callback function executed when the given graphics object is - // created. This allows the graphics toolkit to do toolkit-specific - // initializations for a newly created object. - virtual bool initialize (const graphics_object&) - { - gripe_if_tkit_invalid ("base_graphics_toolkit::initialize"); - return false; - } + // Callback function executed when the given graphics object is + // created. This allows the graphics toolkit to do toolkit-specific + // initializations for a newly created object. + virtual bool initialize (const graphics_object&) + { + gripe_if_tkit_invalid ("base_graphics_toolkit::initialize"); + return false; + } - bool initialize (const graphics_handle&); + bool initialize (const graphics_handle&); - // Callback function executed just prior to deleting the given - // graphics object. This allows the graphics toolkit to perform - // toolkit-specific cleanup operations before an object is deleted. - virtual void finalize (const graphics_object&) - { - gripe_if_tkit_invalid ("base_graphics_toolkit::finalize"); - } + // Callback function executed just prior to deleting the given + // graphics object. This allows the graphics toolkit to perform + // toolkit-specific cleanup operations before an object is deleted. + virtual void finalize (const graphics_object&) + { + gripe_if_tkit_invalid ("base_graphics_toolkit::finalize"); + } - void finalize (const graphics_handle&); + void finalize (const graphics_handle&); - // Close the graphics toolkit. - virtual void close (void) - { - gripe_if_tkit_invalid ("base_graphics_toolkit::close"); - } + // Close the graphics toolkit. + virtual void close (void) + { + gripe_if_tkit_invalid ("base_graphics_toolkit::close"); + } - private: +private: - std::string m_name; + std::string m_name; - private: +private: - void gripe_if_tkit_invalid (const std::string& fname) const - { - if (! is_valid ()) - error ("%s: invalid graphics toolkit", fname.c_str ()); - } - }; + void gripe_if_tkit_invalid (const std::string& fname) const + { + if (! is_valid ()) + error ("%s: invalid graphics toolkit", fname.c_str ()); + } +}; - class graphics_toolkit - { - public: - graphics_toolkit (const std::string& name = "unknown") - : m_rep (new base_graphics_toolkit (name)) - { } +class graphics_toolkit +{ +public: + graphics_toolkit (const std::string& name = "unknown") + : m_rep (new base_graphics_toolkit (name)) + { } - // NEW_REP must be dynamically allocated. - graphics_toolkit (base_graphics_toolkit *new_rep) - : m_rep (std::shared_ptr (new_rep)) - { - if (! m_rep) - error ("invalid graphics_toolkit!"); - } + // NEW_REP must be dynamically allocated. + graphics_toolkit (base_graphics_toolkit *new_rep) + : m_rep (std::shared_ptr (new_rep)) + { + if (! m_rep) + error ("invalid graphics_toolkit!"); + } - graphics_toolkit (const graphics_toolkit& b) = default; + graphics_toolkit (const graphics_toolkit& b) = default; - graphics_toolkit& operator = (const graphics_toolkit& b) = default; + graphics_toolkit& operator = (const graphics_toolkit& b) = default; - ~graphics_toolkit (void) = default; + ~graphics_toolkit (void) = default; - operator bool (void) const - { - return m_rep->is_valid (); - } + operator bool (void) const + { + return m_rep->is_valid (); + } - std::string get_name (void) const - { - return m_rep->get_name (); - } + std::string get_name (void) const + { + return m_rep->get_name (); + } - void redraw_figure (const graphics_object& go) const - { - m_rep->redraw_figure (go); - } + void redraw_figure (const graphics_object& go) const + { + m_rep->redraw_figure (go); + } - void show_figure (const graphics_object& go) const - { - m_rep->show_figure (go); - } + void show_figure (const graphics_object& go) const + { + m_rep->show_figure (go); + } - void print_figure (const graphics_object& go, const std::string& term, - const std::string& file, - const std::string& debug_file = "") const - { - m_rep->print_figure (go, term, file, debug_file); - } + void print_figure (const graphics_object& go, const std::string& term, + const std::string& file, + const std::string& debug_file = "") const + { + m_rep->print_figure (go, term, file, debug_file); + } - uint8NDArray get_pixels (const graphics_object& go) const - { - return m_rep->get_pixels (go); - } + uint8NDArray get_pixels (const graphics_object& go) const + { + return m_rep->get_pixels (go); + } - Matrix get_canvas_size (const graphics_handle& fh) const - { - return m_rep->get_canvas_size (fh); - } + Matrix get_canvas_size (const graphics_handle& fh) const + { + return m_rep->get_canvas_size (fh); + } - double get_screen_resolution (void) const - { - return m_rep->get_screen_resolution (); - } + double get_screen_resolution (void) const + { + return m_rep->get_screen_resolution (); + } - Matrix get_screen_size (void) const - { - return m_rep->get_screen_size (); - } + Matrix get_screen_size (void) const + { + return m_rep->get_screen_size (); + } - Matrix get_text_extent (const graphics_object& go) const - { - return m_rep->get_text_extent (go); - } + Matrix get_text_extent (const graphics_object& go) const + { + return m_rep->get_text_extent (go); + } - // Notifies graphics toolkit that object't property has changed. - void update (const graphics_object& go, int id) - { - m_rep->update (go, id); - } + // Notifies graphics toolkit that object't property has changed. + void update (const graphics_object& go, int id) + { + m_rep->update (go, id); + } - void update (const graphics_handle& h, int id) - { - m_rep->update (h, id); - } + void update (const graphics_handle& h, int id) + { + m_rep->update (h, id); + } - // Notifies graphics toolkit that new object was created. - bool initialize (const graphics_object& go) - { - return m_rep->initialize (go); - } + // Notifies graphics toolkit that new object was created. + bool initialize (const graphics_object& go) + { + return m_rep->initialize (go); + } - bool initialize (const graphics_handle& h) - { - return m_rep->initialize (h); - } + bool initialize (const graphics_handle& h) + { + return m_rep->initialize (h); + } - // Notifies graphics toolkit that object was destroyed. - // This is called only for explicitly deleted object. - // Children are deleted implicitly and graphics toolkit isn't notified. - void finalize (const graphics_object& go) - { - m_rep->finalize (go); - } + // Notifies graphics toolkit that object was destroyed. + // This is called only for explicitly deleted object. + // Children are deleted implicitly and graphics toolkit isn't notified. + void finalize (const graphics_object& go) + { + m_rep->finalize (go); + } - void finalize (const graphics_handle& h) - { - m_rep->finalize (h); - } + void finalize (const graphics_handle& h) + { + m_rep->finalize (h); + } - // Close the graphics toolkit. - void close (void) - { - m_rep->close (); - } + // Close the graphics toolkit. + void close (void) + { + m_rep->close (); + } - private: +private: - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/graphics.cc Thu Dec 01 20:05:44 2022 -0800 @@ -1072,7 +1072,7 @@ else if (cdata.is_uint64_type ()) CONVERT_CDATA_1 (uint64NDArray, uint64_, false); else if (cdata.is_double_type ()) - CONVERT_CDATA_1 (NDArray, , true); + CONVERT_CDATA_1 (NDArray,, true); else if (cdata.is_single_type ()) CONVERT_CDATA_1 (FloatNDArray, float_, true); else if (cdata.islogical ()) @@ -1699,26 +1699,26 @@ } if (m_data.is_double_type () || m_data.islogical ()) - CHECK_ARRAY_EQUAL (double, , NDArray) - else if (m_data.is_single_type ()) - CHECK_ARRAY_EQUAL (float, float_, FloatNDArray) - else if (m_data.is_int8_type ()) - CHECK_ARRAY_EQUAL (octave_int8, int8_, int8NDArray) - else if (m_data.is_int16_type ()) - CHECK_ARRAY_EQUAL (octave_int16, int16_, int16NDArray) - else if (m_data.is_int32_type ()) - CHECK_ARRAY_EQUAL (octave_int32, int32_, int32NDArray) - else if (m_data.is_int64_type ()) - CHECK_ARRAY_EQUAL (octave_int64, int64_, int64NDArray) - else if (m_data.is_uint8_type ()) - CHECK_ARRAY_EQUAL (octave_uint8, uint8_, uint8NDArray) - else if (m_data.is_uint16_type ()) - CHECK_ARRAY_EQUAL (octave_uint16, uint16_, uint16NDArray) - else if (m_data.is_uint32_type ()) - CHECK_ARRAY_EQUAL (octave_uint32, uint32_, uint32NDArray) - else if (m_data.is_uint64_type ()) - CHECK_ARRAY_EQUAL (octave_uint64, uint64_, uint64NDArray) - } + CHECK_ARRAY_EQUAL (double,, NDArray) + else if (m_data.is_single_type ()) + CHECK_ARRAY_EQUAL (float, float_, FloatNDArray) + else if (m_data.is_int8_type ()) + CHECK_ARRAY_EQUAL (octave_int8, int8_, int8NDArray) + else if (m_data.is_int16_type ()) + CHECK_ARRAY_EQUAL (octave_int16, int16_, int16NDArray) + else if (m_data.is_int32_type ()) + CHECK_ARRAY_EQUAL (octave_int32, int32_, int32NDArray) + else if (m_data.is_int64_type ()) + CHECK_ARRAY_EQUAL (octave_int64, int64_, int64NDArray) + else if (m_data.is_uint8_type ()) + CHECK_ARRAY_EQUAL (octave_uint8, uint8_, uint8NDArray) + else if (m_data.is_uint16_type ()) + CHECK_ARRAY_EQUAL (octave_uint16, uint16_, uint16NDArray) + else if (m_data.is_uint32_type ()) + CHECK_ARRAY_EQUAL (octave_uint32, uint32_, uint32NDArray) + else if (m_data.is_uint64_type ()) + CHECK_ARRAY_EQUAL (octave_uint64, uint64_, uint64NDArray) + } } return false; @@ -1980,7 +1980,7 @@ // their handlevisibility property set to "callback" to be visible. octave::unwind_action executing_callbacks_cleanup - ([=] () { executing_callbacks.erase (this); }); + ([=] () { executing_callbacks.erase (this); }); if (! executing_callbacks.contains (this)) { @@ -2014,7 +2014,7 @@ else if (type.compare ("any")) { octave_value ov = (args.length () > 0 ? args(0) - : octave_value (Matrix ())); + : octave_value (Matrix ())); retval = property (new any_property (name, h, ov)); } @@ -2023,7 +2023,8 @@ if (args.length () < 1) error ("addproperty: missing possible values for radio property"); - std::string sv = args(0).xstring_value ("addproperty: argument for radio property must be a string"); + std::string sv = args( + 0).xstring_value ("addproperty: argument for radio property must be a string"); retval = property (new radio_property (name, h, sv)); @@ -2039,7 +2040,7 @@ else if (type.compare ("handle")) { double hv = (args.length () > 0 ? args(0).double_value () - : octave::numeric_limits::NaN ()); + : octave::numeric_limits::NaN ()); graphics_handle gh (hv); @@ -2935,7 +2936,7 @@ if (h.value () < 0) m_handle_free_list.insert - (std::ceil (h.value ()) - make_handle_fraction ()); + (std::ceil (h.value ()) - make_handle_fraction ()); } } @@ -3041,7 +3042,7 @@ octave_value val = xget (0, "currentfigure"); return val.isempty () ? octave::numeric_limits::NaN () - : val.double_value (); + : val.double_value (); } // This function is NOT equivalent to the scripting language function gca. @@ -3051,7 +3052,7 @@ octave_value val = xget (gcf (), "currentaxes"); return val.isempty () ? octave::numeric_limits::NaN () - : val.double_value (); + : val.double_value (); } static void @@ -3685,9 +3686,9 @@ children_list.push_back (go); else if (traverse && go.isa ("hggroup")) go.get_properties ().get_children_of_type (chtype, - get_invisible, - traverse, - children_list); + get_invisible, + traverse, + children_list); } } } @@ -3711,7 +3712,7 @@ void base_graphics_object::update_axis_limits (const std::string& axis_type, - const graphics_handle& h) + const graphics_handle& h) { if (! valid_object ()) error ("base_graphics_object::update_axis_limits: invalid graphics object"); @@ -5145,11 +5146,11 @@ calc_ticklabels (m_xtick, m_xticklabel, m_xscale.is ("log"), xaxislocation_is ("origin"), m_yscale.is ("log") ? 2 : (yaxislocation_is ("origin") ? 0 : - (yaxislocation_is ("left") ? -1 : 1)), m_xlim); + (yaxislocation_is ("left") ? -1 : 1)), m_xlim); calc_ticklabels (m_ytick, m_yticklabel, m_yscale.is ("log"), yaxislocation_is ("origin"), m_xscale.is ("log") ? 2 : (xaxislocation_is ("origin") ? 0 : - (xaxislocation_is ("bottom") ? -1 : 1)), m_ylim); + (xaxislocation_is ("bottom") ? -1 : 1)), m_ylim); calc_ticklabels (m_ztick, m_zticklabel, m_zscale.is ("log"), false, 2, m_zlim); @@ -6353,11 +6354,11 @@ double offset = get___fontsize_points__ () / 2; m_xtickoffset = (mode2D ? std::max (0., m_xticklen) : std::abs (m_xticklen)) + - (m_xstate == AXE_HORZ_DIR ? offset*1.5 : offset); + (m_xstate == AXE_HORZ_DIR ? offset*1.5 : offset); m_ytickoffset = (mode2D ? std::max (0., m_yticklen) : std::abs (m_yticklen)) + - (m_ystate == AXE_HORZ_DIR ? offset*1.5 : offset); + (m_ystate == AXE_HORZ_DIR ? offset*1.5 : offset); m_ztickoffset = (mode2D ? std::max (0., m_zticklen) : std::abs (m_zticklen)) + - (m_zstate == AXE_HORZ_DIR ? offset*1.5 : offset); + (m_zstate == AXE_HORZ_DIR ? offset*1.5 : offset); update_xlabel_position (); update_ylabel_position (); @@ -6433,15 +6434,15 @@ bool isempty = xlabel_props.get_string ().isempty (); octave::unwind_protect_var - restore_var (updating_xlabel_position, true); + restore_var (updating_xlabel_position, true); if (! isempty) { if (xlabel_props.horizontalalignmentmode_is ("auto")) { xlabel_props.set_horizontalalignment - (m_xstate > AXE_DEPTH_DIR ? "center" - : (m_xyzSym ? "left" : "right")); + (m_xstate > AXE_DEPTH_DIR ? "center" + : (m_xyzSym ? "left" : "right")); xlabel_props.set_horizontalalignmentmode ("auto"); } @@ -6449,7 +6450,7 @@ if (xlabel_props.verticalalignmentmode_is ("auto")) { xlabel_props.set_verticalalignment - (m_xstate == AXE_VERT_DIR || m_x2Dtop ? "bottom" : "top"); + (m_xstate == AXE_VERT_DIR || m_x2Dtop ? "bottom" : "top"); xlabel_props.set_verticalalignmentmode ("auto"); } @@ -6537,15 +6538,15 @@ bool isempty = ylabel_props.get_string ().isempty (); octave::unwind_protect_var - restore_var (updating_ylabel_position, true); + restore_var (updating_ylabel_position, true); if (! isempty) { if (ylabel_props.horizontalalignmentmode_is ("auto")) { ylabel_props.set_horizontalalignment - (m_ystate > AXE_DEPTH_DIR ? "center" - : (! m_xyzSym ? "left" : "right")); + (m_ystate > AXE_DEPTH_DIR ? "center" + : (! m_xyzSym ? "left" : "right")); ylabel_props.set_horizontalalignmentmode ("auto"); } @@ -6553,7 +6554,7 @@ if (ylabel_props.verticalalignmentmode_is ("auto")) { ylabel_props.set_verticalalignment - (m_ystate == AXE_VERT_DIR && ! m_y2Dright ? "bottom" : "top"); + (m_ystate == AXE_VERT_DIR && ! m_y2Dright ? "bottom" : "top"); ylabel_props.set_verticalalignmentmode ("auto"); } @@ -6642,14 +6643,14 @@ bool isempty = zlabel_props.get_string ().isempty (); octave::unwind_protect_var - restore_updating_zlabel_position (updating_zlabel_position, true); + restore_updating_zlabel_position (updating_zlabel_position, true); if (! isempty) { if (zlabel_props.horizontalalignmentmode_is ("auto")) { zlabel_props.set_horizontalalignment - ((m_zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right"); + ((m_zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right"); zlabel_props.set_horizontalalignmentmode ("auto"); } @@ -6657,8 +6658,8 @@ if (zlabel_props.verticalalignmentmode_is ("auto")) { zlabel_props.set_verticalalignment - (m_zstate == AXE_VERT_DIR - ? "bottom" : ((m_zSign || camAuto) ? "bottom" : "top")); + (m_zstate == AXE_VERT_DIR + ? "bottom" : ((m_zSign || camAuto) ? "bottom" : "top")); zlabel_props.set_verticalalignmentmode ("auto"); } @@ -6916,7 +6917,7 @@ if (modified_limits) { octave::unwind_protect_var> - restore_var (updating_aspectratios); + restore_var (updating_aspectratios); updating_aspectratios.insert (get___myhandle__ ().value ()); @@ -7012,7 +7013,7 @@ const Matrix& parent_pix_size) const { Matrix pos = (internal ? get_position ().matrix_value () - : get_outerposition ().matrix_value ()); + : get_outerposition ().matrix_value ()); Matrix parent_size (parent_pix_size); if (parent_size.isempty ()) @@ -7076,7 +7077,7 @@ text::properties& text_props = reinterpret_cast - (gh_mgr.get_object (htext).get_properties ()); + (gh_mgr.get_object (htext).get_properties ()); Matrix text_pos = text_props.get_data_position (); text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2)); @@ -8197,7 +8198,7 @@ int n = (is_logscale ? 8 : 4); double mult_below = (is_logscale ? tmp_ticks(1) / tmp_ticks(0) : 1); double mult_above = (is_logscale ? tmp_ticks(n_ticks-1) / tmp_ticks(n_ticks-2) - : 1); + : 1); double d_below = (tmp_ticks(1) - tmp_ticks(0)) / mult_below / (n+1); int n_below = static_cast (std::floor ((tmp_ticks(0)-lo_lim) / d_below)); @@ -8207,7 +8208,7 @@ double d_above = (tmp_ticks(n_ticks-1) - tmp_ticks(n_ticks-2)) * mult_above / (n+1); int n_above = static_cast (std::floor ((hi_lim-tmp_ticks(n_ticks-1)) - / d_above)); + / d_above)); if (n_above < 0) n_above = 0; @@ -8351,8 +8352,8 @@ Matrix axes::properties::get_ticklabel_extents (const Matrix& ticks, - const string_vector& ticklabels, - const Matrix& limits) + const string_vector& ticklabels, + const Matrix& limits) { Matrix ext (1, 2, 0.0); double wmax, hmax; @@ -8651,7 +8652,7 @@ #undef FIX_LIMITS octave::unwind_protect_var> - restore_var (updating_axis_limits); + restore_var (updating_axis_limits); updating_axis_limits.insert (get_handle ().value ()); bool is_auto; @@ -8868,7 +8869,7 @@ } octave::unwind_protect_var> - restore_var (updating_axis_limits); + restore_var (updating_axis_limits); updating_axis_limits.insert (get_handle ().value ()); bool is_auto; @@ -9692,7 +9693,7 @@ graphics_object go = gh_mgr.get_object (get___myhandle__ ()); axes::properties& ax_props = dynamic_cast - (go.get_ancestor ("axes").get_properties ()); + (go.get_ancestor ("axes").get_properties ()); if (is_visible ()) ax_props.increase_num_lights (); else @@ -9709,7 +9710,7 @@ graphics_object go = gh_mgr.get_object (get___myhandle__ ()); axes::properties& ax_props = dynamic_cast - (go.get_ancestor ("axes").get_properties ()); + (go.get_ancestor ("axes").get_properties ()); return (ax_props.get_num_lights () > 0); } @@ -10367,7 +10368,7 @@ axes::properties& parent_axes_prop = dynamic_cast - (go.get_ancestor ("axes").get_properties ()); + (go.get_ancestor ("axes").get_properties ()); Matrix color_order = parent_axes_prop.get_colororder ().matrix_value (); octave_idx_type s = (static_cast (series_idx(0)) - 1) @@ -10395,7 +10396,7 @@ // Increment series index counter in parent axes axes::properties& parent_axes_prop = dynamic_cast - (go.get_ancestor ("axes").get_properties ()); + (go.get_ancestor ("axes").get_properties ()); if (! parent_axes_prop.nextplot_is ("add")) parent_axes_prop.set_nextseriesindex (1); @@ -10405,7 +10406,7 @@ m_properties.set_seriesindex (series_idx); parent_axes_prop.set_nextseriesindex - (parent_axes_prop.get_nextseriesindex () + 1); + (parent_axes_prop.get_nextseriesindex () + 1); } if (m_properties.cdatamode_is ("auto")) @@ -10428,7 +10429,7 @@ graphics_object go = gh_mgr.get_object (get___myhandle__ ()); axes::properties& ax_prop = dynamic_cast - (go.get_ancestor ("axes").get_properties ()); + (go.get_ancestor ("axes").get_properties ()); return (ax_prop.get_num_lights () > 0); } @@ -10605,30 +10606,30 @@ if ((j > 0) && (i > 0)) // upper left quadrangle cross_product - (x(j1,i-1)-x(j2,i), y(j-1,i1)-y(j,i2), z(j-1,i-1)-z(j,i), - x(j2,i-1)-x(j1,i), y(j,i1)-y(j-1,i2), z(j,i-1)-z(j-1,i), - nx, ny, nz); + (x(j1, i-1)-x(j2, i), y(j-1, i1)-y(j, i2), z(j-1, i-1)-z(j, i), + x(j2, i-1)-x(j1, i), y(j, i1)-y(j-1, i2), z(j, i-1)-z(j-1, i), + nx, ny, nz); if ((j > 0) && (i < (p -1))) // upper right quadrangle cross_product - (x(j1,i+1)-x(j2,i), y(j-1,i3)-y(j,i2), z(j-1,i+1)-z(j,i), - x(j1,i)-x(j2,i+1), y(j-1,i2)-y(j,i3), z(j-1,i)-z(j,i+1), - nx, ny, nz); + (x(j1, i+1)-x(j2, i), y(j-1, i3)-y(j, i2), z(j-1, i+1)-z(j, i), + x(j1, i)-x(j2, i+1), y(j-1, i2)-y(j, i3), z(j-1, i)-z(j, i+1), + nx, ny, nz); if ((j < (q - 1)) && (i > 0)) // lower left quadrangle cross_product - (x(j2,i-1)-x(j3,i), y(j,i1)-y(j+1,i2), z(j,i-1)-z(j+1,i), - x(j3,i-1)-x(j2,i), y(j+1,i1)-y(j,i2), z(j+1,i-1)-z(j,i), - nx, ny, nz); + (x(j2, i-1)-x(j3, i), y(j, i1)-y(j+1, i2), z(j, i-1)-z(j+1, i), + x(j3, i-1)-x(j2, i), y(j+1, i1)-y(j, i2), z(j+1, i-1)-z(j, i), + nx, ny, nz); if ((j < (q - 1)) && (i < (p -1))) // lower right quadrangle cross_product - (x(j3,i)-x(j2,i+1), y(j+1,i2)-y(j,i3), z(j+1,i)-z(j,i+1), - x(j3,i+1)-x(j2,i), y(j+1,i3)-y(j,i2), z(j+1,i+1)-z(j,i), - nx, ny, nz); + (x(j3, i)-x(j2, i+1), y(j+1, i2)-y(j, i3), z(j+1, i)-z(j, i+1), + x(j3, i+1)-x(j2, i), y(j+1, i3)-y(j, i2), z(j+1, i+1)-z(j, i), + nx, ny, nz); double d = -std::max (std::max (fabs (nx), fabs (ny)), fabs (nz)); @@ -11190,7 +11191,7 @@ Matrix uibuttongroup::properties::get_boundingbox (bool internal, - const Matrix& parent_pix_size) const + const Matrix& parent_pix_size) const { Matrix pos = get_position ().matrix_value (); Matrix parent_size (parent_pix_size); @@ -11399,7 +11400,7 @@ void uibuttongroup::properties::remove_child (const graphics_handle& h, - bool from_root) + bool from_root) { graphics_handle current_selected = get_selectedobject (); if (h.value () == current_selected.value ()) @@ -12286,7 +12287,7 @@ args(1) = Matrix (); octave::unwind_action_safe restore_gcbo_action - (&gh_manager::restore_gcbo, this); + (&gh_manager::restore_gcbo, this); graphics_object go (get_object (h)); if (go) @@ -12417,7 +12418,7 @@ } else post_event (graphics_event::create_callback_event (h, name, data, - busyaction)); + busyaction)); } } @@ -12437,7 +12438,7 @@ octave::autolock guard (m_graphics_lock); post_event (graphics_event::create_set_event (h, name, value, notify_toolkit, - redraw_figure)); + redraw_figure)); } int @@ -13118,7 +13119,8 @@ caseless_str property; if (nargin > 1) - property = args(1).xstring_value ("get: second argument must be property name or cell array of property names"); + property = args( + 1).xstring_value ("get: second argument must be property name or cell array of property names"); vals.resize (dim_vector (hcv_len, 1)); @@ -13983,7 +13985,8 @@ } } - debug_file = (args.length () > 2 ? args(2).xstring_value ("drawnow: DEBUG_FILE must be a string") : ""); + debug_file = (args.length () > 2 ? args(2).xstring_value ("drawnow: DEBUG_FILE must be a string") : + ""); graphics_handle h = gcf (); @@ -14521,7 +14524,7 @@ else { cleanup_waitfor_postset_listener_action.set - (cleanup_waitfor_postset_listener, ov_listener); + (cleanup_waitfor_postset_listener, ov_listener); go.add_property_listener (pname, ov_listener, GCB_POSTSET); go.add_property_listener (pname, ov_listener, GCB_PERSISTENT); @@ -14546,7 +14549,7 @@ octave_value ov_del_listener (del_listener); cleanup_waitfor_predelete_listener_action.set - (cleanup_waitfor_predelete_listener, ov_del_listener); + (cleanup_waitfor_predelete_listener, ov_del_listener); go.add_property_listener (pname, ov_del_listener, GCB_PREDELETE); @@ -14558,7 +14561,8 @@ if (timeout_index < 0 && args.length () > (max_arg_index + 1)) { - caseless_str s = args(max_arg_index + 1).xstring_value ("waitfor: invalid parameter, expected 'timeout'"); + caseless_str s = args(max_arg_index + + 1).xstring_value ("waitfor: invalid parameter, expected 'timeout'"); if (! s.compare ("timeout")) error ("waitfor: invalid parameter '%s'", s.c_str ()); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gsvd.cc --- a/libinterp/corefcn/gsvd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gsvd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -196,8 +196,10 @@ } else if (argA.iscomplex () || argB.iscomplex ()) { - FloatComplexMatrix ctmpA = argA.xfloat_complex_matrix_value ("gsvd: A must be a real or complex matrix"); - FloatComplexMatrix ctmpB = argB.xfloat_complex_matrix_value ("gsvd: B must be a real or complex matrix"); + FloatComplexMatrix ctmpA = + argA.xfloat_complex_matrix_value ("gsvd: A must be a real or complex matrix"); + FloatComplexMatrix ctmpB = + argB.xfloat_complex_matrix_value ("gsvd: B must be a real or complex matrix"); if (ctmpA.any_element_is_inf_or_nan ()) error ("gsvd: A cannot have Inf or NaN values"); @@ -363,8 +365,8 @@ ## A: 5x3 complex full rank, B: 3x3 complex full rank %!test <48807> -%! A0 = A0 + j*randn (5, 3); -%! B0 = diag ([1 2 4]) + j*diag ([4 -2 -1]); +%! A0 = A0 + j* randn (5, 3); +%! B0 = diag ([1 2 4]) + j* diag ([4 -2 -1]); %! A = A0; %! B = B0; %! [U, V, X, C, S] = gsvd (A, B); @@ -402,7 +404,7 @@ ## now, A is 3x5 %!test <48807> %! A = A0.'; -%! B0 = diag ([1 2 4 8 16]) + j*diag ([-5 4 -3 2 -1]); +%! B0 = diag ([1 2 4 8 16]) + j* diag ([-5 4 -3 2 -1]); %! B = B0; %! [U, V, X, C, S] = gsvd (A, B); %! assert (C'*C + S'*S, eye (5), 5*eps); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gtk-manager.cc --- a/libinterp/corefcn/gtk-manager.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gtk-manager.cc Thu Dec 01 20:05:44 2022 -0800 @@ -35,79 +35,79 @@ OCTAVE_BEGIN_NAMESPACE(octave) - graphics_toolkit - gtk_manager::get_toolkit (void) const - { - graphics_toolkit retval; +graphics_toolkit +gtk_manager::get_toolkit (void) const +{ + graphics_toolkit retval; - if (m_dtk.empty ()) - error ("no graphics toolkits are available!"); + if (m_dtk.empty ()) + error ("no graphics toolkits are available!"); - auto pl = m_loaded_toolkits.find (m_dtk); + auto pl = m_loaded_toolkits.find (m_dtk); - if (pl == m_loaded_toolkits.end ()) - { - auto pa = m_available_toolkits.find (m_dtk); + if (pl == m_loaded_toolkits.end ()) + { + auto pa = m_available_toolkits.find (m_dtk); - if (pa == m_available_toolkits.end ()) - error ("default graphics toolkit '%s' is not available!", - m_dtk.c_str ()); + if (pa == m_available_toolkits.end ()) + error ("default graphics toolkit '%s' is not available!", + m_dtk.c_str ()); - octave_value_list args; - args(0) = m_dtk; - feval ("graphics_toolkit", args); + octave_value_list args; + args(0) = m_dtk; + feval ("graphics_toolkit", args); - pl = m_loaded_toolkits.find (m_dtk); + pl = m_loaded_toolkits.find (m_dtk); - if (pl == m_loaded_toolkits.end ()) - error ("failed to load %s graphics toolkit", m_dtk.c_str ()); + if (pl == m_loaded_toolkits.end ()) + error ("failed to load %s graphics toolkit", m_dtk.c_str ()); - retval = pl->second; - } - else retval = pl->second; + } + else + retval = pl->second; - return retval; - } + return retval; +} - void - gtk_manager::register_toolkit (const std::string& name) - { - if (m_dtk.empty () || name == "qt" - || (name == "fltk" - && m_available_toolkits.find ("qt") == m_available_toolkits.end ())) - m_dtk = name; +void +gtk_manager::register_toolkit (const std::string& name) +{ + if (m_dtk.empty () || name == "qt" + || (name == "fltk" + && m_available_toolkits.find ("qt") == m_available_toolkits.end ())) + m_dtk = name; - m_available_toolkits.insert (name); - } + m_available_toolkits.insert (name); +} - void - gtk_manager::unregister_toolkit (const std::string& name) - { - m_available_toolkits.erase (name); +void +gtk_manager::unregister_toolkit (const std::string& name) +{ + m_available_toolkits.erase (name); - if (m_dtk == name) - { - if (m_available_toolkits.empty ()) - m_dtk.clear (); - else - { - auto pa = m_available_toolkits.cbegin (); + if (m_dtk == name) + { + if (m_available_toolkits.empty ()) + m_dtk.clear (); + else + { + auto pa = m_available_toolkits.cbegin (); - m_dtk = *pa++; + m_dtk = *pa++; - while (pa != m_available_toolkits.cend ()) - { - std::string tk_name = *pa++; + while (pa != m_available_toolkits.cend ()) + { + std::string tk_name = *pa++; - if (tk_name == "qt" - || (tk_name == "fltk" - && (m_available_toolkits.find ("qt") - == m_available_toolkits.cend ()))) - m_dtk = tk_name; - } - } - } - } + if (tk_name == "qt" + || (tk_name == "fltk" + && (m_available_toolkits.find ("qt") + == m_available_toolkits.cend ()))) + m_dtk = tk_name; + } + } + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/gtk-manager.h --- a/libinterp/corefcn/gtk-manager.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/gtk-manager.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,94 +37,94 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class OCTINTERP_API gtk_manager - { - public: +class OCTINTERP_API gtk_manager +{ +public: - gtk_manager (void) { } + gtk_manager (void) { } - ~gtk_manager (void) - { - unload_all_toolkits (); - } + ~gtk_manager (void) + { + unload_all_toolkits (); + } - graphics_toolkit get_toolkit (void) const; + graphics_toolkit get_toolkit (void) const; - void register_toolkit (const std::string& name); + void register_toolkit (const std::string& name); - void unregister_toolkit (const std::string& name); + void unregister_toolkit (const std::string& name); - void load_toolkit (const graphics_toolkit& tk) - { - m_loaded_toolkits[tk.get_name ()] = tk; - } + void load_toolkit (const graphics_toolkit& tk) + { + m_loaded_toolkits[tk.get_name ()] = tk; + } - void unload_toolkit (const std::string& name) - { - m_loaded_toolkits.erase (name); - } + void unload_toolkit (const std::string& name) + { + m_loaded_toolkits.erase (name); + } - graphics_toolkit find_toolkit (const std::string& name) const - { - auto p = m_loaded_toolkits.find (name); + graphics_toolkit find_toolkit (const std::string& name) const + { + auto p = m_loaded_toolkits.find (name); - if (p != m_loaded_toolkits.end ()) - return p->second; - else - return graphics_toolkit (); - } + if (p != m_loaded_toolkits.end ()) + return p->second; + else + return graphics_toolkit (); + } - Cell available_toolkits_list (void) const - { - Cell m (1, m_available_toolkits.size ()); + Cell available_toolkits_list (void) const + { + Cell m (1, m_available_toolkits.size ()); - octave_idx_type i = 0; - for (const auto& tkit : m_available_toolkits) - m(i++) = tkit; + octave_idx_type i = 0; + for (const auto& tkit : m_available_toolkits) + m(i++) = tkit; - return m; - } + return m; + } - Cell loaded_toolkits_list (void) const - { - Cell m (1, m_loaded_toolkits.size ()); + Cell loaded_toolkits_list (void) const + { + Cell m (1, m_loaded_toolkits.size ()); - octave_idx_type i = 0; - for (const auto& nm_tkit_p : m_loaded_toolkits) - m(i++) = nm_tkit_p.first; + octave_idx_type i = 0; + for (const auto& nm_tkit_p : m_loaded_toolkits) + m(i++) = nm_tkit_p.first; - return m; - } + return m; + } - void unload_all_toolkits (void) - { - while (! m_loaded_toolkits.empty ()) - { - auto p = m_loaded_toolkits.begin (); + void unload_all_toolkits (void) + { + while (! m_loaded_toolkits.empty ()) + { + auto p = m_loaded_toolkits.begin (); - std::string name = p->first; + std::string name = p->first; - p->second.close (); + p->second.close (); - // The toolkit may have unloaded itself. If not, we'll do it here. - if (m_loaded_toolkits.find (name) != m_loaded_toolkits.end ()) - unload_toolkit (name); - } - } + // The toolkit may have unloaded itself. If not, we'll do it here. + if (m_loaded_toolkits.find (name) != m_loaded_toolkits.end ()) + unload_toolkit (name); + } + } - std::string default_toolkit (void) const { return m_dtk; } + std::string default_toolkit (void) const { return m_dtk; } - private: +private: - // The name of the default toolkit. - std::string m_dtk; + // The name of the default toolkit. + std::string m_dtk; - // The list of toolkits that we know about. - std::set m_available_toolkits; + // The list of toolkits that we know about. + std::set m_available_toolkits; - // The list of toolkits we have actually loaded. - std::map m_loaded_toolkits; - }; + // The list of toolkits we have actually loaded. + std::map m_loaded_toolkits; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/help.cc --- a/libinterp/corefcn/help.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/help.cc Thu Dec 01 20:05:44 2022 -0800 @@ -76,661 +76,661 @@ OCTAVE_BEGIN_NAMESPACE(octave) - const static char * const operators[] = - { - "!", - "~", - "!=", - "~=", - R"(")", - "#", - "%", - "#{", - "%{", - "#}", - "%}", - "...", - "&", - "&&", - "'", - "(", - ")", - "*", - "^", - "+", - "++", - ",", - "-", - "--", - ".'", - ".*", - ".^", - "./", - "/", - R"(.\)", - R"(\)", - ":", - ";", - "<", - "<=", - "=", - "==", - ">", - ">=", - "[", - "]", - "|", - "||", - nullptr - }; +const static char *const operators[] = +{ + "!", + "~", + "!=", + "~=", + R"(")", + "#", + "%", + "#{", + "%{", + "#}", + "%}", + "...", + "&", + "&&", + "'", + "(", + ")", + "*", + "^", + "+", + "++", + ",", + "-", + "--", + ".'", + ".*", + ".^", + "./", + "/", + R"(.\)", + R"(\)", + ":", + ";", + "<", + "<=", + "=", + "==", + ">", + ">=", + "[", + "]", + "|", + "||", + nullptr +}; - const static string_vector operator_names (operators); +const static string_vector operator_names (operators); - static bool - looks_like_html (const std::string& msg) - { - const std::size_t p1 = msg.find ('\n'); - std::string t = msg.substr (0, p1); - // FIXME: this comparison should be case-insensitive - const std::size_t p2 = t.find (" 12 && h[12] == ':') - tmp_nm = h.substr (13); + if (external_doc && h.length () > 12 && h[12] == ':') + tmp_nm = h.substr (13); - raw_help_from_docstrings_file (tmp_nm, h, symbol_found); - } + raw_help_from_docstrings_file (tmp_nm, h, symbol_found); + } - return h; - } + return h; +} - std::string help_system::which (const std::string& name, - std::string& type) const - { - std::string file; +std::string help_system::which (const std::string& name, + std::string& type) const +{ + std::string file; - if (name.empty ()) - return file; + if (name.empty ()) + return file; - type = ""; + type = ""; - symbol_table& symtab = m_interpreter.get_symbol_table (); + symbol_table& symtab = m_interpreter.get_symbol_table (); - octave_value val = symtab.find_function (name); + octave_value val = symtab.find_function (name); - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - if (fcn) - { - if (fcn->is_classdef_meta ()) - { - octave_classdef_meta *meta_obj - = dynamic_cast (fcn); + if (fcn) + { + if (fcn->is_classdef_meta ()) + { + octave_classdef_meta *meta_obj + = dynamic_cast (fcn); - file = meta_obj->file_name (); + file = meta_obj->file_name (); - if (meta_obj->is_classdef_constructor ()) - type = "class constructor"; - else if (meta_obj->is_classdef_method ()) - type = "class method"; - else - type = "classdef meta object"; - } - else - { + if (meta_obj->is_classdef_constructor ()) + type = "class constructor"; + else if (meta_obj->is_classdef_method ()) + type = "class method"; + else + type = "classdef meta object"; + } + else + { - file = fcn->fcn_file_name (); + file = fcn->fcn_file_name (); - if (! file.empty ()) - type = val.is_user_script () ? "script" : "function"; - else - { - if (fcn->is_user_function ()) - type = "command-line function"; - else - { - file = fcn->src_file_name (); - type = "built-in function"; - } - } - } - } - else - { - // We might find a file that contains only a doc string. + if (! file.empty ()) + type = val.is_user_script () ? "script" : "function"; + else + { + if (fcn->is_user_function ()) + type = "command-line function"; + else + { + file = fcn->src_file_name (); + type = "built-in function"; + } + } + } + } + else + { + // We might find a file that contains only a doc string. - load_path& lp = m_interpreter.get_load_path (); + load_path& lp = m_interpreter.get_load_path (); - file = lp.find_fcn_file (name); - } - } + file = lp.find_fcn_file (name); + } + } - if (file.empty ()) - { - // File query. + if (file.empty ()) + { + // File query. - load_path& lp = m_interpreter.get_load_path (); + load_path& lp = m_interpreter.get_load_path (); - // For compatibility: "file." queries "file". - if (name.size () > 1 && name[name.size () - 1] == '.') - file = lp.find_file (name.substr (0, name.size () - 1)); - else - file = lp.find_file (name); + // For compatibility: "file." queries "file". + if (name.size () > 1 && name[name.size () - 1] == '.') + file = lp.find_file (name.substr (0, name.size () - 1)); + else + file = lp.find_file (name); - file = sys::env::make_absolute (file); - } + file = sys::env::make_absolute (file); + } - return file; - } + return file; +} - std::string help_system::which (const std::string& name) const - { - std::string type; +std::string help_system::which (const std::string& name) const +{ + std::string type; - return which (name, type); - } + return which (name, type); +} - string_vector help_system::make_name_list (void) const - { - const static string_vector keywords - = Fiskeyword ()(0).string_vector_value (); +string_vector help_system::make_name_list (void) const +{ + const static string_vector keywords + = Fiskeyword ()(0).string_vector_value (); - const static int key_len = keywords.numel (); + const static int key_len = keywords.numel (); - symbol_table& symtab = m_interpreter.get_symbol_table (); + symbol_table& symtab = m_interpreter.get_symbol_table (); - const string_vector bif = symtab.built_in_function_names (); - const int bif_len = bif.numel (); + const string_vector bif = symtab.built_in_function_names (); + const int bif_len = bif.numel (); - const string_vector cfl = symtab.cmdline_function_names (); - const int cfl_len = cfl.numel (); + const string_vector cfl = symtab.cmdline_function_names (); + const int cfl_len = cfl.numel (); - const string_vector lcl = m_interpreter.variable_names (); - const int lcl_len = lcl.numel (); + const string_vector lcl = m_interpreter.variable_names (); + const int lcl_len = lcl.numel (); - load_path& lp = m_interpreter.get_load_path (); + load_path& lp = m_interpreter.get_load_path (); - const string_vector ffl = lp.fcn_names (); - const int ffl_len = ffl.numel (); + const string_vector ffl = lp.fcn_names (); + const int ffl_len = ffl.numel (); - const string_vector afl = m_interpreter.autoloaded_functions (); - const int afl_len = afl.numel (); + const string_vector afl = m_interpreter.autoloaded_functions (); + const int afl_len = afl.numel (); - const string_vector lfl = local_functions (); - const int lfl_len = lfl.numel (); + const string_vector lfl = local_functions (); + const int lfl_len = lfl.numel (); - const int total_len - = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len + lfl_len; + const int total_len + = key_len + bif_len + cfl_len + lcl_len + ffl_len + afl_len + lfl_len; - string_vector list (total_len); + string_vector list (total_len); - // Put all the symbols in one big list. + // Put all the symbols in one big list. - int j = 0; - int i = 0; + int j = 0; + int i = 0; - for (i = 0; i < key_len; i++) - list[j++] = keywords[i]; + for (i = 0; i < key_len; i++) + list[j++] = keywords[i]; - for (i = 0; i < bif_len; i++) - list[j++] = bif[i]; + for (i = 0; i < bif_len; i++) + list[j++] = bif[i]; - for (i = 0; i < cfl_len; i++) - list[j++] = cfl[i]; + for (i = 0; i < cfl_len; i++) + list[j++] = cfl[i]; - for (i = 0; i < lcl_len; i++) - list[j++] = lcl[i]; + for (i = 0; i < lcl_len; i++) + list[j++] = lcl[i]; - for (i = 0; i < ffl_len; i++) - list[j++] = ffl[i]; + for (i = 0; i < ffl_len; i++) + list[j++] = ffl[i]; - for (i = 0; i < afl_len; i++) - list[j++] = afl[i]; + for (i = 0; i < afl_len; i++) + list[j++] = afl[i]; - for (i = 0; i < lfl_len; i++) - list[j++] = lfl[i]; + for (i = 0; i < lfl_len; i++) + list[j++] = lfl[i]; - return list; - } + return list; +} - void help_system::get_help_text (const std::string& name, std::string& text, - std::string& format) const - { - bool symbol_found = false; - text = raw_help (name, symbol_found); +void help_system::get_help_text (const std::string& name, std::string& text, + std::string& format) const +{ + bool symbol_found = false; + text = raw_help (name, symbol_found); - format = "Not found"; - if (symbol_found) - { - std::size_t idx = -1; - if (text.empty ()) - { - format = "Not documented"; - } - else if (looks_like_texinfo (text, idx)) - { - format = "texinfo"; - text.erase (0, idx); - } - else if (looks_like_html (text)) - { - format = "html"; - } - else - { - format = "plain text"; - } - } - } + format = "Not found"; + if (symbol_found) + { + std::size_t idx = -1; + if (text.empty ()) + { + format = "Not documented"; + } + else if (looks_like_texinfo (text, idx)) + { + format = "texinfo"; + text.erase (0, idx); + } + else if (looks_like_html (text)) + { + format = "html"; + } + else + { + format = "plain text"; + } + } +} - void help_system::get_help_text_from_file (const std::string& fname, - std::string& text, - std::string& format) const - { - bool symbol_found = false; +void help_system::get_help_text_from_file (const std::string& fname, + std::string& text, + std::string& format) const +{ + bool symbol_found = false; - std::string f; + std::string f; - raw_help_from_file (fname, text, f, symbol_found); + raw_help_from_file (fname, text, f, symbol_found); - format = "Not found"; - if (symbol_found) - { - std::size_t idx = -1; - if (text.empty ()) - { - format = "Not documented"; - } - else if (looks_like_texinfo (text, idx)) - { - format = "texinfo"; - text.erase (0, idx); - } - else if (looks_like_html (text)) - { - format = "html"; - } - else - { - format = "plain text"; - } - } - } + format = "Not found"; + if (symbol_found) + { + std::size_t idx = -1; + if (text.empty ()) + { + format = "Not documented"; + } + else if (looks_like_texinfo (text, idx)) + { + format = "texinfo"; + text.erase (0, idx); + } + else if (looks_like_html (text)) + { + format = "html"; + } + else + { + format = "plain text"; + } + } +} - std::string help_system::init_built_in_docstrings_file (void) - { - std::string df = sys::env::getenv ("OCTAVE_BUILT_IN_DOCSTRINGS_FILE"); +std::string help_system::init_built_in_docstrings_file (void) +{ + std::string df = sys::env::getenv ("OCTAVE_BUILT_IN_DOCSTRINGS_FILE"); - std::string dir_sep = sys::file_ops::dir_sep_str (); + std::string dir_sep = sys::file_ops::dir_sep_str (); - if (df.empty ()) - df = config::oct_etc_dir () + dir_sep + "built-in-docstrings"; + if (df.empty ()) + df = config::oct_etc_dir () + dir_sep + "built-in-docstrings"; - return df; - } + return df; +} - std::string help_system::init_doc_cache_file (void) - { - std::string def_file = config::prepend_octave_home (OCTAVE_DOC_CACHE_FILE); +std::string help_system::init_doc_cache_file (void) +{ + std::string def_file = config::prepend_octave_home (OCTAVE_DOC_CACHE_FILE); - std::string env_file = sys::env::getenv ("OCTAVE_DOC_CACHE_FILE"); + std::string env_file = sys::env::getenv ("OCTAVE_DOC_CACHE_FILE"); - return (env_file.empty () ? def_file : env_file); - } + return (env_file.empty () ? def_file : env_file); +} - std::string help_system::init_info_file (void) - { - std::string std_info_file = config::prepend_octave_home (OCTAVE_INFOFILE); +std::string help_system::init_info_file (void) +{ + std::string std_info_file = config::prepend_octave_home (OCTAVE_INFOFILE); - std::string oct_info_file = sys::env::getenv ("OCTAVE_INFO_FILE"); + std::string oct_info_file = sys::env::getenv ("OCTAVE_INFO_FILE"); - return (oct_info_file.empty () ? std_info_file : oct_info_file); - } + return (oct_info_file.empty () ? std_info_file : oct_info_file); +} - std::string help_system::init_info_program (void) - { - std::string info_prog = sys::env::getenv ("OCTAVE_INFO_PROGRAM"); +std::string help_system::init_info_program (void) +{ + std::string info_prog = sys::env::getenv ("OCTAVE_INFO_PROGRAM"); - if (info_prog.empty ()) - info_prog = "info"; + if (info_prog.empty ()) + info_prog = "info"; - return info_prog; - } + return info_prog; +} - std::string help_system::init_texi_macros_file (void) - { - std::string def_file - = config::prepend_octave_home (OCTAVE_TEXI_MACROS_FILE); +std::string help_system::init_texi_macros_file (void) +{ + std::string def_file + = config::prepend_octave_home (OCTAVE_TEXI_MACROS_FILE); - std::string env_file = sys::env::getenv ("OCTAVE_TEXI_MACROS_FILE"); + std::string env_file = sys::env::getenv ("OCTAVE_TEXI_MACROS_FILE"); - return (env_file.empty () ? def_file : env_file); - } + return (env_file.empty () ? def_file : env_file); +} - // Return a vector of all functions from this file, - // for use in command line auto-completion. - string_vector help_system::local_functions (void) const - { - string_vector retval; +// Return a vector of all functions from this file, +// for use in command line auto-completion. +string_vector help_system::local_functions (void) const +{ + string_vector retval; - tree_evaluator& tw = m_interpreter.get_evaluator (); + tree_evaluator& tw = m_interpreter.get_evaluator (); - octave_user_code *curr_fcn = tw.current_user_code (); + octave_user_code *curr_fcn = tw.current_user_code (); - if (! curr_fcn) - return retval; + if (! curr_fcn) + return retval; - // All subfunctions are listed in the top-level function of this file. - // If curr_fcn is a subfunction, then there must be a parent and - // curr_fcn will always be valid in and after executing this loop. + // All subfunctions are listed in the top-level function of this file. + // If curr_fcn is a subfunction, then there must be a parent and + // curr_fcn will always be valid in and after executing this loop. - while (curr_fcn->is_subfunction ()) - { - symbol_scope pscope = curr_fcn->parent_fcn_scope (); - curr_fcn = pscope.user_code (); - } + while (curr_fcn->is_subfunction ()) + { + symbol_scope pscope = curr_fcn->parent_fcn_scope (); + curr_fcn = pscope.user_code (); + } - // Get subfunctions. - const std::list names = curr_fcn->subfunction_names (); + // Get subfunctions. + const std::list names = curr_fcn->subfunction_names (); - std::size_t sz = names.size (); - retval.resize (sz); + std::size_t sz = names.size (); + retval.resize (sz); - // Loop over them. - std::size_t i = 0; - for (const auto& nm : names) - retval(i++) = nm; + // Loop over them. + std::size_t i = 0; + for (const auto& nm : names) + retval(i++) = nm; - return retval; - } + return retval; +} - bool help_system::raw_help_from_symbol_table (const std::string& nm, - std::string& h, std::string& w, - bool& symbol_found) const - { - std::string meth_nm; +bool help_system::raw_help_from_symbol_table (const std::string& nm, + std::string& h, std::string& w, + bool& symbol_found) const +{ + std::string meth_nm; - symbol_table& symtab = m_interpreter.get_symbol_table (); + symbol_table& symtab = m_interpreter.get_symbol_table (); - octave_value val = symtab.find_function (nm); + octave_value val = symtab.find_function (nm); - if (! val.is_defined ()) - { - std::size_t pos = nm.rfind ('.'); + if (! val.is_defined ()) + { + std::size_t pos = nm.rfind ('.'); - if (pos != std::string::npos) - { - meth_nm = nm.substr (pos+1); + if (pos != std::string::npos) + { + meth_nm = nm.substr (pos+1); - val = symtab.find_function (nm.substr (0, pos)); - } - } + val = symtab.find_function (nm.substr (0, pos)); + } + } - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - if (fcn) - { - // FCN may actually be a classdef_meta object. + if (fcn) + { + // FCN may actually be a classdef_meta object. - symbol_found = true; + symbol_found = true; - h = fcn->doc_string (meth_nm); + h = fcn->doc_string (meth_nm); - w = fcn->fcn_file_name (); + w = fcn->fcn_file_name (); - if (w.empty ()) - w = fcn->is_user_function () ? "command-line function" + if (w.empty ()) + w = fcn->is_user_function () ? "command-line function" : "built-in function"; - return true; - } - } + return true; + } + } - return false; - } + return false; +} - bool help_system::raw_help_from_file (const std::string& nm, - std::string& h, std::string& file, - bool& symbol_found) const - { - bool retval = false; +bool help_system::raw_help_from_file (const std::string& nm, + std::string& h, std::string& file, + bool& symbol_found) const +{ + bool retval = false; - h = get_help_from_file (nm, symbol_found, file); + h = get_help_from_file (nm, symbol_found, file); - if (h.length () > 0) - retval = true; + if (h.length () > 0) + retval = true; - return retval; - } + return retval; +} - bool - help_system::raw_help_from_docstrings_file (const std::string& nm, - std::string& h, - bool& symbol_found) const - { - typedef std::pair txt_limits_type; - typedef std::map help_txt_map_type; +bool +help_system::raw_help_from_docstrings_file (const std::string& nm, + std::string& h, + bool& symbol_found) const +{ + typedef std::pair txt_limits_type; + typedef std::map help_txt_map_type; - static help_txt_map_type help_txt_map; - static bool initialized = false; + static help_txt_map_type help_txt_map; + static bool initialized = false; - h = ""; - symbol_found = false; + h = ""; + symbol_found = false; - // FIXME: Should we cache the timestamp of the file and reload the - // offsets if it changes? Or just warn about that? Or just ignore - // it, and assume it won't change? + // FIXME: Should we cache the timestamp of the file and reload the + // offsets if it changes? Or just warn about that? Or just ignore + // it, and assume it won't change? - if (! initialized) - { - std::ifstream file = sys::ifstream (m_built_in_docstrings_file.c_str (), - std::ios::in | std::ios::binary); + if (! initialized) + { + 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", - m_built_in_docstrings_file.c_str ()); + if (! file) + error ("failed to open docstrings file: %s", + m_built_in_docstrings_file.c_str ()); - // Ignore header; - file.ignore (std::numeric_limits::max(), 0x1d); + // Ignore header; + file.ignore (std::numeric_limits::max(), 0x1d); - if (file.eof ()) - error ("invalid built-in-docstrings file!"); + if (file.eof ()) + error ("invalid built-in-docstrings file!"); - // FIXME: eliminate fixed buffer size. - std::size_t bufsize = 1000; - OCTAVE_LOCAL_BUFFER (char, buf, bufsize); + // FIXME: eliminate fixed buffer size. + std::size_t bufsize = 1000; + OCTAVE_LOCAL_BUFFER (char, buf, bufsize); - while (! file.eof ()) - { - std::string name; - int i = 0; - int c; - while (file - && (c = file.get ()) != std::istream::traits_type::eof ()) - { - if (c == '\n' || c == '\r') - { - buf[i] = '\0'; - name = buf; - break; - } - else - buf[i++] = c; - } + while (! file.eof ()) + { + std::string name; + int i = 0; + int c; + while (file + && (c = file.get ()) != std::istream::traits_type::eof ()) + { + if (c == '\n' || c == '\r') + { + buf[i] = '\0'; + name = buf; + break; + } + else + buf[i++] = c; + } - // Skip @c FILENAME which is part of current DOCSTRINGS - // syntax. This may disappear if a specific format for - // docstring files is developed. - while (file - && (c = file.get ()) != std::istream::traits_type::eof () - && c != '\n' && c != '\r') - ; // skip text + // Skip @c FILENAME which is part of current DOCSTRINGS + // syntax. This may disappear if a specific format for + // docstring files is developed. + while (file + && (c = file.get ()) != std::istream::traits_type::eof () + && c != '\n' && c != '\r') + ; // skip text - // skip newline characters - while (file - && (c = file.get ()) != std::istream::traits_type::eof () - && (c == '\n' || c == '\r')) - ; // skip text + // skip newline characters + while (file + && (c = file.get ()) != std::istream::traits_type::eof () + && (c == '\n' || c == '\r')) + ; // skip text - file.unget (); + file.unget (); - // Position of beginning of help text. - std::streampos beg = file.tellg (); + // Position of beginning of help text. + std::streampos beg = file.tellg (); - // Skip help text. - file.ignore (std::numeric_limits::max(), 0x1d); + // Skip help text. + file.ignore (std::numeric_limits::max(), 0x1d); + + // Position of end of help text. + std::streamoff len; - // Position of end of help text. - std::streamoff len; - - if (! file.eof ()) + if (! file.eof ()) + len = file.tellg () - beg - 1; + else + { + file.seekg (0, file.end); len = file.tellg () - beg - 1; - else - { - file.seekg (0, file.end); - len = file.tellg () - beg - 1; - file.setstate (file.eofbit); // reset eof flag - } + file.setstate (file.eofbit); // reset eof flag + } - help_txt_map[name] = txt_limits_type (beg, len); - } + help_txt_map[name] = txt_limits_type (beg, len); + } - initialized = true; - } + initialized = true; + } - help_txt_map_type::const_iterator it = help_txt_map.find (nm); + help_txt_map_type::const_iterator it = help_txt_map.find (nm); - if (it != help_txt_map.end ()) - { - txt_limits_type txt_limits = it->second; + if (it != help_txt_map.end ()) + { + txt_limits_type txt_limits = it->second; - std::streampos beg = txt_limits.first; - std::streamoff len = txt_limits.second; + std::streampos beg = txt_limits.first; + std::streamoff len = txt_limits.second; - std::ifstream file = sys::ifstream (m_built_in_docstrings_file.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", - m_built_in_docstrings_file.c_str ()); + if (! file) + error ("failed to open docstrings file: %s", + m_built_in_docstrings_file.c_str ()); - file.seekg (beg); + file.seekg (beg); - std::size_t txt_len = len; - OCTAVE_LOCAL_BUFFER (char, buf, txt_len + 1); + std::size_t txt_len = len; + OCTAVE_LOCAL_BUFFER (char, buf, txt_len + 1); - file.read (buf, txt_len); + file.read (buf, txt_len); - buf[txt_len] = '\0'; + buf[txt_len] = '\0'; - h = buf; + h = buf; - symbol_found = true; - } + symbol_found = true; + } - return symbol_found; - } + return symbol_found; +} - // FIXME: It's not likely that this does the right thing now. +// FIXME: It's not likely that this does the right thing now. - string_vector make_name_list (void) - { - help_system& help_sys = __get_help_system__ (); +string_vector make_name_list (void) +{ + help_system& help_sys = __get_help_system__ (); - return help_sys.make_name_list (); - } + return help_sys.make_name_list (); +} DEFMETHOD (get_help_text, interp, args, , doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/help.h --- a/libinterp/corefcn/help.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/help.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,170 +38,170 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; - class help_system - { - public: +class help_system +{ +public: - help_system (interpreter& interp) - : m_interpreter (interp), - m_built_in_docstrings_file (init_built_in_docstrings_file ()), - m_doc_cache_file (init_doc_cache_file ()), - m_info_file (init_info_file ()), - m_info_program (init_info_program ()), - m_makeinfo_program ("makeinfo"), - m_suppress_verbose_help_message (false), - m_texi_macros_file (init_texi_macros_file ()) - { } + help_system (interpreter& interp) + : m_interpreter (interp), + m_built_in_docstrings_file (init_built_in_docstrings_file ()), + m_doc_cache_file (init_doc_cache_file ()), + m_info_file (init_info_file ()), + m_info_program (init_info_program ()), + m_makeinfo_program ("makeinfo"), + m_suppress_verbose_help_message (false), + m_texi_macros_file (init_texi_macros_file ()) + { } - octave_value - built_in_docstrings_file (const octave_value_list& args, int nargout); + octave_value + built_in_docstrings_file (const octave_value_list& args, int nargout); - std::string - built_in_docstrings_file (void) const { return m_built_in_docstrings_file; } + std::string + built_in_docstrings_file (void) const { return m_built_in_docstrings_file; } - std::string built_in_docstrings_file (const std::string& file) - { - return set (m_built_in_docstrings_file, file); - } + std::string built_in_docstrings_file (const std::string& file) + { + return set (m_built_in_docstrings_file, file); + } - octave_value doc_cache_file (const octave_value_list& args, int nargout); + octave_value doc_cache_file (const octave_value_list& args, int nargout); - std::string doc_cache_file (void) const { return m_doc_cache_file; } + std::string doc_cache_file (void) const { return m_doc_cache_file; } - std::string doc_cache_file (const std::string& file) - { - return set (m_doc_cache_file, file); - } + std::string doc_cache_file (const std::string& file) + { + return set (m_doc_cache_file, file); + } - octave_value info_file (const octave_value_list& args, int nargout); + octave_value info_file (const octave_value_list& args, int nargout); - std::string info_file (void) const { return m_info_file; } + std::string info_file (void) const { return m_info_file; } - std::string info_file (const std::string& file) - { - return set (m_info_file, file); - } + std::string info_file (const std::string& file) + { + return set (m_info_file, file); + } - octave_value info_program (const octave_value_list& args, int nargout); + octave_value info_program (const octave_value_list& args, int nargout); - std::string info_program (void) const { return m_info_program; } + std::string info_program (void) const { return m_info_program; } - std::string info_program (const std::string& file) - { - return set (m_info_program, file); - } + std::string info_program (const std::string& file) + { + return set (m_info_program, file); + } - octave_value makeinfo_program (const octave_value_list& args, int nargout); + octave_value makeinfo_program (const octave_value_list& args, int nargout); - std::string makeinfo_program (void) const { return m_makeinfo_program; } + std::string makeinfo_program (void) const { return m_makeinfo_program; } - std::string makeinfo_program (const std::string& file) - { - return set (m_makeinfo_program, file); - } + std::string makeinfo_program (const std::string& file) + { + return set (m_makeinfo_program, file); + } - octave_value - suppress_verbose_help_message (const octave_value_list& args, int nargout); + octave_value + suppress_verbose_help_message (const octave_value_list& args, int nargout); - bool suppress_verbose_help_message (void) const - { - return m_suppress_verbose_help_message; - } + bool suppress_verbose_help_message (void) const + { + return m_suppress_verbose_help_message; + } - bool suppress_verbose_help_message (bool flag) - { - return set (m_suppress_verbose_help_message, flag); - } + bool suppress_verbose_help_message (bool flag) + { + return set (m_suppress_verbose_help_message, flag); + } - octave_value texi_macros_file (const octave_value_list& args, int nargout); + octave_value texi_macros_file (const octave_value_list& args, int nargout); - std::string texi_macros_file (void) const { return m_texi_macros_file; } + std::string texi_macros_file (void) const { return m_texi_macros_file; } - std::string texi_macros_file (const std::string& file) - { - return set (m_texi_macros_file, file); - } + std::string texi_macros_file (const std::string& file) + { + return set (m_texi_macros_file, file); + } - std::string raw_help (const std::string&, bool&) const; + std::string raw_help (const std::string&, bool&) const; - std::string which (const std::string& name) const; - std::string which (const std::string& name, std::string& type) const; + std::string which (const std::string& name) const; + std::string which (const std::string& name, std::string& type) const; - string_vector make_name_list (void) const; + string_vector make_name_list (void) const; - void get_help_text (const std::string& name, std::string& text, - std::string& format) const; + void get_help_text (const std::string& name, std::string& text, + std::string& format) const; - void get_help_text_from_file (const std::string& fname, std::string& text, - std::string& format) const; + void get_help_text_from_file (const std::string& fname, std::string& text, + std::string& format) const; - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - // Name of the file containing doc strings for built-in functions. - // (--built-in-docstrings-file file) - std::string m_built_in_docstrings_file; + // Name of the file containing doc strings for built-in functions. + // (--built-in-docstrings-file file) + std::string m_built_in_docstrings_file; - // Name of the doc cache file specified on the command line. - // (--doc-cache-file file) - std::string m_doc_cache_file; + // Name of the doc cache file specified on the command line. + // (--doc-cache-file file) + std::string m_doc_cache_file; - // Name of the info file specified on command line. - // (--info-file file) - std::string m_info_file; + // Name of the info file specified on command line. + // (--info-file file) + std::string m_info_file; - // Name of the info reader we'd like to use. - // (--info-program program) - std::string m_info_program; + // Name of the info reader we'd like to use. + // (--info-program program) + std::string m_info_program; - // Name of the makeinfo program to run. - std::string m_makeinfo_program; + // Name of the makeinfo program to run. + std::string m_makeinfo_program; - // If TRUE, don't print additional help message in help and usage - // functions. - bool m_suppress_verbose_help_message; + // If TRUE, don't print additional help message in help and usage + // functions. + bool m_suppress_verbose_help_message; - // Name of the file containing local Texinfo macros that are prepended - // to doc strings before processing. - // (--texi-macros-file) - std::string m_texi_macros_file; + // Name of the file containing local Texinfo macros that are prepended + // to doc strings before processing. + // (--texi-macros-file) + std::string m_texi_macros_file; - static std::string init_built_in_docstrings_file (void); + static std::string init_built_in_docstrings_file (void); - static std::string init_doc_cache_file (void); + static std::string init_doc_cache_file (void); - static std::string init_info_file (void); + static std::string init_info_file (void); - static std::string init_info_program (void); + static std::string init_info_program (void); - static std::string init_texi_macros_file (void); + static std::string init_texi_macros_file (void); - template - T set (T& var, const T& new_val) - { - T old_val = var; - var = new_val; - return old_val; - } + template + T set (T& var, const T& new_val) + { + T old_val = var; + var = new_val; + return old_val; + } - string_vector local_functions (void) const; + string_vector local_functions (void) const; - bool raw_help_from_symbol_table (const std::string& nm, - std::string& h, std::string& w, - bool& symbol_found) const; + bool raw_help_from_symbol_table (const std::string& nm, + std::string& h, std::string& w, + bool& symbol_found) const; - bool raw_help_from_file (const std::string& nm, - std::string& h, std::string& file, - bool& symbol_found) const; + bool raw_help_from_file (const std::string& nm, + std::string& h, std::string& file, + bool& symbol_found) const; - bool raw_help_from_docstrings_file (const std::string& nm, std::string& h, - bool& symbol_found) const; - }; + bool raw_help_from_docstrings_file (const std::string& nm, std::string& h, + bool& symbol_found) const; +}; - extern string_vector make_name_list (void); +extern string_vector make_name_list (void); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/hook-fcn.cc --- a/libinterp/corefcn/hook-fcn.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/hook-fcn.cc Thu Dec 01 20:05:44 2022 -0800 @@ -32,40 +32,40 @@ OCTAVE_BEGIN_NAMESPACE(octave) - hook_function::hook_function (const octave_value& f, const octave_value& d) - { - if (f.is_string ()) - { - std::string name = f.string_value (); +hook_function::hook_function (const octave_value& f, const octave_value& d) +{ + if (f.is_string ()) + { + std::string name = f.string_value (); - m_rep = std::shared_ptr (new named_hook_function (name, d)); - } - else if (f.is_function_handle ()) - { - m_rep = std::shared_ptr (new fcn_handle_hook_function (f, d)); - } - else - error ("invalid hook function"); - } + m_rep = std::shared_ptr (new named_hook_function (name, d)); + } + else if (f.is_function_handle ()) + { + m_rep = std::shared_ptr (new fcn_handle_hook_function (f, d)); + } + else + error ("invalid hook function"); +} - void named_hook_function::eval (const octave_value_list& initial_args) - { - octave_value_list args = initial_args; +void named_hook_function::eval (const octave_value_list& initial_args) +{ + octave_value_list args = initial_args; - if (m_data.is_defined ()) - args.append (m_data); + if (m_data.is_defined ()) + args.append (m_data); - feval (m_name, args, 0); - } + feval (m_name, args, 0); +} - void fcn_handle_hook_function::eval (const octave_value_list& initial_args) - { - octave_value_list args = initial_args; +void fcn_handle_hook_function::eval (const octave_value_list& initial_args) +{ + octave_value_list args = initial_args; - if (m_data.is_defined ()) - args.append (m_data); + if (m_data.is_defined ()) + args.append (m_data); - feval (m_fcn_handle, args, 0); - } + feval (m_fcn_handle, args, 0); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/hook-fcn.h --- a/libinterp/corefcn/hook-fcn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/hook-fcn.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,179 +38,179 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class base_hook_function - { - public: +class base_hook_function +{ +public: - base_hook_function (void) = default; + base_hook_function (void) = default; - base_hook_function (const base_hook_function&) = default; + base_hook_function (const base_hook_function&) = default; - virtual ~base_hook_function (void) = default; + virtual ~base_hook_function (void) = default; - virtual std::string id (void) const { return ""; } + virtual std::string id (void) const { return ""; } - virtual bool is_valid (void) const { return false; } + virtual bool is_valid (void) const { return false; } - virtual void eval (const octave_value_list&) { } - }; + virtual void eval (const octave_value_list&) { } +}; - class hook_function - { - public: +class hook_function +{ +public: - hook_function (void) - { - static std::shared_ptr - nil_rep (new base_hook_function ()); + hook_function (void) + { + static std::shared_ptr + nil_rep (new base_hook_function ()); - m_rep = nil_rep; - } + m_rep = nil_rep; + } - hook_function (const octave_value& f, - const octave_value& d = octave_value ()); + hook_function (const octave_value& f, + const octave_value& d = octave_value ()); - ~hook_function (void) = default; + ~hook_function (void) = default; - hook_function (const hook_function& hf) = default; + hook_function (const hook_function& hf) = default; - hook_function& operator = (const hook_function& hf) = default; + hook_function& operator = (const hook_function& hf) = default; - std::string id (void) const { return m_rep->id (); } + std::string id (void) const { return m_rep->id (); } - bool is_valid (void) const { return m_rep->is_valid (); } + bool is_valid (void) const { return m_rep->is_valid (); } - void eval (const octave_value_list& initial_args) - { - m_rep->eval (initial_args); - } + void eval (const octave_value_list& initial_args) + { + m_rep->eval (initial_args); + } - private: +private: - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; - class named_hook_function : public base_hook_function - { - public: +class named_hook_function : public base_hook_function +{ +public: - named_hook_function (const std::string& n, const octave_value& d) - : m_name (n), m_data (d) - { } + named_hook_function (const std::string& n, const octave_value& d) + : m_name (n), m_data (d) + { } - void eval (const octave_value_list& initial_args); + void eval (const octave_value_list& initial_args); - std::string id (void) const { return m_name; } + std::string id (void) const { return m_name; } - bool is_valid (void) const { return is_valid_function (m_name); } + bool is_valid (void) const { return is_valid_function (m_name); } - private: +private: + + std::string m_name; - std::string m_name; + octave_value m_data; +}; - octave_value m_data; - }; +class fcn_handle_hook_function : public base_hook_function +{ +public: - class fcn_handle_hook_function : public base_hook_function + fcn_handle_hook_function (const octave_value& fh_arg, const octave_value& d) + : m_ident (), m_valid (false), m_fcn_handle (fh_arg), m_data (d) { - public: + octave_fcn_handle *fh = m_fcn_handle.fcn_handle_value (true); - fcn_handle_hook_function (const octave_value& fh_arg, const octave_value& d) - : m_ident (), m_valid (false), m_fcn_handle (fh_arg), m_data (d) - { - octave_fcn_handle *fh = m_fcn_handle.fcn_handle_value (true); - - if (fh) - { - m_valid = true; + if (fh) + { + m_valid = true; - std::ostringstream buf; - buf << fh; - m_ident = fh->fcn_name () + ':' + buf.str (); - } - } + std::ostringstream buf; + buf << fh; + m_ident = fh->fcn_name () + ':' + buf.str (); + } + } - void eval (const octave_value_list& initial_args); + void eval (const octave_value_list& initial_args); - std::string id (void) const { return m_ident; } + std::string id (void) const { return m_ident; } - bool is_valid (void) const { return m_valid; } + bool is_valid (void) const { return m_valid; } - private: +private: - std::string m_ident; + std::string m_ident; - bool m_valid; + bool m_valid; - octave_value m_fcn_handle; + octave_value m_fcn_handle; - octave_value m_data; - }; + octave_value m_data; +}; - class hook_function_list - { - public: +class hook_function_list +{ +public: - typedef std::map map_type; + typedef std::map map_type; - typedef map_type::iterator iterator; - typedef map_type::const_iterator const_iterator; + typedef map_type::iterator iterator; + typedef map_type::const_iterator const_iterator; - hook_function_list (void) = default; + hook_function_list (void) = default; - ~hook_function_list (void) = default; + ~hook_function_list (void) = default; - hook_function_list (const hook_function_list& lst) = default; + hook_function_list (const hook_function_list& lst) = default; - hook_function_list& operator = (const hook_function_list& lst) = default; + hook_function_list& operator = (const hook_function_list& lst) = default; - bool empty (void) const { return m_fcn_map.empty (); } + bool empty (void) const { return m_fcn_map.empty (); } - void clear (void) { m_fcn_map.clear (); } + void clear (void) { m_fcn_map.clear (); } - void insert (const std::string& id, const hook_function& f) - { - m_fcn_map[id] = f; - } + void insert (const std::string& id, const hook_function& f) + { + m_fcn_map[id] = f; + } - iterator find (const std::string& id) - { - return m_fcn_map.find (id); - } + iterator find (const std::string& id) + { + return m_fcn_map.find (id); + } - const_iterator find (const std::string& id) const - { - return m_fcn_map.find (id); - } + const_iterator find (const std::string& id) const + { + return m_fcn_map.find (id); + } - iterator end (void) { return m_fcn_map.end (); } + iterator end (void) { return m_fcn_map.end (); } - const_iterator end (void) const { return m_fcn_map.end (); } + const_iterator end (void) const { return m_fcn_map.end (); } - void erase (iterator p) { m_fcn_map.erase (p); } + void erase (iterator p) { m_fcn_map.erase (p); } - void run (const octave_value_list& initial_args = octave_value_list ()) - { - auto p = m_fcn_map.begin (); + void run (const octave_value_list& initial_args = octave_value_list ()) + { + auto p = m_fcn_map.begin (); - while (p != m_fcn_map.end ()) - { - std::string hook_fcn_id = p->first; - hook_function hook_fcn = p->second; + while (p != m_fcn_map.end ()) + { + std::string hook_fcn_id = p->first; + hook_function hook_fcn = p->second; - auto q = p++; + auto q = p++; - if (hook_fcn.is_valid ()) - hook_fcn.eval (initial_args); - else - m_fcn_map.erase (q); - } - } + if (hook_fcn.is_valid ()) + hook_fcn.eval (initial_args); + else + m_fcn_map.erase (q); + } + } - private: +private: - map_type m_fcn_map; - }; + map_type m_fcn_map; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/input.cc --- a/libinterp/corefcn/input.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/input.cc Thu Dec 01 20:05:44 2022 -0800 @@ -92,1043 +92,1043 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static std::string - quoting_filename (const std::string& text, int, char quote) - { - if (quote) - return text; - else - return ("'" + text); - } +static std::string +quoting_filename (const std::string& text, int, char quote) +{ + if (quote) + return text; + else + return ("'" + text); +} + +// Try to parse a partial command line in reverse, excluding trailing TEXT. +// If it appears a variable has been indexed by () or {}, +// return that expression, +// to allow autocomplete of field names of arrays of structures. +static std::string +find_indexed_expression (const std::string& text) +{ + std::string line = command_editor::get_line_buffer (); + + int pos = line.length () - text.length (); + int curly_count = 0; + int paren_count = 0; + + int last = --pos; + + while (pos >= 0 && (line[pos] == ')' || line[pos] == '}')) + { + if (line[pos] == ')') + paren_count++; + else + curly_count++; + + while (curly_count + paren_count > 0 && --pos >= 0) + { + if (line[pos] == ')') + paren_count++; + else if (line[pos] == '(') + paren_count--; + else if (line[pos] == '}') + curly_count++; + else if (line[pos] == '{') + curly_count--; + } + + while (--pos >= 0 && line[pos] == ' ') + ; + } - // Try to parse a partial command line in reverse, excluding trailing TEXT. - // If it appears a variable has been indexed by () or {}, - // return that expression, - // to allow autocomplete of field names of arrays of structures. - static std::string - find_indexed_expression (const std::string& text) - { - std::string line = command_editor::get_line_buffer (); + while (pos >= 0 && (isalnum (line[pos]) || line[pos] == '_')) + pos--; + + if (++pos >= 0) + return (line.substr (pos, last + 1 - pos)); + else + return std::string (); +} + +static string_vector +generate_struct_completions (const std::string& text, + std::string& prefix, std::string& hint) +{ + string_vector names; + + std::size_t pos = text.rfind ('.'); + bool array = false; + + if (pos != std::string::npos) + { + if (pos == text.length ()) + hint = ""; + else + hint = text.substr (pos+1); - int pos = line.length () - text.length (); - int curly_count = 0; - int paren_count = 0; + prefix = text.substr (0, pos); - int last = --pos; + if (prefix == "") + { + array = true; + prefix = find_indexed_expression (text); + } + + std::string base_name = prefix; + + pos = base_name.find_first_of ("{(. "); - while (pos >= 0 && (line[pos] == ')' || line[pos] == '}')) - { - if (line[pos] == ')') - paren_count++; - else - curly_count++; + if (pos != std::string::npos) + base_name = base_name.substr (0, pos); + + interpreter& interp = __get_interpreter__ (); + + if (interp.is_variable (base_name)) + { + int parse_status; + + error_system& es = interp.get_error_system (); + + unwind_protect frame; - while (curly_count + paren_count > 0 && --pos >= 0) - { - if (line[pos] == ')') - paren_count++; - else if (line[pos] == '(') - paren_count--; - else if (line[pos] == '}') - curly_count++; - else if (line[pos] == '{') - curly_count--; - } + frame.add (&error_system::set_discard_warning_messages, &es, + es.discard_warning_messages ()); + + es.discard_warning_messages (true); + + try + { + octave_value tmp + = interp.eval_string (prefix, true, parse_status); + + frame.run (); + + if (tmp.is_defined () + && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ())) + names = tmp.map_keys (); + } + catch (const execution_exception&) + { + interp.recover_from_exception (); + } + } + } - while (--pos >= 0 && line[pos] == ' ') - ; - } + // Undo look-back that found the array expression, + // but insert an extra "." to distinguish from the non-struct case. + if (array) + prefix = "."; + + return names; +} - while (pos >= 0 && (isalnum (line[pos]) || line[pos] == '_')) - pos--; +// FIXME: this will have to be much smarter to work "correctly". +static bool +looks_like_struct (const std::string& text, char prev_char) +{ + bool retval = (! text.empty () + && (text != "." || prev_char == ')' || prev_char == '}') + && text.find_first_of (sys::file_ops::dir_sep_chars ()) == std::string::npos + && text.find ("..") == std::string::npos + && text.rfind ('.') != std::string::npos); + + return retval; +} + +// FIXME: make this generate filenames when appropriate. - if (++pos >= 0) - return (line.substr (pos, last + 1 - pos)); - else - return std::string (); - } +static string_vector +generate_possible_completions (const std::string& text, std::string& prefix, + std::string& hint, bool& deemed_struct) +{ + string_vector names; + + prefix = ""; + + char prev_char = command_editor::get_prev_char (text.length ()); + deemed_struct = looks_like_struct (text, prev_char); - static string_vector - generate_struct_completions (const std::string& text, - std::string& prefix, std::string& hint) - { - string_vector names; + if (deemed_struct) + names = generate_struct_completions (text, prefix, hint); + else + names = make_name_list (); + + // Sort and remove duplicates. + + names.sort (true); + + return names; +} - std::size_t pos = text.rfind ('.'); - bool array = false; +static bool +is_completing_dirfns (void) +{ + static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"}; + static const std::size_t dirfns_commands_length = 4; + + bool retval = false; + + std::string line = command_editor::get_line_buffer (); + + for (std::size_t i = 0; i < dirfns_commands_length; i++) + { + int index = line.find (dirfns_commands[i] + ' '); - if (pos != std::string::npos) - { - if (pos == text.length ()) - hint = ""; - else - hint = text.substr (pos+1); + if (index == 0) + { + retval = true; + break; + } + } - prefix = text.substr (0, pos); + return retval; +} + +static std::string +generate_completion (const std::string& text, int state) +{ + std::string retval; - if (prefix == "") - { - array = true; - prefix = find_indexed_expression (text); - } + static std::string prefix; + static std::string hint; + + static std::size_t hint_len = 0; + + static int list_index = 0; + static int name_list_len = 0; + static int name_list_total_len = 0; + static string_vector name_list; + static string_vector file_name_list; + + static int matches = 0; + + if (state == 0) + { + list_index = 0; + + prefix = ""; + + hint = text; + + // No reason to display symbols while completing a + // file/directory operation. - std::string base_name = prefix; + bool deemed_struct = false; - pos = base_name.find_first_of ("{(. "); + if (is_completing_dirfns ()) + name_list = string_vector (); + else + name_list = generate_possible_completions (text, prefix, hint, + deemed_struct); + + name_list_len = name_list.numel (); - if (pos != std::string::npos) - base_name = base_name.substr (0, pos); + // If the line was something like "a{1}." then text = "." but + // we don't want to expand all the . files. + if (! deemed_struct) + { + + file_name_list = command_editor::generate_filename_completions (text); - interpreter& interp = __get_interpreter__ (); + name_list.append (file_name_list); + + } + + name_list_total_len = name_list.numel (); + + hint_len = hint.length (); - if (interp.is_variable (base_name)) - { - int parse_status; + matches = 0; + + for (int i = 0; i < name_list_len; i++) + if (hint == name_list[i].substr (0, hint_len)) + matches++; + } - error_system& es = interp.get_error_system (); + if (name_list_total_len > 0 && matches > 0) + { + while (list_index < name_list_total_len) + { + std::string name = name_list[list_index]; + + list_index++; - unwind_protect frame; + if (hint == name.substr (0, hint_len)) + { + // Special case: array reference forces prefix="." + // in generate_struct_completions () + if (list_index <= name_list_len && ! prefix.empty ()) + retval = (prefix == "." ? "" : prefix) + '.' + name; + else + retval = name; - frame.add (&error_system::set_discard_warning_messages, &es, - es.discard_warning_messages ()); + char prev_char = + command_editor::get_prev_char (text.length ()); - es.discard_warning_messages (true); + if (matches == 1 && looks_like_struct (retval, prev_char)) + { + // Don't append anything, since we don't know + // whether it should be '(' or '.'. - try - { - octave_value tmp - = interp.eval_string (prefix, true, parse_status); + command_editor::set_completion_append_character ('\0'); + } + else + { + input_system& input_sys = __get_input_system__ (); - frame.run (); + command_editor::set_completion_append_character + (input_sys.completion_append_char ()); + } + + break; + } + } + } + + return retval; +} - if (tmp.is_defined () - && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ())) - names = tmp.map_keys (); - } - catch (const execution_exception&) - { - interp.recover_from_exception (); - } - } - } +static int internal_input_event_hook_fcn (void) +{ + octave_quit (); + + input_system& input_sys = __get_input_system__ (); + + input_sys.run_input_event_hooks (); + + return 0; +} + +// Use literal "octave" in default setting for PS1 instead of +// "\\s" to avoid setting the prompt to "octave.exe" or +// "octave-gui", etc. + +input_system::input_system (interpreter& interp) + : m_interpreter (interp), m_PS1 (R"(octave:\#> )"), m_PS2 ("> "), + m_completion_append_char (' '), m_gud_mode (false), + m_mfile_encoding ("utf-8"), m_auto_repeat_debug_command (true), + m_last_debugging_command ("\n"), m_input_event_hook_functions (), + m_initialized (false) +{ } - // Undo look-back that found the array expression, - // but insert an extra "." to distinguish from the non-struct case. - if (array) - prefix = "."; +void input_system::initialize (bool line_editing) +{ + if (m_initialized) + return; + + // Force default line editor if we don't want readline editing. + if (! line_editing) + { + command_editor::force_default_editor (); + return; + } - return names; - } + // If we are using readline, this allows conditional parsing of the + // .inputrc file. + + command_editor::set_name ("Octave"); + + // FIXME: this needs to include a comma too, but that + // causes trouble for the new struct element completion code. + + static const char *s = "\t\n !\"\'*+-/:;<=>(){}[\\]^`~"; + + command_editor::set_basic_word_break_characters (s); + + command_editor::set_completer_word_break_characters (s); - // FIXME: this will have to be much smarter to work "correctly". - static bool - looks_like_struct (const std::string& text, char prev_char) - { - bool retval = (! text.empty () - && (text != "." || prev_char == ')' || prev_char == '}') - && text.find_first_of (sys::file_ops::dir_sep_chars ()) == std::string::npos - && text.find ("..") == std::string::npos - && text.rfind ('.') != std::string::npos); + command_editor::set_basic_quote_characters (R"(")"); + + command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{"); + + command_editor::set_completer_quote_characters (R"('")"); + + command_editor::set_completion_function (generate_completion); + + command_editor::set_quoting_function (quoting_filename); - return retval; - } + command_editor::add_event_hook (internal_input_event_hook_fcn); + + m_initialized = true; +} + +octave_value +input_system::PS1 (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_PS1, args, nargout, "PS1"); +} - // FIXME: make this generate filenames when appropriate. +octave_value +input_system::PS2 (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_PS2, args, nargout, "PS2"); +} + +octave_value +input_system::completion_append_char (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_completion_append_char, args, nargout, + "completion_append_char"); +} - static string_vector - generate_possible_completions (const std::string& text, std::string& prefix, - std::string& hint, bool& deemed_struct) - { - string_vector names; +octave_value +input_system::gud_mode (const octave_value_list& args, int nargout) +{ + return set_internal_variable (m_gud_mode, args, nargout, "__gud_mode__"); +} - prefix = ""; +octave_value +input_system::mfile_encoding (const octave_value_list& args, int nargout) +{ + // Save current value in case there is an error in the additional + // validation below. - char prev_char = command_editor::get_prev_char (text.length ()); - deemed_struct = looks_like_struct (text, prev_char); + std::string saved_encoding = m_mfile_encoding; + + // We must pass the actual variable to change here for temporary + // "local" settings to work properly. - if (deemed_struct) - names = generate_struct_completions (text, prefix, hint); - else - names = make_name_list (); + octave_value retval + = set_internal_variable (m_mfile_encoding, args, nargout, + "__mfile_encoding__"); + + // Additional validation if the encoding has changed. - // Sort and remove duplicates. + if (m_mfile_encoding != saved_encoding) + { + if (m_mfile_encoding.empty ()) + { + m_mfile_encoding = "system"; + } + else + { + std::transform (m_mfile_encoding.begin (), + m_mfile_encoding.end (), + m_mfile_encoding.begin (), ::tolower); - names.sort (true); + std::string encoding = (m_mfile_encoding.compare ("system") == 0) + ? octave_locale_charset_wrapper () : m_mfile_encoding; - return names; - } + // Check for valid encoding name. + void *codec + = octave_iconv_open_wrapper (encoding.c_str (), "utf-8"); - static bool - is_completing_dirfns (void) - { - static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"}; - static const std::size_t dirfns_commands_length = 4; + if (codec == reinterpret_cast (-1)) + { + m_mfile_encoding = saved_encoding; + if (errno == EINVAL) + error ("__mfile_encoding__: conversion from encoding '%s' " + "not supported", encoding.c_str ()); + else + error ("__mfile_encoding__: error %d opening encoding '%s'", + errno, encoding.c_str ()); + } + else + octave_iconv_close_wrapper (codec); + } + + } + + // Synchronize the related gui preference for editor encoding + feval ("__event_manager_gui_preference__", + ovl ("editor/default_encoding", m_mfile_encoding)); + + return retval; +} - bool retval = false; - - std::string line = command_editor::get_line_buffer (); +// Get part of the directory that would be added to the load path +static std::string load_path_dir (const std::string& dir) +{ + std::string lp_dir = dir; - for (std::size_t i = 0; i < dirfns_commands_length; i++) - { - int index = line.find (dirfns_commands[i] + ' '); + // strip trailing filesep + std::size_t ipos = lp_dir.find_last_not_of (sys::file_ops::dir_sep_chars ()); + if (ipos != std::string::npos) + lp_dir = lp_dir.erase (ipos+1); + + // strip trailing private folder + ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); + if (ipos != std::string::npos + && lp_dir.substr (ipos+1).compare ("private") == 0) + { + lp_dir = lp_dir.erase (ipos); + ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); + } - if (index == 0) - { - retval = true; - break; - } - } + // strip trailing @class folder + if (ipos != std::string::npos && lp_dir[ipos+1] == '@') + { + lp_dir = lp_dir.erase (ipos); + ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); + } + + // strip (nested) +namespace folders + while (ipos != std::string::npos && lp_dir[ipos+1] == '+') + { + lp_dir = lp_dir.erase (ipos); + ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); + } - return retval; - } + return lp_dir; +} + +std::string input_system::dir_encoding (const std::string& dir) +{ + std::string enc = m_mfile_encoding; + // use canonicalized path as key + const std::string key = sys::canonicalize_file_name (dir); + + auto enc_it = m_dir_encoding.find (key); + if (enc_it != m_dir_encoding.end ()) + enc = enc_it->second; + + return enc; +} - static std::string - generate_completion (const std::string& text, int state) - { - std::string retval; +void input_system::set_dir_encoding (const std::string& dir, + std::string& enc) +{ + // use lower case + std::transform (enc.begin (), enc.end (), enc.begin (), ::tolower); - static std::string prefix; - static std::string hint; - - static std::size_t hint_len = 0; + if (enc.compare ("delete") == 0) + { + // Remove path from map + m_dir_encoding.erase (load_path_dir (dir)); + return; + } + else if (enc.compare ("utf-8")) + { + // Check for valid encoding name. + // FIXME: This will probably not happen very often and opening the + // encoder doesn't take long. + // Should we cache working encoding identifiers anyway? + void *codec + = octave_iconv_open_wrapper (enc.c_str (), "utf-8"); - static int list_index = 0; - static int name_list_len = 0; - static int name_list_total_len = 0; - static string_vector name_list; - static string_vector file_name_list; + if (codec == reinterpret_cast (-1)) + { + if (errno == EINVAL) + error ("dir_encoding: conversion from encoding '%s' " + "not supported", enc.c_str ()); + else + error ("dir_encoding: error %d opening encoding '%s'.", + errno, enc.c_str ()); + } + else + octave_iconv_close_wrapper (codec); + } - static int matches = 0; + m_dir_encoding[load_path_dir (dir)] = enc; + + return; +} - if (state == 0) - { - list_index = 0; +octave_value +input_system::auto_repeat_debug_command (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_auto_repeat_debug_command, args, nargout, + "auto_repeat_debug_command"); +} - prefix = ""; +bool input_system::yes_or_no (const std::string& prompt) +{ + std::string prompt_string = prompt + "(yes or no) "; - hint = text; + while (1) + { + bool eof = false; + + std::string input_buf = interactive_input (prompt_string, eof); - // No reason to display symbols while completing a - // file/directory operation. + if (input_buf == "yes") + return true; + else if (input_buf == "no") + return false; + else + message (nullptr, "Please answer yes or no."); + } +} - bool deemed_struct = false; +std::string input_system::interactive_input (const std::string& s, bool& eof) +{ + Vlast_prompt_time.stamp (); + + if (Vdrawnow_requested && m_interpreter.interactive ()) + { + bool eval_error = false; - if (is_completing_dirfns ()) - name_list = string_vector (); - else - name_list = generate_possible_completions (text, prefix, hint, - deemed_struct); + try + { + Fdrawnow (m_interpreter); + } + catch (const execution_exception& ee) + { + eval_error = true; + + m_interpreter.handle_exception (ee); + } + + flush_stdout (); - name_list_len = name_list.numel (); + // We set Vdrawnow_requested to false even if there is an error in + // drawnow so that the error doesn't reappear at every prompt. + + Vdrawnow_requested = false; - // If the line was something like "a{1}." then text = "." but - // we don't want to expand all the . files. - if (! deemed_struct) - { + if (eval_error) + return "\n"; + } + + return gnu_readline (s, eof); +} + +// If the user simply hits return, this will produce an empty matrix. - file_name_list = command_editor::generate_filename_completions (text); +octave_value_list +input_system::get_user_input (const octave_value_list& args, int nargout) +{ + octave_value_list retval; - name_list.append (file_name_list); + std::string prompt = args(0).xstring_value ("input: unrecognized argument"); - } + bool read_as_string = false; + if (args.length () == 2) // `input (..., "s")`? + { + std::string literal + = args(1).xstring_value ("input: second argument must be 's'."); + if (literal.length () != 1 || literal[0] != 's') + error ("input: second argument must be 's'."); - name_list_total_len = name_list.numel (); + read_as_string = true; + } - hint_len = hint.length (); + output_system& output_sys = m_interpreter.get_output_system (); + + output_sys.reset (); - matches = 0; + octave_diary << prompt; + + bool eof = false; + + std::string input_buf = interactive_input (prompt.c_str (), eof); - for (int i = 0; i < name_list_len; i++) - if (hint == name_list[i].substr (0, hint_len)) - matches++; - } + if (input_buf.empty ()) + error ("input: reading user-input failed!"); + + std::size_t len = input_buf.length (); + + octave_diary << input_buf; + + if (input_buf[len - 1] != '\n') + octave_diary << "\n"; - if (name_list_total_len > 0 && matches > 0) - { - while (list_index < name_list_total_len) - { - std::string name = name_list[list_index]; + if (read_as_string) + { + // FIXME: fix gnu_readline and octave_gets instead! + if (input_buf.length () == 1 && input_buf[0] == '\n') + retval(0) = ""; + else + retval(0) = input_buf; + } + else + { + int parse_status = 0; - list_index++; + retval + = m_interpreter.eval_string (input_buf, true, parse_status, nargout); + + tree_evaluator& tw = m_interpreter.get_evaluator (); + + if (! tw.in_debug_repl () && retval.empty ()) + retval(0) = Matrix (); + } + + return retval; +} + +bool input_system::have_input_event_hooks (void) const +{ + return ! m_input_event_hook_functions.empty (); +} - if (hint == name.substr (0, hint_len)) - { - // Special case: array reference forces prefix="." - // in generate_struct_completions () - if (list_index <= name_list_len && ! prefix.empty ()) - retval = (prefix == "." ? "" : prefix) + '.' + name; - else - retval = name; +void input_system::add_input_event_hook (const hook_function& hook_fcn) +{ + m_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn); +} + +bool input_system::remove_input_event_hook (const std::string& hook_fcn_id) +{ + hook_function_list::iterator p + = m_input_event_hook_functions.find (hook_fcn_id); + + if (p == m_input_event_hook_functions.end ()) + return false; - char prev_char = - command_editor::get_prev_char (text.length ()); + m_input_event_hook_functions.erase (p); + return true; +} + +void input_system::clear_input_event_hooks (void) +{ + m_input_event_hook_functions.clear (); +} + +void input_system::run_input_event_hooks (void) +{ + m_input_event_hook_functions.run (); +} + +std::string +input_system::gnu_readline (const std::string& s, bool& eof) const +{ + octave_quit (); - if (matches == 1 && looks_like_struct (retval, prev_char)) - { - // Don't append anything, since we don't know - // whether it should be '(' or '.'. + eof = false; + + std::string retval = command_editor::readline (s, eof); + + if (! eof && retval.empty ()) + retval = "\n"; + + return retval; +} + +std::string base_reader::octave_gets (const std::string& prompt, bool& eof) +{ + octave_quit (); + + eof = false; + + std::string retval; + + // Process pre input event hook function prior to flushing output and + // printing the prompt. + + tree_evaluator& tw = m_interpreter.get_evaluator (); - command_editor::set_completion_append_character ('\0'); - } - else - { - input_system& input_sys = __get_input_system__ (); + event_manager& evmgr = m_interpreter.get_event_manager (); + + if (m_interpreter.interactive ()) + { + if (! tw.in_debug_repl ()) + evmgr.exit_debugger_event (); + + evmgr.pre_input_event (); + + evmgr.set_workspace (); + } - command_editor::set_completion_append_character - (input_sys.completion_append_char ()); - } + bool history_skip_auto_repeated_debugging_command = false; + + input_system& input_sys = m_interpreter.get_input_system (); + + pipe_handler_error_count = 0; - break; - } - } - } + output_system& output_sys = m_interpreter.get_output_system (); + + output_sys.reset (); + + octave_diary << prompt; + + retval = input_sys.interactive_input (prompt, eof); - return retval; - } + // There is no need to update the load_path cache if there is no + // user input. + if (retval != "\n" + && retval.find_first_not_of (" \t\n\r") != std::string::npos) + { + load_path& lp = m_interpreter.get_load_path (); + + lp.update (); - static int internal_input_event_hook_fcn (void) - { - octave_quit (); - - input_system& input_sys = __get_input_system__ (); - - input_sys.run_input_event_hooks (); + if (tw.in_debug_repl ()) + input_sys.last_debugging_command (retval); + else + input_sys.last_debugging_command ("\n"); + } + else if (tw.in_debug_repl () && input_sys.auto_repeat_debug_command ()) + { + retval = input_sys.last_debugging_command (); + history_skip_auto_repeated_debugging_command = true; + } - return 0; - } + if (retval != "\n") + { + if (! history_skip_auto_repeated_debugging_command) + { + if (command_history::add (retval)) + evmgr.append_history (retval); + } - // Use literal "octave" in default setting for PS1 instead of - // "\\s" to avoid setting the prompt to "octave.exe" or - // "octave-gui", etc. + octave_diary << retval; + + if (! retval.empty () && retval.back () != '\n') + octave_diary << "\n"; + } + else + octave_diary << "\n"; - input_system::input_system (interpreter& interp) - : m_interpreter (interp), m_PS1 (R"(octave:\#> )"), m_PS2 ("> "), - m_completion_append_char (' '), m_gud_mode (false), - m_mfile_encoding ("utf-8"), m_auto_repeat_debug_command (true), - m_last_debugging_command ("\n"), m_input_event_hook_functions (), - m_initialized (false) + // Process post input event hook function after the internal history + // list has been updated. + + if (m_interpreter.interactive ()) + evmgr.post_input_event (); + + return retval; +} + +class +terminal_reader : public base_reader +{ +public: + + terminal_reader (interpreter& interp) + : base_reader (interp), m_eof (false), m_input_queue () { } - void input_system::initialize (bool line_editing) - { - if (m_initialized) - return; - - // Force default line editor if we don't want readline editing. - if (! line_editing) - { - command_editor::force_default_editor (); - return; - } - - // If we are using readline, this allows conditional parsing of the - // .inputrc file. - - command_editor::set_name ("Octave"); - - // FIXME: this needs to include a comma too, but that - // causes trouble for the new struct element completion code. + std::string get_input (const std::string& prompt, bool& eof); - static const char *s = "\t\n !\"\'*+-/:;<=>(){}[\\]^`~"; - - command_editor::set_basic_word_break_characters (s); - - command_editor::set_completer_word_break_characters (s); - - command_editor::set_basic_quote_characters (R"(")"); - - command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{"); - - command_editor::set_completer_quote_characters (R"('")"); - - command_editor::set_completion_function (generate_completion); - - command_editor::set_quoting_function (quoting_filename); - - command_editor::add_event_hook (internal_input_event_hook_fcn); - - m_initialized = true; - } + std::string input_source (void) const { return s_in_src; } - octave_value - input_system::PS1 (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_PS1, args, nargout, "PS1"); - } - - octave_value - input_system::PS2 (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_PS2, args, nargout, "PS2"); - } - - octave_value - input_system::completion_append_char (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_completion_append_char, args, nargout, - "completion_append_char"); - } + bool input_from_terminal (void) const { return true; } - octave_value - input_system::gud_mode (const octave_value_list& args, int nargout) - { - return set_internal_variable (m_gud_mode, args, nargout, "__gud_mode__"); - } +private: - octave_value - input_system::mfile_encoding (const octave_value_list& args, int nargout) - { - // Save current value in case there is an error in the additional - // validation below. - - std::string saved_encoding = m_mfile_encoding; - - // We must pass the actual variable to change here for temporary - // "local" settings to work properly. - - octave_value retval - = set_internal_variable (m_mfile_encoding, args, nargout, - "__mfile_encoding__"); - - // Additional validation if the encoding has changed. + bool m_eof; + std::queue m_input_queue; - if (m_mfile_encoding != saved_encoding) - { - if (m_mfile_encoding.empty ()) - { - m_mfile_encoding = "system"; - } - else - { - std::transform (m_mfile_encoding.begin (), - m_mfile_encoding.end (), - m_mfile_encoding.begin (), ::tolower); - - std::string encoding = (m_mfile_encoding.compare ("system") == 0) - ? octave_locale_charset_wrapper () : m_mfile_encoding; - - // Check for valid encoding name. - void *codec - = octave_iconv_open_wrapper (encoding.c_str (), "utf-8"); + static const std::string s_in_src; +}; - if (codec == reinterpret_cast (-1)) - { - m_mfile_encoding = saved_encoding; - if (errno == EINVAL) - error ("__mfile_encoding__: conversion from encoding '%s' " - "not supported", encoding.c_str ()); - else - error ("__mfile_encoding__: error %d opening encoding '%s'", - errno, encoding.c_str ()); - } - else - octave_iconv_close_wrapper (codec); - } +class +file_reader : public base_reader +{ +public: - } - - // Synchronize the related gui preference for editor encoding - feval ("__event_manager_gui_preference__", - ovl ("editor/default_encoding", m_mfile_encoding)); - - return retval; - } - - // Get part of the directory that would be added to the load path - static std::string load_path_dir (const std::string& dir) + file_reader (interpreter& interp, FILE *f_arg) + : base_reader (interp), m_file (f_arg) { - std::string lp_dir = dir; - - // strip trailing filesep - std::size_t ipos = lp_dir.find_last_not_of (sys::file_ops::dir_sep_chars ()); - if (ipos != std::string::npos) - lp_dir = lp_dir.erase (ipos+1); - - // strip trailing private folder - ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); - if (ipos != std::string::npos - && lp_dir.substr (ipos+1).compare ("private") == 0) - { - lp_dir = lp_dir.erase (ipos); - ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); - } - - // strip trailing @class folder - if (ipos != std::string::npos && lp_dir[ipos+1] == '@') - { - lp_dir = lp_dir.erase (ipos); - ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); - } - - // strip (nested) +namespace folders - while (ipos != std::string::npos && lp_dir[ipos+1] == '+') - { - lp_dir = lp_dir.erase (ipos); - ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ()); - } - - return lp_dir; - } - - std::string input_system::dir_encoding (const std::string& dir) - { - std::string enc = m_mfile_encoding; - // use canonicalized path as key - const std::string key = sys::canonicalize_file_name (dir); - - auto enc_it = m_dir_encoding.find (key); - if (enc_it != m_dir_encoding.end ()) - enc = enc_it->second; - - return enc; + input_system& input_sys = interp.get_input_system (); + m_encoding = input_sys.mfile_encoding (); } - void input_system::set_dir_encoding (const std::string& dir, - std::string& enc) - { - // use lower case - std::transform (enc.begin (), enc.end (), enc.begin (), ::tolower); + file_reader (interpreter& interp, FILE *f_arg, const std::string& enc) + : base_reader (interp), m_file (f_arg), m_encoding (enc) { } + + std::string get_input (const std::string& prompt, bool& eof); - if (enc.compare ("delete") == 0) - { - // Remove path from map - m_dir_encoding.erase (load_path_dir (dir)); - return; - } - else if (enc.compare ("utf-8")) - { - // Check for valid encoding name. - // FIXME: This will probably not happen very often and opening the - // encoder doesn't take long. - // Should we cache working encoding identifiers anyway? - void *codec - = octave_iconv_open_wrapper (enc.c_str (), "utf-8"); + std::string input_source (void) const { return s_in_src; } + + bool input_from_file (void) const { return true; } - if (codec == reinterpret_cast (-1)) - { - if (errno == EINVAL) - error ("dir_encoding: conversion from encoding '%s' " - "not supported", enc.c_str ()); - else - error ("dir_encoding: error %d opening encoding '%s'.", - errno, enc.c_str ()); - } - else - octave_iconv_close_wrapper (codec); - } +private: - m_dir_encoding[load_path_dir (dir)] = enc; + FILE *m_file; - return; - } + std::string m_encoding; - octave_value - input_system::auto_repeat_debug_command (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_auto_repeat_debug_command, args, nargout, - "auto_repeat_debug_command"); - } - - bool input_system::yes_or_no (const std::string& prompt) - { - std::string prompt_string = prompt + "(yes or no) "; - - while (1) - { - bool eof = false; + static const std::string s_in_src; +}; - std::string input_buf = interactive_input (prompt_string, eof); +class +eval_string_reader : public base_reader +{ +public: - if (input_buf == "yes") - return true; - else if (input_buf == "no") - return false; - else - message (nullptr, "Please answer yes or no."); - } - } - - std::string input_system::interactive_input (const std::string& s, bool& eof) - { - Vlast_prompt_time.stamp (); - - if (Vdrawnow_requested && m_interpreter.interactive ()) - { - bool eval_error = false; + eval_string_reader (interpreter& interp, const std::string& str) + : base_reader (interp), m_eval_string (str) + { } - try - { - Fdrawnow (m_interpreter); - } - catch (const execution_exception& ee) - { - eval_error = true; + std::string get_input (const std::string& prompt, bool& eof); - m_interpreter.handle_exception (ee); - } - - flush_stdout (); + std::string input_source (void) const { return s_in_src; } - // We set Vdrawnow_requested to false even if there is an error in - // drawnow so that the error doesn't reappear at every prompt. - - Vdrawnow_requested = false; + bool input_from_eval_string (void) const { return true; } - if (eval_error) - return "\n"; - } - - return gnu_readline (s, eof); - } - - // If the user simply hits return, this will produce an empty matrix. +private: - octave_value_list - input_system::get_user_input (const octave_value_list& args, int nargout) - { - octave_value_list retval; - - std::string prompt = args(0).xstring_value ("input: unrecognized argument"); + std::string m_eval_string; - bool read_as_string = false; - if (args.length () == 2) // `input (..., "s")`? - { - std::string literal - = args(1).xstring_value ("input: second argument must be 's'."); - if (literal.length () != 1 || literal[0] != 's') - error ("input: second argument must be 's'."); + static const std::string s_in_src; +}; - read_as_string = true; - } - - output_system& output_sys = m_interpreter.get_output_system (); - - output_sys.reset (); - - octave_diary << prompt; - - bool eof = false; +input_reader::input_reader (interpreter& interp) + : m_rep (new terminal_reader (interp)) +{ } - std::string input_buf = interactive_input (prompt.c_str (), eof); - - if (input_buf.empty ()) - error ("input: reading user-input failed!"); - - std::size_t len = input_buf.length (); - - octave_diary << input_buf; - - if (input_buf[len - 1] != '\n') - octave_diary << "\n"; +input_reader::input_reader (interpreter& interp, FILE *file) + : m_rep (new file_reader (interp, file)) +{ } - if (read_as_string) - { - // FIXME: fix gnu_readline and octave_gets instead! - if (input_buf.length () == 1 && input_buf[0] == '\n') - retval(0) = ""; - else - retval(0) = input_buf; - } - else - { - int parse_status = 0; +input_reader::input_reader (interpreter& interp, FILE *file, + const std::string& enc) + : m_rep (new file_reader (interp, file, enc)) +{ } - retval - = m_interpreter.eval_string (input_buf, true, parse_status, nargout); - - tree_evaluator& tw = m_interpreter.get_evaluator (); - - if (! tw.in_debug_repl () && retval.empty ()) - retval(0) = Matrix (); - } - - return retval; - } +input_reader::input_reader (interpreter& interp, const std::string& str) + : m_rep (new eval_string_reader (interp, str)) +{ } - bool input_system::have_input_event_hooks (void) const - { - return ! m_input_event_hook_functions.empty (); - } +const std::string base_reader::s_in_src ("invalid"); - void input_system::add_input_event_hook (const hook_function& hook_fcn) - { - m_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn); - } - - bool input_system::remove_input_event_hook (const std::string& hook_fcn_id) - { - hook_function_list::iterator p - = m_input_event_hook_functions.find (hook_fcn_id); - - if (p == m_input_event_hook_functions.end ()) - return false; +const std::string terminal_reader::s_in_src ("terminal"); - m_input_event_hook_functions.erase (p); - return true; - } - - void input_system::clear_input_event_hooks (void) - { - m_input_event_hook_functions.clear (); - } - - void input_system::run_input_event_hooks (void) - { - m_input_event_hook_functions.run (); - } - - std::string - input_system::gnu_readline (const std::string& s, bool& eof) const - { - octave_quit (); - - eof = false; - - std::string retval = command_editor::readline (s, eof); +// If octave_gets returns multiple lines, we cache the input and +// return it one line at a time. Multiple input lines may happen when +// using readline and bracketed paste mode is enabled, for example. +// Instead of queueing lines here, it might be better to modify the +// grammar in the parser to handle multiple lines when working +// interactively. See also bug #59938. - if (! eof && retval.empty ()) - retval = "\n"; - - return retval; - } - - std::string base_reader::octave_gets (const std::string& prompt, bool& eof) - { - octave_quit (); - - eof = false; - - std::string retval; - - // Process pre input event hook function prior to flushing output and - // printing the prompt. - - tree_evaluator& tw = m_interpreter.get_evaluator (); +std::string +terminal_reader::get_input (const std::string& prompt, bool& eof) +{ + octave_quit (); - event_manager& evmgr = m_interpreter.get_event_manager (); - - if (m_interpreter.interactive ()) - { - if (! tw.in_debug_repl ()) - evmgr.exit_debugger_event (); - - evmgr.pre_input_event (); + eof = false; - evmgr.set_workspace (); - } - - bool history_skip_auto_repeated_debugging_command = false; + if (m_input_queue.empty ()) + { + std::string input = octave_gets (prompt, m_eof); - input_system& input_sys = m_interpreter.get_input_system (); - - pipe_handler_error_count = 0; - - output_system& output_sys = m_interpreter.get_output_system (); - - output_sys.reset (); + std::size_t len = input.size (); - octave_diary << prompt; - - retval = input_sys.interactive_input (prompt, eof); - - // There is no need to update the load_path cache if there is no - // user input. - if (retval != "\n" - && retval.find_first_not_of (" \t\n\r") != std::string::npos) - { - load_path& lp = m_interpreter.get_load_path (); - - lp.update (); + if (len == 0) + { + if (m_eof) + { + eof = m_eof; + return input; + } + else + { + // Can this happen, or will the string returned from + // octave_gets always end in a newline character? - if (tw.in_debug_repl ()) - input_sys.last_debugging_command (retval); - else - input_sys.last_debugging_command ("\n"); - } - else if (tw.in_debug_repl () && input_sys.auto_repeat_debug_command ()) - { - retval = input_sys.last_debugging_command (); - history_skip_auto_repeated_debugging_command = true; - } - - if (retval != "\n") - { - if (! history_skip_auto_repeated_debugging_command) - { - if (command_history::add (retval)) - evmgr.append_history (retval); - } - - octave_diary << retval; - - if (! retval.empty () && retval.back () != '\n') - octave_diary << "\n"; - } - else - octave_diary << "\n"; + input = "\n"; + len = 1; + } + } - // Process post input event hook function after the internal history - // list has been updated. - - if (m_interpreter.interactive ()) - evmgr.post_input_event (); - - return retval; - } - - class - terminal_reader : public base_reader - { - public: - - terminal_reader (interpreter& interp) - : base_reader (interp), m_eof (false), m_input_queue () - { } - - std::string get_input (const std::string& prompt, bool& eof); + std::size_t beg = 0; + while (beg < len) + { + std::size_t end = input.find ('\n', beg); - std::string input_source (void) const { return s_in_src; } - - bool input_from_terminal (void) const { return true; } - - private: - - bool m_eof; - std::queue m_input_queue; - - static const std::string s_in_src; - }; - - class - file_reader : public base_reader - { - public: - - file_reader (interpreter& interp, FILE *f_arg) - : base_reader (interp), m_file (f_arg) - { - input_system& input_sys = interp.get_input_system (); - m_encoding = input_sys.mfile_encoding (); + if (end == std::string::npos) + { + m_input_queue.push (input.substr (beg)); + break; + } + else + { + m_input_queue.push (input.substr (beg, end-beg+1)); + beg = end + 1; + } + } } - file_reader (interpreter& interp, FILE *f_arg, const std::string& enc) - : base_reader (interp), m_file (f_arg), m_encoding (enc) { } - - std::string get_input (const std::string& prompt, bool& eof); - - std::string input_source (void) const { return s_in_src; } - - bool input_from_file (void) const { return true; } - - private: + std::string retval = m_input_queue.front (); + m_input_queue.pop (); - FILE *m_file; - - std::string m_encoding; + if (m_input_queue.empty ()) + eof = m_eof; - static const std::string s_in_src; - }; + return retval; +} - class - eval_string_reader : public base_reader - { - public: +const std::string file_reader::s_in_src ("file"); - eval_string_reader (interpreter& interp, const std::string& str) - : base_reader (interp), m_eval_string (str) - { } - - std::string get_input (const std::string& prompt, bool& eof); - - std::string input_source (void) const { return s_in_src; } - - bool input_from_eval_string (void) const { return true; } - - private: +std::string +file_reader::get_input (const std::string& /*prompt*/, bool& eof) +{ + octave_quit (); - std::string m_eval_string; - - static const std::string s_in_src; - }; + eof = false; - input_reader::input_reader (interpreter& interp) - : m_rep (new terminal_reader (interp)) - { } + std::string src_str = fgets (m_file, eof); - input_reader::input_reader (interpreter& interp, FILE *file) - : m_rep (new file_reader (interp, file)) - { } + std::string mfile_encoding; - input_reader::input_reader (interpreter& interp, FILE *file, - const std::string& enc) - : m_rep (new file_reader (interp, file, enc)) - { } - - input_reader::input_reader (interpreter& interp, const std::string& str) - : m_rep (new eval_string_reader (interp, str)) - { } - - const std::string base_reader::s_in_src ("invalid"); - - const std::string terminal_reader::s_in_src ("terminal"); - - // If octave_gets returns multiple lines, we cache the input and - // return it one line at a time. Multiple input lines may happen when - // using readline and bracketed paste mode is enabled, for example. - // Instead of queueing lines here, it might be better to modify the - // grammar in the parser to handle multiple lines when working - // interactively. See also bug #59938. - - std::string - terminal_reader::get_input (const std::string& prompt, bool& eof) - { - octave_quit (); - - eof = false; + if (m_encoding.empty ()) + { + input_system& input_sys = m_interpreter.get_input_system (); + mfile_encoding = input_sys.mfile_encoding (); + } + else + mfile_encoding = m_encoding; - if (m_input_queue.empty ()) - { - std::string input = octave_gets (prompt, m_eof); - - std::size_t len = input.size (); + std::string encoding; + if (mfile_encoding.compare ("system") == 0) + { + encoding = octave_locale_charset_wrapper (); + // encoding identifiers should consist of ASCII only characters + std::transform (encoding.begin (), encoding.end (), encoding.begin (), + ::tolower); + } + else + encoding = mfile_encoding; - if (len == 0) - { - if (m_eof) - { - eof = m_eof; - return input; - } - else - { - // Can this happen, or will the string returned from - // octave_gets always end in a newline character? - - input = "\n"; - len = 1; - } - } - - std::size_t beg = 0; - while (beg < len) - { - std::size_t end = input.find ('\n', beg); + if (encoding.compare ("utf-8") == 0) + { + // Check for BOM and strip it + if (src_str.compare (0, 3, "\xef\xbb\xbf") == 0) + src_str.erase (0, 3); - if (end == std::string::npos) - { - m_input_queue.push (input.substr (beg)); - break; - } - else - { - m_input_queue.push (input.substr (beg, end-beg+1)); - beg = end + 1; - } - } - } - - std::string retval = m_input_queue.front (); - m_input_queue.pop (); - - if (m_input_queue.empty ()) - eof = m_eof; - - return retval; - } - - const std::string file_reader::s_in_src ("file"); + // replace invalid portions of the string + // FIXME: Include file name that corresponds to m_file. + if (string::u8_validate ("get_input", src_str) > 0) + warning_with_id ("octave:get_input:invalid_utf8", + "Invalid UTF-8 byte sequences have been replaced."); + } + else + { + // convert encoding to UTF-8 before returning string + const char *src = src_str.c_str (); + std::size_t srclen = src_str.length (); - std::string - file_reader::get_input (const std::string& /*prompt*/, bool& eof) - { - octave_quit (); + std::size_t length; + uint8_t *utf8_str; - eof = false; - - std::string src_str = fgets (m_file, eof); - - std::string mfile_encoding; + utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src, srclen, + &length); - if (m_encoding.empty ()) - { - input_system& input_sys = m_interpreter.get_input_system (); - mfile_encoding = input_sys.mfile_encoding (); - } - else - mfile_encoding = m_encoding; + if (! utf8_str) + error ("file_reader::get_input: " + "converting from codepage '%s' to UTF-8: %s", + encoding.c_str (), std::strerror (errno)); - std::string encoding; - if (mfile_encoding.compare ("system") == 0) - { - encoding = octave_locale_charset_wrapper (); - // encoding identifiers should consist of ASCII only characters - std::transform (encoding.begin (), encoding.end (), encoding.begin (), - ::tolower); - } - else - encoding = mfile_encoding; + unwind_action free_utf8_str ([=] () { ::free (utf8_str); }); - if (encoding.compare ("utf-8") == 0) - { - // Check for BOM and strip it - if (src_str.compare (0, 3, "\xef\xbb\xbf") == 0) - src_str.erase (0, 3); + src_str = std::string (reinterpret_cast (utf8_str), length); + } + + return src_str; +} - // replace invalid portions of the string - // FIXME: Include file name that corresponds to m_file. - if (string::u8_validate ("get_input", src_str) > 0) - warning_with_id ("octave:get_input:invalid_utf8", - "Invalid UTF-8 byte sequences have been replaced."); - } - else - { - // convert encoding to UTF-8 before returning string - const char *src = src_str.c_str (); - std::size_t srclen = src_str.length (); +const std::string eval_string_reader::s_in_src ("eval_string"); - std::size_t length; - uint8_t *utf8_str; - - utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src, srclen, - &length); - - if (! utf8_str) - error ("file_reader::get_input: " - "converting from codepage '%s' to UTF-8: %s", - encoding.c_str (), std::strerror (errno)); +std::string +eval_string_reader::get_input (const std::string& /*prompt*/, bool& eof) +{ + octave_quit (); - unwind_action free_utf8_str ([=] () { ::free (utf8_str); }); - - src_str = std::string (reinterpret_cast (utf8_str), length); - } + eof = false; - return src_str; - } - - const std::string eval_string_reader::s_in_src ("eval_string"); + std::string retval; - std::string - eval_string_reader::get_input (const std::string& /*prompt*/, bool& eof) - { - octave_quit (); + retval = m_eval_string; - eof = false; - - std::string retval; - - retval = m_eval_string; + // Clear the eval string so that the next call will return + // an empty character string with EOF = true. + m_eval_string = ""; - // Clear the eval string so that the next call will return - // an empty character string with EOF = true. - m_eval_string = ""; + if (retval.empty ()) + eof = true; - if (retval.empty ()) - eof = true; - - return retval; - } + return retval; +} DEFMETHOD (input, interp, args, nargout, doc: /* -*- texinfo -*- @@ -1444,7 +1444,8 @@ if (nargin < 1 || nargin > 2) print_usage (); - std::string hook_fcn_id = args(0).xstring_value ("remove_input_event_hook: argument not valid as a hook function name or id"); + std::string hook_fcn_id = args( + 0).xstring_value ("remove_input_event_hook: argument not valid as a hook function name or id"); bool warn = (nargin < 2); @@ -1545,7 +1546,7 @@ return input_sys.completion_append_char (args, nargout); } -DEFMETHOD (__request_drawnow__, , args, , +DEFMETHOD (__request_drawnow__,, args, , doc: /* -*- texinfo -*- @deftypefn {} {} __request_drawnow__ () @deftypefnx {} {} __request_drawnow__ (@var{flag}) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/input.h --- a/libinterp/corefcn/input.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/input.h Thu Dec 01 20:05:44 2022 -0800 @@ -54,255 +54,255 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; - class input_system - { - public: +class input_system +{ +public: - input_system (interpreter& interp); + input_system (interpreter& interp); - void initialize (bool line_editing); + void initialize (bool line_editing); - octave_value PS1 (const octave_value_list& args, int nargout); + octave_value PS1 (const octave_value_list& args, int nargout); - std::string PS1 (void) const { return m_PS1; } + std::string PS1 (void) const { return m_PS1; } - std::string PS1 (const std::string& s) - { - std::string val = m_PS1; - m_PS1 = s; - return val; - } + std::string PS1 (const std::string& s) + { + std::string val = m_PS1; + m_PS1 = s; + return val; + } - void set_PS1 (const std::string& s) { m_PS1 = s; } + void set_PS1 (const std::string& s) { m_PS1 = s; } - octave_value PS2 (const octave_value_list& args, int nargout); + octave_value PS2 (const octave_value_list& args, int nargout); - std::string PS2 (void) const { return m_PS2; } + std::string PS2 (void) const { return m_PS2; } - std::string PS2 (const std::string& s) - { - std::string val = m_PS2; - m_PS2 = s; - return val; - } + std::string PS2 (const std::string& s) + { + std::string val = m_PS2; + m_PS2 = s; + return val; + } - void set_PS2 (const std::string& s) { m_PS2 = s; } + void set_PS2 (const std::string& s) { m_PS2 = s; } - std::string last_debugging_command (void) const - { - return m_last_debugging_command; - } + std::string last_debugging_command (void) const + { + return m_last_debugging_command; + } - std::string last_debugging_command (const std::string& s) - { - std::string val = m_last_debugging_command; - m_last_debugging_command = s; - return val; - } + std::string last_debugging_command (const std::string& s) + { + std::string val = m_last_debugging_command; + m_last_debugging_command = s; + return val; + } - octave_value - completion_append_char (const octave_value_list& args, int nargout); + octave_value + completion_append_char (const octave_value_list& args, int nargout); - char completion_append_char (void) const - { - return m_completion_append_char; - } + char completion_append_char (void) const + { + return m_completion_append_char; + } - char completion_append_char (char c) - { - char val = m_completion_append_char; - m_completion_append_char = c; - return val; - } + char completion_append_char (char c) + { + char val = m_completion_append_char; + m_completion_append_char = c; + return val; + } - void set_completion_append_char (char c) { m_completion_append_char = c; } + void set_completion_append_char (char c) { m_completion_append_char = c; } - octave_value gud_mode (const octave_value_list& args, int nargout); + octave_value gud_mode (const octave_value_list& args, int nargout); - bool gud_mode (void) const { return m_gud_mode; } + bool gud_mode (void) const { return m_gud_mode; } - bool gud_mode (bool flag) - { - bool val = m_gud_mode; - m_gud_mode = flag; - return val; - } + bool gud_mode (bool flag) + { + bool val = m_gud_mode; + m_gud_mode = flag; + return val; + } - void set_gud_mode (bool flag) { m_gud_mode = flag; } + void set_gud_mode (bool flag) { m_gud_mode = flag; } - octave_value mfile_encoding (const octave_value_list& args, int nargout); + octave_value mfile_encoding (const octave_value_list& args, int nargout); - std::string mfile_encoding (void) const { return m_mfile_encoding; } + std::string mfile_encoding (void) const { return m_mfile_encoding; } - std::string mfile_encoding (const std::string& s) - { - std::string val = m_mfile_encoding; - m_mfile_encoding = s; - return val; - } + std::string mfile_encoding (const std::string& s) + { + std::string val = m_mfile_encoding; + m_mfile_encoding = s; + return val; + } - void set_mfile_encoding (const std::string& s) { m_mfile_encoding = s; } + void set_mfile_encoding (const std::string& s) { m_mfile_encoding = s; } - std::string dir_encoding (const std::string& dir); + std::string dir_encoding (const std::string& dir); - void set_dir_encoding (const std::string& dir, std::string& enc); + void set_dir_encoding (const std::string& dir, std::string& enc); - octave_value - auto_repeat_debug_command (const octave_value_list& args, int nargout); + octave_value + auto_repeat_debug_command (const octave_value_list& args, int nargout); - bool auto_repeat_debug_command (void) const - { - return m_auto_repeat_debug_command; - } + bool auto_repeat_debug_command (void) const + { + return m_auto_repeat_debug_command; + } - bool auto_repeat_debug_command (bool val) - { - bool old_val = m_auto_repeat_debug_command; - m_auto_repeat_debug_command = val; - return old_val; - } + bool auto_repeat_debug_command (bool val) + { + bool old_val = m_auto_repeat_debug_command; + m_auto_repeat_debug_command = val; + return old_val; + } - bool yes_or_no (const std::string& prompt); + bool yes_or_no (const std::string& prompt); - std::string interactive_input (const std::string& s, bool& eof); + std::string interactive_input (const std::string& s, bool& eof); - octave_value_list - get_user_input (const octave_value_list& args, int nargout); + octave_value_list + get_user_input (const octave_value_list& args, int nargout); - bool have_input_event_hooks (void) const; + bool have_input_event_hooks (void) const; - void add_input_event_hook (const hook_function& hook_fcn); + void add_input_event_hook (const hook_function& hook_fcn); - bool remove_input_event_hook (const std::string& hook_fcn_id); + bool remove_input_event_hook (const std::string& hook_fcn_id); - void clear_input_event_hooks (void); + void clear_input_event_hooks (void); - void run_input_event_hooks (void); + void run_input_event_hooks (void); - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - // Primary prompt string. - std::string m_PS1; + // Primary prompt string. + std::string m_PS1; - // Secondary prompt string. - std::string m_PS2; + // Secondary prompt string. + std::string m_PS2; - // Character to append after successful command-line completion - // attempts. - char m_completion_append_char; + // Character to append after successful command-line completion + // attempts. + char m_completion_append_char; - // TRUE if we are running in the Emacs GUD mode. - bool m_gud_mode; + // TRUE if we are running in the Emacs GUD mode. + bool m_gud_mode; - // Codepage which is used to read .m files - std::string m_mfile_encoding; + // Codepage which is used to read .m files + std::string m_mfile_encoding; - // map of directories -> used mfile encoding - std::unordered_map m_dir_encoding; + // map of directories -> used mfile encoding + std::unordered_map m_dir_encoding; - // TRUE means repeat last debug command if the user just types RET. - bool m_auto_repeat_debug_command; + // TRUE means repeat last debug command if the user just types RET. + bool m_auto_repeat_debug_command; - // If we are in debugging mode, this is the last command entered, - // so that we can repeat the previous command if the user just - // types RET. - std::string m_last_debugging_command; + // If we are in debugging mode, this is the last command entered, + // so that we can repeat the previous command if the user just + // types RET. + std::string m_last_debugging_command; - hook_function_list m_input_event_hook_functions; + hook_function_list m_input_event_hook_functions; - bool m_initialized; + bool m_initialized; - std::string gnu_readline (const std::string& s, bool& eof) const; - }; + std::string gnu_readline (const std::string& s, bool& eof) const; +}; - class base_reader - { - public: +class base_reader +{ +public: - friend class input_reader; + friend class input_reader; - base_reader (interpreter& interp) - : m_interpreter (interp) - { } + base_reader (interpreter& interp) + : m_interpreter (interp) + { } - base_reader (const base_reader& x) - : m_interpreter (x.m_interpreter) - { } + base_reader (const base_reader& x) + : m_interpreter (x.m_interpreter) + { } - virtual ~base_reader (void) = default; + virtual ~base_reader (void) = default; - virtual std::string get_input (const std::string& prompt, bool& eof) = 0; + virtual std::string get_input (const std::string& prompt, bool& eof) = 0; - virtual std::string input_source (void) const { return s_in_src; } + virtual std::string input_source (void) const { return s_in_src; } - std::string octave_gets (const std::string& prompt, bool& eof); + std::string octave_gets (const std::string& prompt, bool& eof); - virtual bool input_from_terminal (void) const { return false; } + virtual bool input_from_terminal (void) const { return false; } - virtual bool input_from_file (void) const { return false; } + virtual bool input_from_file (void) const { return false; } - virtual bool input_from_eval_string (void) const { return false; } + virtual bool input_from_eval_string (void) const { return false; } - protected: +protected: - interpreter& m_interpreter; + interpreter& m_interpreter; - private: +private: - static const std::string s_in_src; - }; + static const std::string s_in_src; +}; - class input_reader - { - public: +class input_reader +{ +public: - input_reader (interpreter& interp); + input_reader (interpreter& interp); - input_reader (interpreter& interp, FILE *file); + input_reader (interpreter& interp, FILE *file); - input_reader (interpreter& interp, FILE *file, const std::string& enc); + input_reader (interpreter& interp, FILE *file, const std::string& enc); - input_reader (interpreter& interp, const std::string& str); + input_reader (interpreter& interp, const std::string& str); - input_reader (const input_reader& ir) = default; + input_reader (const input_reader& ir) = default; - input_reader& operator = (const input_reader& ir) = default; + input_reader& operator = (const input_reader& ir) = default; - ~input_reader (void) = default; + ~input_reader (void) = default; - std::string get_input (const std::string& prompt, bool& eof) - { - return m_rep->get_input (prompt, eof); - } + std::string get_input (const std::string& prompt, bool& eof) + { + return m_rep->get_input (prompt, eof); + } - std::string input_source (void) const - { - return m_rep->input_source (); - } + std::string input_source (void) const + { + return m_rep->input_source (); + } - bool input_from_terminal (void) const - { - return m_rep->input_from_terminal (); - } + bool input_from_terminal (void) const + { + return m_rep->input_from_terminal (); + } - bool input_from_file (void) const - { - return m_rep->input_from_file (); - } + bool input_from_file (void) const + { + return m_rep->input_from_file (); + } - bool input_from_eval_string (void) const - { - return m_rep->input_from_eval_string (); - } + bool input_from_eval_string (void) const + { + return m_rep->input_from_eval_string (); + } - private: +private: - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/interpreter-private.cc --- a/libinterp/corefcn/interpreter-private.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/interpreter-private.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,203 +51,203 @@ OCTAVE_BEGIN_NAMESPACE(octave) - interpreter& __get_interpreter__ (void) - { - interpreter *interp = interpreter::the_interpreter (); +interpreter& __get_interpreter__ (void) +{ + interpreter *interp = interpreter::the_interpreter (); - if (! interp) - { - std::cerr << "fatal error: octave interpreter context missing" << std::endl; - abort (); - } + if (! interp) + { + std::cerr << "fatal error: octave interpreter context missing" << std::endl; + abort (); + } - return *interp; - } + return *interp; +} - dynamic_loader& __get_dynamic_loader__ (void) - { - interpreter& interp = __get_interpreter__ (); +dynamic_loader& __get_dynamic_loader__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_dynamic_loader (); - } + return interp.get_dynamic_loader (); +} - error_system& __get_error_system__ (void) - { - interpreter& interp = __get_interpreter__ (); +error_system& __get_error_system__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_error_system (); - } + return interp.get_error_system (); +} - gh_manager& __get_gh_manager__ (void) - { - interpreter& interp = __get_interpreter__ (); +gh_manager& __get_gh_manager__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_gh_manager (); - } + return interp.get_gh_manager (); +} - help_system& __get_help_system__ (void) - { - interpreter& interp = __get_interpreter__ (); +help_system& __get_help_system__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_help_system (); - } + return interp.get_help_system (); +} - input_system& __get_input_system__ (void) - { - interpreter& interp = __get_interpreter__ (); +input_system& __get_input_system__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_input_system (); - } + return interp.get_input_system (); +} - output_system& __get_output_system__ (void) - { - interpreter& interp = __get_interpreter__ (); +output_system& __get_output_system__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_output_system (); - } + return interp.get_output_system (); +} - load_path& __get_load_path__ (void) - { - interpreter& interp = __get_interpreter__ (); +load_path& __get_load_path__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_load_path (); - } + return interp.get_load_path (); +} - load_save_system& __get_load_save_system__ (void) - { - interpreter& interp = __get_interpreter__ (); +load_save_system& __get_load_save_system__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_load_save_system (); - } + return interp.get_load_save_system (); +} - event_manager& __get_event_manager__ (void) - { - interpreter& interp = __get_interpreter__ (); +event_manager& __get_event_manager__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_event_manager (); - } + return interp.get_event_manager (); +} - type_info& __get_type_info__ (void) - { - interpreter& interp = __get_interpreter__ (); +type_info& __get_type_info__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_type_info (); - } + return interp.get_type_info (); +} - symbol_table& __get_symbol_table__ (void) - { - interpreter& interp = __get_interpreter__ (); +symbol_table& __get_symbol_table__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_symbol_table (); - } + return interp.get_symbol_table (); +} - symbol_scope __get_current_scope__ (void) - { - interpreter& interp = __get_interpreter__ (); +symbol_scope __get_current_scope__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_current_scope (); - } + return interp.get_current_scope (); +} - symbol_scope __require_current_scope__ (void) - { - symbol_scope scope = __get_current_scope__ (); +symbol_scope __require_current_scope__ (void) +{ + symbol_scope scope = __get_current_scope__ (); - if (! scope) - error ("__require_current_scope__: symbol table scope missing"); + if (! scope) + error ("__require_current_scope__: symbol table scope missing"); - return scope; - } + return scope; +} - tree_evaluator& __get_evaluator__ (void) - { - interpreter& interp = __get_interpreter__ (); +tree_evaluator& __get_evaluator__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_evaluator (); - } + return interp.get_evaluator (); +} - bp_table& __get_bp_table__ (void) - { - tree_evaluator& tw = __get_evaluator__ (); +bp_table& __get_bp_table__ (void) +{ + tree_evaluator& tw = __get_evaluator__ (); - return tw.get_bp_table (); - } + return tw.get_bp_table (); +} - child_list& __get_child_list__ (void) - { - interpreter& interp = __get_interpreter__ (); +child_list& __get_child_list__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_child_list (); - } + return interp.get_child_list (); +} - cdef_manager& __get_cdef_manager__ (void) - { - interpreter& interp = __get_interpreter__ (); +cdef_manager& __get_cdef_manager__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_cdef_manager (); - } + return interp.get_cdef_manager (); +} - display_info& __get_display_info__ (void) - { - interpreter& interp = __get_interpreter__ (); +display_info& __get_display_info__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_display_info (); - } + return interp.get_display_info (); +} - gtk_manager& __get_gtk_manager__ (void) - { - interpreter& interp = __get_interpreter__ (); +gtk_manager& __get_gtk_manager__ (void) +{ + interpreter& interp = __get_interpreter__ (); - return interp.get_gtk_manager (); - } + return interp.get_gtk_manager (); +} - octave_value - get_function_handle (interpreter& interp, const octave_value& arg, - const std::string& parameter_name) - { - std::list parameter_names; - parameter_names.push_back (parameter_name); - return get_function_handle (interp, arg, parameter_names); - } +octave_value +get_function_handle (interpreter& interp, const octave_value& arg, + const std::string& parameter_name) +{ + std::list parameter_names; + parameter_names.push_back (parameter_name); + return get_function_handle (interp, arg, parameter_names); +} - // May return a function handle object, inline function object, or - // function object. +// May return a function handle object, inline function object, or +// function object. - octave_value - get_function_handle (interpreter& interp, const octave_value& arg, - const std::list& parameter_names) - { - if (arg.is_function_handle () || arg.is_inline_function ()) - return arg; - else if (arg.is_string ()) - { - std::string fstr = arg.string_value (); +octave_value +get_function_handle (interpreter& interp, const octave_value& arg, + const std::list& parameter_names) +{ + if (arg.is_function_handle () || arg.is_inline_function ()) + return arg; + else if (arg.is_string ()) + { + std::string fstr = arg.string_value (); - if (fstr.empty ()) - return octave_value (); + if (fstr.empty ()) + return octave_value (); - symbol_table& symtab = interp.get_symbol_table (); + symbol_table& symtab = interp.get_symbol_table (); - octave_value fcn = symtab.find_function (fstr); + octave_value fcn = symtab.find_function (fstr); - if (fcn.is_defined ()) - return fcn; + if (fcn.is_defined ()) + return fcn; - // Possibly warn here that passing the function body in a - // character string is discouraged. + // Possibly warn here that passing the function body in a + // character string is discouraged. - octave_value_list args (parameter_names.size () + 1); - octave_idx_type i = 0; - args(i++) = fstr; - for (const auto& pname : parameter_names) - args(i++) = pname; + octave_value_list args (parameter_names.size () + 1); + octave_idx_type i = 0; + args(i++) = fstr; + for (const auto& pname : parameter_names) + args(i++) = pname; - octave_value_list tmp = interp.feval ("inline", args, 1); + octave_value_list tmp = interp.feval ("inline", args, 1); - if (tmp.length () > 0) - return tmp(0); - } + if (tmp.length () > 0) + return tmp(0); + } - return octave_value (); - } + return octave_value (); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/interpreter-private.h --- a/libinterp/corefcn/interpreter-private.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/interpreter-private.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,82 +35,82 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class bp_table; - class cdef_manager; - class child_list; - class display_info; - class dynamic_loader; - class error_system; - class event_manager; - class gh_manager; - class gtk_manager; - class help_system; - class input_system; - class interpreter; - class load_path; - class load_save_system; - class output_system; - class tree_evaluator; - class type_info; +class bp_table; +class cdef_manager; +class child_list; +class display_info; +class dynamic_loader; +class error_system; +class event_manager; +class gh_manager; +class gtk_manager; +class help_system; +class input_system; +class interpreter; +class load_path; +class load_save_system; +class output_system; +class tree_evaluator; +class type_info; - extern OCTINTERP_API interpreter& __get_interpreter__ (void); +extern OCTINTERP_API interpreter& __get_interpreter__ (void); - extern OCTINTERP_API dynamic_loader& __get_dynamic_loader__ (void); +extern OCTINTERP_API dynamic_loader& __get_dynamic_loader__ (void); - extern OCTINTERP_API error_system& __get_error_system__ (void); +extern OCTINTERP_API error_system& __get_error_system__ (void); - extern OCTINTERP_API gh_manager& __get_gh_manager__ (void); +extern OCTINTERP_API gh_manager& __get_gh_manager__ (void); - extern OCTINTERP_API help_system& __get_help_system__ (void); +extern OCTINTERP_API help_system& __get_help_system__ (void); - extern OCTINTERP_API input_system& __get_input_system__ (void); +extern OCTINTERP_API input_system& __get_input_system__ (void); - extern OCTINTERP_API load_path& __get_load_path__ (void); +extern OCTINTERP_API load_path& __get_load_path__ (void); - extern OCTINTERP_API load_save_system& __get_load_save_system__ (void); +extern OCTINTERP_API load_save_system& __get_load_save_system__ (void); - extern OCTINTERP_API event_manager& __get_event_manager__ (void); +extern OCTINTERP_API event_manager& __get_event_manager__ (void); - extern OCTINTERP_API output_system& __get_output_system__ (void); +extern OCTINTERP_API output_system& __get_output_system__ (void); - extern OCTINTERP_API type_info& __get_type_info__ (void); +extern OCTINTERP_API type_info& __get_type_info__ (void); - extern OCTINTERP_API symbol_table& __get_symbol_table__ (void); +extern OCTINTERP_API symbol_table& __get_symbol_table__ (void); - extern OCTINTERP_API symbol_scope __get_current_scope__ (void); +extern OCTINTERP_API symbol_scope __get_current_scope__ (void); - extern OCTINTERP_API symbol_scope __require_current_scope__ (void); +extern OCTINTERP_API symbol_scope __require_current_scope__ (void); - extern OCTINTERP_API tree_evaluator& __get_evaluator__ (void); +extern OCTINTERP_API tree_evaluator& __get_evaluator__ (void); - extern OCTINTERP_API bp_table& __get_bp_table__ (void); +extern OCTINTERP_API bp_table& __get_bp_table__ (void); - extern OCTINTERP_API child_list& __get_child_list__ (void); +extern OCTINTERP_API child_list& __get_child_list__ (void); - extern OCTINTERP_API cdef_manager& __get_cdef_manager__ (void); +extern OCTINTERP_API cdef_manager& __get_cdef_manager__ (void); - extern OCTINTERP_API display_info& __get_display_info__ (void); +extern OCTINTERP_API display_info& __get_display_info__ (void); - extern OCTINTERP_API gtk_manager& __get_gtk_manager__ (void); +extern OCTINTERP_API gtk_manager& __get_gtk_manager__ (void); - // Functions that could be methods in the interpreter class but maybe - // shouldn't be exposed as part of the public interface. +// Functions that could be methods in the interpreter class but maybe +// shouldn't be exposed as part of the public interface. - // Convert octave_value object ARG to be a function handle object. It - // may be a function handle, inline function, the name of a function, - // or the text of an inline function that has the given argument names - // PARAMETER_NAMES. Use of the latter form is discouraged. +// Convert octave_value object ARG to be a function handle object. It +// may be a function handle, inline function, the name of a function, +// or the text of an inline function that has the given argument names +// PARAMETER_NAMES. Use of the latter form is discouraged. - OCTINTERP_API - octave_value - get_function_handle (interpreter& interp, const octave_value& arg, - const std::string& parameter_name); +OCTINTERP_API +octave_value +get_function_handle (interpreter& interp, const octave_value& arg, + const std::string& parameter_name); - OCTINTERP_API - octave_value - get_function_handle (interpreter& interp, const octave_value& arg, - const std::list& parameter_names - = std::list ()); +OCTINTERP_API +octave_value +get_function_handle (interpreter& interp, const octave_value& arg, + const std::list& parameter_names + = std::list ()); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/interpreter.cc --- a/libinterp/corefcn/interpreter.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/interpreter.cc Thu Dec 01 20:05:44 2022 -0800 @@ -287,8 +287,8 @@ std::string arg = args(0).xstring_value ("atexit: FCN argument must be a string"); bool add_mode = (nargin == 2) - ? args(1).xbool_value ("atexit: FLAG argument must be a logical value") - : true; + ? args(1).xbool_value ("atexit: FLAG argument must be a logical value") + : true; octave_value_list retval; @@ -314,622 +314,622 @@ return ovl (interp.traditional ()); } - temporary_file_list::~temporary_file_list (void) - { - cleanup (); - } +temporary_file_list::~temporary_file_list (void) +{ + cleanup (); +} - void temporary_file_list::insert (const std::string& file) - { - m_files.insert (file); - } +void temporary_file_list::insert (const std::string& file) +{ + m_files.insert (file); +} - void temporary_file_list::cleanup (void) - { - while (! m_files.empty ()) - { - auto it = m_files.begin (); +void temporary_file_list::cleanup (void) +{ + while (! m_files.empty ()) + { + auto it = m_files.begin (); - octave_unlink_wrapper (it->c_str ()); + octave_unlink_wrapper (it->c_str ()); - m_files.erase (it); - } - } + m_files.erase (it); + } +} - // The time we last time we changed directories. - sys::time Vlast_chdir_time = 0.0; +// The time we last time we changed directories. +sys::time Vlast_chdir_time = 0.0; - // Execute commands from a file and catch potential exceptions in a consistent - // way. This function should be called anywhere we might parse and execute - // commands from a file before we have entered the main loop in - // toplev.cc. +// Execute commands from a file and catch potential exceptions in a consistent +// way. This function should be called anywhere we might parse and execute +// commands from a file before we have entered the main loop in +// toplev.cc. - static int safe_source_file (const std::string& file_name, - const std::string& context = "", - bool verbose = false, - bool require_file = true) - { - interpreter& interp = __get_interpreter__ (); +static int safe_source_file (const std::string& file_name, + const std::string& context = "", + bool verbose = false, + bool require_file = true) +{ + interpreter& interp = __get_interpreter__ (); - try - { - source_file (file_name, context, verbose, require_file); - } - catch (const interrupt_exception&) - { - interp.recover_from_exception (); + try + { + source_file (file_name, context, verbose, require_file); + } + catch (const interrupt_exception&) + { + interp.recover_from_exception (); - return 1; - } - catch (const execution_exception& ee) - { - interp.handle_exception (ee); + return 1; + } + catch (const execution_exception& ee) + { + interp.handle_exception (ee); - return 1; - } + return 1; + } - return 0; - } + return 0; +} - static void initialize_version_info (void) - { - octave_value_list args; +static void initialize_version_info (void) +{ + octave_value_list args; - args(3) = OCTAVE_RELEASE_DATE; - args(2) = config::release (); - args(1) = OCTAVE_VERSION; - args(0) = "GNU Octave"; + args(3) = OCTAVE_RELEASE_DATE; + args(2) = config::release (); + args(1) = OCTAVE_VERSION; + args(0) = "GNU Octave"; - F__version_info__ (args, 0); - } + F__version_info__ (args, 0); +} - static void xerbla_abort (void) - { - error ("Fortran procedure terminated by call to XERBLA"); - } +static void xerbla_abort (void) +{ + error ("Fortran procedure terminated by call to XERBLA"); +} - static void initialize_xerbla_error_handler (void) - { - // The idea here is to force xerbla to be referenced so that we will - // link to our own version instead of the one provided by the BLAS - // library. But numeric_limits::NaN () should never be -1, so - // we should never actually call xerbla. FIXME (again!): If this - // becomes a constant expression the test might be optimized away and - // then the reference to the function might also disappear. +static void initialize_xerbla_error_handler (void) +{ + // The idea here is to force xerbla to be referenced so that we will + // link to our own version instead of the one provided by the BLAS + // library. But numeric_limits::NaN () should never be -1, so + // we should never actually call xerbla. FIXME (again!): If this + // becomes a constant expression the test might be optimized away and + // then the reference to the function might also disappear. - if (numeric_limits::NaN () == -1) - F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6)); + if (numeric_limits::NaN () == -1) + F77_FUNC (xerbla, XERBLA) ("octave", 13 F77_CHAR_ARG_LEN (6)); - typedef void (*xerbla_handler_ptr) (void); + typedef void (*xerbla_handler_ptr) (void); - typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr); + typedef void (*octave_set_xerbla_handler_ptr) (xerbla_handler_ptr); - dynamic_library libs (""); + dynamic_library libs (""); - if (libs) - { - octave_set_xerbla_handler_ptr octave_set_xerbla_handler - = reinterpret_cast - (libs.search ("octave_set_xerbla_handler")); + if (libs) + { + octave_set_xerbla_handler_ptr octave_set_xerbla_handler + = reinterpret_cast + (libs.search ("octave_set_xerbla_handler")); - if (octave_set_xerbla_handler) - octave_set_xerbla_handler (xerbla_abort); - } - } + if (octave_set_xerbla_handler) + octave_set_xerbla_handler (xerbla_abort); + } +} - OCTAVE_NORETURN static void - lo_error_handler (const char *fmt, ...) - { - va_list args; - va_start (args, fmt); - verror_with_cfn (fmt, args); - va_end (args); +OCTAVE_NORETURN static void +lo_error_handler (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + verror_with_cfn (fmt, args); + va_end (args); - throw execution_exception (); - } + throw execution_exception (); +} - OCTAVE_NORETURN static void - lo_error_with_id_handler (const char *id, const char *fmt, ...) - { - va_list args; - va_start (args, fmt); - verror_with_id_cfn (id, fmt, args); - va_end (args); +OCTAVE_NORETURN static void +lo_error_with_id_handler (const char *id, const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + verror_with_id_cfn (id, fmt, args); + va_end (args); - throw execution_exception (); - } + throw execution_exception (); +} - static void initialize_error_handlers (void) - { - set_liboctave_error_handler (lo_error_handler); - set_liboctave_error_with_id_handler (lo_error_with_id_handler); - set_liboctave_warning_handler (warning); - set_liboctave_warning_with_id_handler (warning_with_id); - } +static void initialize_error_handlers (void) +{ + set_liboctave_error_handler (lo_error_handler); + set_liboctave_error_with_id_handler (lo_error_with_id_handler); + set_liboctave_warning_handler (warning); + set_liboctave_warning_with_id_handler (warning_with_id); +} - // Create an interpreter object and perform initialization up to the - // point of setting reading command history and setting the load - // path. +// Create an interpreter object and perform initialization up to the +// point of setting reading command history and setting the load +// path. - interpreter::interpreter (application *app_context) - : m_app_context (app_context), - m_tmp_files (), - m_atexit_fcns (), - m_display_info (), - m_environment (), - m_settings (), - m_error_system (*this), - m_evaluator (*this), - m_help_system (*this), - m_input_system (*this), - m_output_system (*this), - m_history_system (*this), - m_dynamic_loader (*this), - m_load_path (*this), - m_load_save_system (*this), - m_type_info (), - m_symbol_table (*this), - m_stream_list (*this), - m_child_list (), - m_url_handle_manager (), - m_cdef_manager (*this), - m_gtk_manager (), - m_event_manager (*this), - m_gh_manager (nullptr), - m_interactive (false), - 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), - m_interrupt_all_in_process_group (true), - m_cancel_quit (false), - m_executing_finish_script (false), - m_executing_atexit (false), - m_initialized (false) - { - // FIXME: When thread_local storage is used by default, this message - // should change to say something like - // - // only one Octave interpreter may be active in any given thread +interpreter::interpreter (application *app_context) + : m_app_context (app_context), + m_tmp_files (), + m_atexit_fcns (), + m_display_info (), + m_environment (), + m_settings (), + m_error_system (*this), + m_evaluator (*this), + m_help_system (*this), + m_input_system (*this), + m_output_system (*this), + m_history_system (*this), + m_dynamic_loader (*this), + m_load_path (*this), + m_load_save_system (*this), + m_type_info (), + m_symbol_table (*this), + m_stream_list (*this), + m_child_list (), + m_url_handle_manager (), + m_cdef_manager (*this), + m_gtk_manager (), + m_event_manager (*this), + m_gh_manager (nullptr), + m_interactive (false), + 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), + m_interrupt_all_in_process_group (true), + m_cancel_quit (false), + m_executing_finish_script (false), + m_executing_atexit (false), + m_initialized (false) +{ + // FIXME: When thread_local storage is used by default, this message + // should change to say something like + // + // only one Octave interpreter may be active in any given thread - if (m_instance) - throw std::runtime_error - ("only one Octave interpreter may be active"); + if (m_instance) + throw std::runtime_error + ("only one Octave interpreter may be active"); - m_instance = this; + m_instance = this; #if defined (OCTAVE_HAVE_WINDOWS_UTF8_LOCALE) - // Force a UTF-8 locale on Windows if possible - std::setlocale (LC_ALL, ".UTF8"); + // Force a UTF-8 locale on Windows if possible + std::setlocale (LC_ALL, ".UTF8"); #else - std::setlocale (LC_ALL, ""); + std::setlocale (LC_ALL, ""); #endif - // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting - std::setlocale (LC_NUMERIC, "C"); - std::setlocale (LC_TIME, "C"); - sys::env::putenv ("LC_NUMERIC", "C"); - sys::env::putenv ("LC_TIME", "C"); + // Matlab uses "C" locale for LC_NUMERIC class regardless of local setting + std::setlocale (LC_NUMERIC, "C"); + std::setlocale (LC_TIME, "C"); + sys::env::putenv ("LC_NUMERIC", "C"); + sys::env::putenv ("LC_TIME", "C"); + + // Initialize the default floating point unit control state. + octave_set_default_fpucw (); + + thread::init (); - // Initialize the default floating point unit control state. - octave_set_default_fpucw (); + octave_ieee_init (); - thread::init (); + initialize_xerbla_error_handler (); + + initialize_error_handlers (); - octave_ieee_init (); + if (m_app_context) + { + install_signal_handlers (); + octave_unblock_signal_by_name ("SIGTSTP"); + } + else + quit_allowed = false; - initialize_xerbla_error_handler (); + if (! m_app_context) + m_display_info.initialize (); - initialize_error_handlers (); + bool line_editing = false; - if (m_app_context) - { - install_signal_handlers (); - octave_unblock_signal_by_name ("SIGTSTP"); - } - else - quit_allowed = false; + if (m_app_context) + { + // Embedded interpreters don't execute command line options. + const cmdline_options& options = m_app_context->options (); + + // Make all command-line arguments available to startup files, + // including PKG_ADD files. + + string_vector args = options.all_args (); - if (! m_app_context) - m_display_info.initialize (); + m_app_context->intern_argv (args); + intern_nargin (args.numel () - 1); + + bool is_octave_program = m_app_context->is_octave_program (); + + std::list command_line_path = options.command_line_path (); + + for (const auto& pth : command_line_path) + m_load_path.set_command_line_path (pth); - bool line_editing = false; + std::string exec_path = options.exec_path (); + if (! exec_path.empty ()) + m_environment.exec_path (exec_path); + + std::string image_path = options.image_path (); + if (! image_path.empty ()) + m_environment.image_path (image_path); - if (m_app_context) - { - // Embedded interpreters don't execute command line options. - const cmdline_options& options = m_app_context->options (); + if (! options.no_window_system ()) + m_display_info.initialize (); + + // Is input coming from a terminal? If so, we are probably + // interactive. - // Make all command-line arguments available to startup files, - // including PKG_ADD files. + // If stdin is not a tty, then we are reading commands from a + // pipe or a redirected file. + bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin)); - string_vector args = options.all_args (); + m_interactive = (! is_octave_program && stdin_is_tty + && octave_isatty_wrapper (fileno (stdout))); - m_app_context->intern_argv (args); - intern_nargin (args.numel () - 1); - - bool is_octave_program = m_app_context->is_octave_program (); + // Don't force interactive if we're already interactive (bug #60696). + bool forced_interactive = options.forced_interactive (); + if (m_interactive) + { + m_app_context->forced_interactive (false); + forced_interactive = false; + } - std::list command_line_path = options.command_line_path (); + // Check if the user forced an interactive session. + if (forced_interactive) + m_interactive = true; - for (const auto& pth : command_line_path) - m_load_path.set_command_line_path (pth); + line_editing = options.line_editing (); + if ((! m_interactive || forced_interactive) + && ! options.forced_line_editing ()) + line_editing = false; + + m_traditional = options.traditional (); - std::string exec_path = options.exec_path (); - if (! exec_path.empty ()) - m_environment.exec_path (exec_path); + // FIXME: if possible, perform the following actions directly + // instead of using the interpreter-level functions. + + if (options.echo_commands ()) + m_evaluator.echo + (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS + | tree_evaluator::ECHO_ALL); - std::string image_path = options.image_path (); - if (! image_path.empty ()) - m_environment.image_path (image_path); + std::string docstrings_file = options.docstrings_file (); + if (! docstrings_file.empty ()) + Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file)); - if (! options.no_window_system ()) - m_display_info.initialize (); + std::string doc_cache_file = options.doc_cache_file (); + if (! doc_cache_file.empty ()) + Fdoc_cache_file (*this, octave_value (doc_cache_file)); - // Is input coming from a terminal? If so, we are probably - // interactive. + std::string info_file = options.info_file (); + if (! info_file.empty ()) + Finfo_file (*this, octave_value (info_file)); - // If stdin is not a tty, then we are reading commands from a - // pipe or a redirected file. - bool stdin_is_tty = octave_isatty_wrapper (fileno (stdin)); + std::string info_program = options.info_program (); + if (! info_program.empty ()) + Finfo_program (*this, octave_value (info_program)); - m_interactive = (! is_octave_program && stdin_is_tty - && octave_isatty_wrapper (fileno (stdout))); + std::string texi_macros_file = options.texi_macros_file (); + if (! texi_macros_file.empty ()) + Ftexi_macros_file (*this, octave_value (texi_macros_file)); + } - // Don't force interactive if we're already interactive (bug #60696). - bool forced_interactive = options.forced_interactive (); - if (m_interactive) - { - m_app_context->forced_interactive (false); - forced_interactive = false; - } + // FIXME: we defer creation of the gh_manager object because it + // creates a root_figure object that requires the display_info + // object, but that is currently only accessible through the global + // interpreter object and that is not available until after the + // interpreter::instance pointer is set (above). It would be better + // if m_gh_manager could be an object value instead of a pointer and + // created as part of the interpreter initialization. To do that, + // we should either make the display_info object independent of the + // interpreter object (does it really need to cache any + // information?) or defer creation of the root_figure object until + // it is actually needed. + m_gh_manager = new gh_manager (*this); + + m_input_system.initialize (line_editing); - // Check if the user forced an interactive session. - if (forced_interactive) - m_interactive = true; + // These can come after command line args since none of them set any + // defaults that might be changed by command line options. + + initialize_version_info (); + + // This should be done before initializing the load path because + // some PKG_ADD files might need --traditional behavior. - line_editing = options.line_editing (); - if ((! m_interactive || forced_interactive) - && ! options.forced_line_editing ()) - line_editing = false; + if (m_traditional) + maximum_braindamage (); - m_traditional = options.traditional (); + octave_interpreter_ready = true; +} + +OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr; - // FIXME: if possible, perform the following actions directly - // instead of using the interpreter-level functions. +interpreter::~interpreter (void) +{ + if (! m_app_context) + shutdown (); - if (options.echo_commands ()) - m_evaluator.echo - (tree_evaluator::ECHO_SCRIPTS | tree_evaluator::ECHO_FUNCTIONS - | tree_evaluator::ECHO_ALL); + delete m_gh_manager; +} - std::string docstrings_file = options.docstrings_file (); - if (! docstrings_file.empty ()) - Fbuilt_in_docstrings_file (*this, octave_value (docstrings_file)); +void interpreter::intern_nargin (octave_idx_type nargs) +{ + m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs); +} + +// Read the history file unless a command-line option inhibits that. - std::string doc_cache_file = options.doc_cache_file (); - if (! doc_cache_file.empty ()) - Fdoc_cache_file (*this, octave_value (doc_cache_file)); +void interpreter::initialize_history (bool read_history_file) +{ + if (! m_history_initialized) + { + // Allow command-line option to override. + + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - std::string info_file = options.info_file (); - if (! info_file.empty ()) - Finfo_file (*this, octave_value (info_file)); + read_history_file = options.read_history_file (); - std::string info_program = options.info_program (); - if (! info_program.empty ()) - Finfo_program (*this, octave_value (info_program)); + if (! read_history_file) + command_history::ignore_entries (); + } + + m_history_system.initialize (read_history_file); + + if (! m_app_context) + command_history::ignore_entries (); - std::string texi_macros_file = options.texi_macros_file (); - if (! texi_macros_file.empty ()) - Ftexi_macros_file (*this, octave_value (texi_macros_file)); - } + m_history_initialized = true; + } +} + +// Set the initial path to the system default unless command-line +// option says to leave it empty. + +void interpreter::initialize_load_path (bool set_initial_path) +{ + if (! m_load_path_initialized) + { + // Allow command-line option to override. + + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); + + set_initial_path = options.set_initial_path (); + } - // FIXME: we defer creation of the gh_manager object because it - // creates a root_figure object that requires the display_info - // object, but that is currently only accessible through the global - // interpreter object and that is not available until after the - // interpreter::instance pointer is set (above). It would be better - // if m_gh_manager could be an object value instead of a pointer and - // created as part of the interpreter initialization. To do that, - // we should either make the display_info object independent of the - // interpreter object (does it really need to cache any - // information?) or defer creation of the root_figure object until - // it is actually needed. - m_gh_manager = new gh_manager (*this); + // Temporarily set the execute_pkg_add function to one that + // catches exceptions. This is better than wrapping + // load_path::initialize in a try-catch block because it will + // not stop executing PKG_ADD files at the first exception. + // It's also better than changing the default execute_pkg_add + // function to use safe_source file because that will normally + // be evaluated from the normal interpreter loop where exceptions + // are already handled. - m_input_system.initialize (line_editing); + unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path, + m_load_path.get_add_hook ()); + + m_load_path.set_add_hook ([=] (const std::string& dir) + { this->execute_pkg_add (dir); }); - // These can come after command line args since none of them set any - // defaults that might be changed by command line options. + m_load_path.initialize (set_initial_path); - initialize_version_info (); + m_load_path_initialized = true; + } +} + +// This may be called separately from execute - // This should be done before initializing the load path because - // some PKG_ADD files might need --traditional behavior. +void interpreter::initialize (void) +{ + if (m_initialized) + return; - if (m_traditional) - maximum_braindamage (); - - octave_interpreter_ready = true; - } - - OCTAVE_THREAD_LOCAL interpreter *interpreter::m_instance = nullptr; + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - interpreter::~interpreter (void) - { - if (! m_app_context) - shutdown (); + if (options.experimental_terminal_widget ()) + { + if (! options.gui ()) + display_startup_message (); + } + else + display_startup_message (); + } + else + display_startup_message (); + + // Wait to read the history file until the interpreter reads input + // files and begins evaluating commands. - delete m_gh_manager; - } + initialize_history (); + + // Initializing the load path may execute PKG_ADD files, so can't be + // done until the interpreter is ready to execute commands. - void interpreter::intern_nargin (octave_idx_type nargs) - { - m_evaluator.set_auto_fcn_var (stack_frame::NARGIN, nargs); - } + // Deferring it to the execute step also allows the path to be + // initialized between creating and execute the interpreter, for + // example, to set a custom path for an embedded interpreter. + + initialize_load_path (); + + octave_save_signal_mask (); + + can_interrupt = true; - // Read the history file unless a command-line option inhibits that. + octave_signal_hook = respond_to_pending_signals; + octave_interrupt_hook = nullptr; + + catch_interrupts (); + + // FIXME: could we eliminate this variable or make it not be global? + // Global used to communicate with signal handler. + octave_initialized = true; - void interpreter::initialize_history (bool read_history_file) - { - if (! m_history_initialized) - { - // Allow command-line option to override. + m_initialized = true; +} - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); +// Note: this function is currently only used with the new +// experimental terminal widget. + +void interpreter::get_line_and_eval (void) +{ + m_evaluator.get_line_and_eval (); +} - read_history_file = options.read_history_file (); +// Note: the following class is currently only used with the new +// experimental terminal widget. - if (! read_history_file) - command_history::ignore_entries (); - } +class cli_input_reader +{ +public: + + cli_input_reader (interpreter& interp) + : m_interpreter (interp), m_thread () { } - m_history_system.initialize (read_history_file); + cli_input_reader (const cli_input_reader&) = delete; + + cli_input_reader& operator = (const cli_input_reader&) = delete; - if (! m_app_context) - command_history::ignore_entries (); + ~cli_input_reader (void) + { + // FIXME: Would it be better to ensure that + // interpreter::get_line_and_eval exits and then call + // m_thread.join () here? - m_history_initialized = true; - } + m_thread.detach (); } - // Set the initial path to the system default unless command-line - // option says to leave it empty. - - void interpreter::initialize_load_path (bool set_initial_path) - { - if (! m_load_path_initialized) - { - // Allow command-line option to override. - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - set_initial_path = options.set_initial_path (); - } - - // Temporarily set the execute_pkg_add function to one that - // catches exceptions. This is better than wrapping - // load_path::initialize in a try-catch block because it will - // not stop executing PKG_ADD files at the first exception. - // It's also better than changing the default execute_pkg_add - // function to use safe_source file because that will normally - // be evaluated from the normal interpreter loop where exceptions - // are already handled. - - unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path, - m_load_path.get_add_hook ()); - - m_load_path.set_add_hook ([=] (const std::string& dir) - { this->execute_pkg_add (dir); }); - - m_load_path.initialize (set_initial_path); - - m_load_path_initialized = true; - } - } - - // This may be called separately from execute - - void interpreter::initialize (void) + void start (void) { - if (m_initialized) - return; - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - if (options.experimental_terminal_widget ()) - { - if (! options.gui ()) - display_startup_message (); - } - else - display_startup_message (); - } - else - display_startup_message (); - - // Wait to read the history file until the interpreter reads input - // files and begins evaluating commands. - - initialize_history (); - - // Initializing the load path may execute PKG_ADD files, so can't be - // done until the interpreter is ready to execute commands. - - // Deferring it to the execute step also allows the path to be - // initialized between creating and execute the interpreter, for - // example, to set a custom path for an embedded interpreter. - - initialize_load_path (); - - octave_save_signal_mask (); - - can_interrupt = true; - - octave_signal_hook = respond_to_pending_signals; - octave_interrupt_hook = nullptr; - - catch_interrupts (); - - // FIXME: could we eliminate this variable or make it not be global? - // Global used to communicate with signal handler. - octave_initialized = true; - - m_initialized = true; - } - - // Note: this function is currently only used with the new - // experimental terminal widget. - - void interpreter::get_line_and_eval (void) - { - m_evaluator.get_line_and_eval (); + m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter); } - // Note: the following class is currently only used with the new - // experimental terminal widget. +private: + + interpreter& m_interpreter; + + std::thread m_thread; +}; + +void interpreter::parse_and_execute (const std::string& input, + bool& incomplete_parse) +{ + m_evaluator.parse_and_execute (input, incomplete_parse); +} + +// FIXME: this function is intended to be executed only once. Should +// we enforce that restriction? + +int interpreter::execute (void) +{ + int exit_status = 0; + + try + { + initialize (); - class cli_input_reader - { - public: + execute_startup_files (); + + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); + + if (m_app_context->have_eval_option_code ()) + { + int status = execute_eval_option_code (); - cli_input_reader (interpreter& interp) - : m_interpreter (interp), m_thread () { } + if (status ) + exit_status = status; + + if (! options.persist ()) + { + shutdown (); - cli_input_reader (const cli_input_reader&) = delete; + return exit_status; + } + } + + // If there is an extra argument, see if it names a file to + // read. Additional arguments are taken as command line options + // for the script. - cli_input_reader& operator = (const cli_input_reader&) = delete; + if (m_app_context->have_script_file ()) + { + int status = execute_command_line_file (); + + if (status) + exit_status = status; + + if (! options.persist ()) + { + shutdown (); + + return exit_status; + } + } + + if (options.forced_interactive ()) + command_editor::blink_matching_paren (false); - ~cli_input_reader (void) + if (options.server ()) + exit_status = server_loop (); + else if (options.experimental_terminal_widget ()) + { + if (options.gui ()) + { + m_event_manager.start_gui (true); + + exit_status = server_loop (); + } + else + { + // Use an object so that the thread started for the + // reader will be cleaned up no matter how we exit + // this function. + + cli_input_reader reader (*this); + + reader.start (); + + exit_status = server_loop (); + } + } + else + exit_status = main_loop (); + + shutdown (); + } + } + catch (const exit_exception& xe) { - // FIXME: Would it be better to ensure that - // interpreter::get_line_and_eval exits and then call - // m_thread.join () here? + exit_status = xe.exit_status (); - m_thread.detach (); - } - - void start (void) - { - m_thread = std::thread (&interpreter::get_line_and_eval, &m_interpreter); + shutdown (); } - private: - - interpreter& m_interpreter; - - std::thread m_thread; - }; - - void interpreter::parse_and_execute (const std::string& input, - bool& incomplete_parse) - { - m_evaluator.parse_and_execute (input, incomplete_parse); - } - - // FIXME: this function is intended to be executed only once. Should - // we enforce that restriction? - - int interpreter::execute (void) - { - int exit_status = 0; - - try - { - initialize (); - - execute_startup_files (); - - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - if (m_app_context->have_eval_option_code ()) - { - int status = execute_eval_option_code (); - - if (status ) - exit_status = status; - - if (! options.persist ()) - { - shutdown (); - - return exit_status; - } - } - - // If there is an extra argument, see if it names a file to - // read. Additional arguments are taken as command line options - // for the script. - - if (m_app_context->have_script_file ()) - { - int status = execute_command_line_file (); + return exit_status; +} - if (status) - exit_status = status; - - if (! options.persist ()) - { - shutdown (); - - return exit_status; - } - } - - if (options.forced_interactive ()) - command_editor::blink_matching_paren (false); - - if (options.server ()) - exit_status = server_loop (); - else if (options.experimental_terminal_widget ()) - { - if (options.gui ()) - { - m_event_manager.start_gui (true); - - exit_status = server_loop (); - } - else - { - // Use an object so that the thread started for the - // reader will be cleaned up no matter how we exit - // this function. - - cli_input_reader reader (*this); - - reader.start (); - - exit_status = server_loop (); - } - } - else - exit_status = main_loop (); - - shutdown (); - } - } - catch (const exit_exception& xe) - { - exit_status = xe.exit_status (); - - shutdown (); - } - - return exit_status; - } - - // Call a function with exceptions handled to avoid problems with - // errors while shutting down. +// Call a function with exceptions handled to avoid problems with +// errors while shutting down. #define OCTAVE_IGNORE_EXCEPTION(E) \ catch (E) \ @@ -965,1121 +965,1121 @@ } \ while (0) - void interpreter::shutdown (void) - { - // Attempt to prevent more than one call to shutdown. +void interpreter::shutdown (void) +{ + // Attempt to prevent more than one call to shutdown. - if (! m_initialized) - return; + if (! m_initialized) + return; - m_initialized = false; + m_initialized = false; - OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); + OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); - // Any atexit functions added after this function call won't be - // executed. Each atexit function is executed with - // OCTAVE_SAFE_CALL, so we don't need that here. + // Any atexit functions added after this function call won't be + // executed. Each atexit function is executed with + // OCTAVE_SAFE_CALL, so we don't need that here. - execute_atexit_fcns (); + execute_atexit_fcns (); - // Clear all functions and variables while the event manager is - // still processing events and notify the event manager. This way, - // the workspace model will be cleared before the GUI exits. + // Clear all functions and variables while the event manager is + // still processing events and notify the event manager. This way, + // the workspace model will be cleared before the GUI exits. - // FIXME: This approach seems a bit fragile since there could be - // other places in the GUI that have references to interpreter - // objects. How can we reliably ensure that they are all removed - // before the interpreter exits? Maybe the best solution is to - // always start the GUI from the interpreter and close it when the - // interpreter exits? However, the workspace model is owned by the - // base_qobject object not the workspace viewer or the main window, - // so simply closing the GUI window(s) is not sufficient. See also - // bug #61994. + // FIXME: This approach seems a bit fragile since there could be + // other places in the GUI that have references to interpreter + // objects. How can we reliably ensure that they are all removed + // before the interpreter exits? Maybe the best solution is to + // always start the GUI from the interpreter and close it when the + // interpreter exits? However, the workspace model is owned by the + // base_qobject object not the workspace viewer or the main window, + // so simply closing the GUI window(s) is not sufficient. See also + // bug #61994. - // Note that we don't force symbols to be cleared, so we will - // respect mlock at this point. Later, we'll force all variables - // and functions to be cleared. + // Note that we don't force symbols to be cleared, so we will + // respect mlock at this point. Later, we'll force all variables + // and functions to be cleared. - OCTAVE_SAFE_CALL (clear_all, ()); - OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ()); + OCTAVE_SAFE_CALL (clear_all, ()); + OCTAVE_SAFE_CALL (m_event_manager.clear_workspace, ()); - // If we are attached to a GUI, queue and event to close it (only - // works with the new terminal widget), process pending events and - // disable the link. + // If we are attached to a GUI, queue and event to close it (only + // works with the new terminal widget), process pending events and + // disable the link. - OCTAVE_SAFE_CALL (m_event_manager.close_gui, ()); - OCTAVE_SAFE_CALL (m_event_manager.process_events, (true)); - OCTAVE_SAFE_CALL (m_event_manager.disable, ()); + OCTAVE_SAFE_CALL (m_event_manager.close_gui, ()); + OCTAVE_SAFE_CALL (m_event_manager.process_events, (true)); + OCTAVE_SAFE_CALL (m_event_manager.disable, ()); - OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ()); - - // We may still have some figures. Close them. + OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ()); - OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); + // We may still have some figures. Close them. - // What is supposed to happen if a figure has a closerequestfcn or - // deletefcn callback registered that creates other figures or - // variables? What if those variables are classdef objects with - // destructors that can create figures? The possibilities are - // endless. At some point, we have to give up and force execution - // to end. + OCTAVE_SAFE_CALL (feval, ("close", ovl ("all"), 0)); - // Note that we again don't force symbols to be cleared, so we - // continue to respect mlock here. Later, we'll force all variables - // and functions to be cleared. + // What is supposed to happen if a figure has a closerequestfcn or + // deletefcn callback registered that creates other figures or + // variables? What if those variables are classdef objects with + // destructors that can create figures? The possibilities are + // endless. At some point, we have to give up and force execution + // to end. - OCTAVE_SAFE_CALL (clear_all, ()); + // Note that we again don't force symbols to be cleared, so we + // continue to respect mlock here. Later, we'll force all variables + // and functions to be cleared. - // Do this explicitly so that destructors for mex file objects - // are called, so that functions registered with mexAtExit are - // called. + OCTAVE_SAFE_CALL (clear_all, ()); - OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ()); + // Do this explicitly so that destructors for mex file objects + // are called, so that functions registered with mexAtExit are + // called. - OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ()); - - OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ()); + OCTAVE_SAFE_CALL (m_symbol_table.clear_mex_functions, ()); - if (! command_history::ignoring_entries ()) - OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ()); + OCTAVE_SAFE_CALL (command_editor::restore_terminal_state, ()); + + OCTAVE_SAFE_CALL (m_history_system.write_timestamp, ()); - OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ()); + if (! command_history::ignoring_entries ()) + OCTAVE_SAFE_CALL (command_history::clean_up_and_save, ()); - // Now that the graphics toolkits have been unloaded, force all - // symbols to be cleared. + OCTAVE_SAFE_CALL (m_gtk_manager.unload_all_toolkits, ()); - OCTAVE_SAFE_CALL (clear_all, (true)); + // Now that the graphics toolkits have been unloaded, force all + // symbols to be cleared. + + OCTAVE_SAFE_CALL (clear_all, (true)); - // FIXME: May still need something like this to ensure that - // destructors for class objects will run properly. Should that be - // done earlier? Before or after atexit functions are executed? - // What will happen if the destructor for an obect attempts to - // display a figure? + // FIXME: May still need something like this to ensure that + // destructors for class objects will run properly. Should that be + // done earlier? Before or after atexit functions are executed? + // What will happen if the destructor for an obect attempts to + // display a figure? - OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ()); + OCTAVE_SAFE_CALL (m_symbol_table.cleanup, ()); - OCTAVE_SAFE_CALL (sysdep_cleanup, ()); + OCTAVE_SAFE_CALL (sysdep_cleanup, ()); - OCTAVE_SAFE_CALL (flush_stdout, ()); + OCTAVE_SAFE_CALL (flush_stdout, ()); - // Don't call singleton_cleanup_list::cleanup until we have the - // problems with registering/unregistering types worked out. For - // example, uncomment the following line, then use the make_int - // function from the examples directory to create an integer - // object and then exit Octave. Octave should crash with a - // segfault when cleaning up the typinfo singleton. We need some - // way to force new octave_value_X types that are created in - // .oct files to be unregistered when the .oct file shared library - // is unloaded. - // - // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); - } + // Don't call singleton_cleanup_list::cleanup until we have the + // problems with registering/unregistering types worked out. For + // example, uncomment the following line, then use the make_int + // function from the examples directory to create an integer + // object and then exit Octave. Octave should crash with a + // segfault when cleaning up the typinfo singleton. We need some + // way to force new octave_value_X types that are created in + // .oct files to be unregistered when the .oct file shared library + // is unloaded. + // + // OCTAVE_SAFE_CALL (singleton_cleanup_list::cleanup, ()); +} - void interpreter::execute_atexit_fcns (void) - { - // Prevent atexit functions from adding new functions to the list. - m_executing_atexit = true; +void interpreter::execute_atexit_fcns (void) +{ + // Prevent atexit functions from adding new functions to the list. + m_executing_atexit = true; - while (! m_atexit_fcns.empty ()) - { - std::string fcn = m_atexit_fcns.front (); + while (! m_atexit_fcns.empty ()) + { + std::string fcn = m_atexit_fcns.front (); - m_atexit_fcns.pop_front (); + m_atexit_fcns.pop_front (); - OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); + OCTAVE_SAFE_CALL (feval, (fcn, octave_value_list (), 0)); - OCTAVE_SAFE_CALL (flush_stdout, ()); - } - } + OCTAVE_SAFE_CALL (flush_stdout, ()); + } +} - void interpreter::display_startup_message (void) const - { - bool inhibit_startup_message = false; +void interpreter::display_startup_message (void) const +{ + bool inhibit_startup_message = false; - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); - - inhibit_startup_message = options.inhibit_startup_message (); - } + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - if (m_interactive && ! inhibit_startup_message) - std::cout << octave_startup_message () << "\n" << std::endl; - } + inhibit_startup_message = options.inhibit_startup_message (); + } - // Initialize by reading startup files. Return non-zero if an exception - // occurs when reading any of them, but don't exit early because of an - // exception. + if (m_interactive && ! inhibit_startup_message) + std::cout << octave_startup_message () << "\n" << std::endl; +} - int interpreter::execute_startup_files (void) - { - bool read_site_files = m_read_site_files; - bool read_init_files = m_read_init_files; - bool verbose = m_verbose; - bool inhibit_startup_message = m_inhibit_startup_message; +// Initialize by reading startup files. Return non-zero if an exception +// occurs when reading any of them, but don't exit early because of an +// exception. - if (m_app_context) - { - const cmdline_options& options = m_app_context->options (); +int interpreter::execute_startup_files (void) +{ + bool read_site_files = m_read_site_files; + bool read_init_files = m_read_init_files; + bool verbose = m_verbose; + bool inhibit_startup_message = m_inhibit_startup_message; - read_site_files = options.read_site_files (); - read_init_files = options.read_init_files (); - verbose = options.verbose_flag (); - inhibit_startup_message = options.inhibit_startup_message (); - } + if (m_app_context) + { + const cmdline_options& options = m_app_context->options (); - verbose = (verbose && ! inhibit_startup_message); + read_site_files = options.read_site_files (); + read_init_files = options.read_init_files (); + verbose = options.verbose_flag (); + inhibit_startup_message = options.inhibit_startup_message (); + } - bool require_file = false; + verbose = (verbose && ! inhibit_startup_message); - std::string context; + bool require_file = false; - int exit_status = 0; + std::string context; + + int exit_status = 0; - if (read_site_files) - { - // Execute commands from the site-wide configuration file. - // First from the file $(prefix)/lib/octave/site/m/octaverc - // (if it exists), then from the file - // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). + if (read_site_files) + { + // Execute commands from the site-wide configuration file. + // First from the file $(prefix)/lib/octave/site/m/octaverc + // (if it exists), then from the file + // $(prefix)/share/octave/$(version)/m/octaverc (if it exists). - int status = safe_source_file (config::local_site_defaults_file (), - context, verbose, require_file); + int status = safe_source_file (config::local_site_defaults_file (), + context, verbose, require_file); - if (status) - exit_status = status; + if (status) + exit_status = status; - status = safe_source_file (config::site_defaults_file (), - context, verbose, require_file); + status = safe_source_file (config::site_defaults_file (), + context, verbose, require_file); - if (status) - exit_status = status; - } + if (status) + exit_status = status; + } - if (read_init_files) - { - // Try to execute commands from the Matlab compatible startup.m file - // if it exists anywhere in the load path when starting Octave. - std::string ff_startup_m = file_in_path ("startup.m", ""); + if (read_init_files) + { + // Try to execute commands from the Matlab compatible startup.m file + // if it exists anywhere in the load path when starting Octave. + std::string ff_startup_m = file_in_path ("startup.m", ""); - if (! ff_startup_m.empty ()) - { - int parse_status = 0; + if (! ff_startup_m.empty ()) + { + int parse_status = 0; - try - { - eval_string (std::string ("startup"), false, parse_status, 0); - } - catch (const interrupt_exception&) - { - recover_from_exception (); - } - catch (const execution_exception& ee) - { - handle_exception (ee); - } - } - - // Try to execute commands from $CONFIG/octave/octaverc, where - // $CONFIG is the platform-dependent location for user local - // configuration files. + try + { + eval_string (std::string ("startup"), false, parse_status, 0); + } + catch (const interrupt_exception&) + { + recover_from_exception (); + } + catch (const execution_exception& ee) + { + handle_exception (ee); + } + } - std::string user_config_dir = sys::env::get_user_config_directory (); + // Try to execute commands from $CONFIG/octave/octaverc, where + // $CONFIG is the platform-dependent location for user local + // configuration files. - std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str () - + "octave"; + std::string user_config_dir = sys::env::get_user_config_directory (); - std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir); + std::string cfg_dir = user_config_dir + sys::file_ops::dir_sep_str () + + "octave"; - if (! cfg_rc.empty ()) - { - int status = safe_source_file (cfg_rc, context, verbose, - require_file); + std::string cfg_rc = sys::env::make_absolute ("octaverc", cfg_dir); - if (status) - exit_status = status; - } + if (! cfg_rc.empty ()) + { + int status = safe_source_file (cfg_rc, context, verbose, + require_file); - // Try to execute commands from $HOME/$OCTAVE_INITFILE and - // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, - // .octaverc is assumed. + if (status) + exit_status = status; + } - bool home_rc_already_executed = false; - - std::string initfile = sys::env::getenv ("OCTAVE_INITFILE"); + // Try to execute commands from $HOME/$OCTAVE_INITFILE and + // $OCTAVE_INITFILE. If $OCTAVE_INITFILE is not set, + // .octaverc is assumed. - if (initfile.empty ()) - initfile = ".octaverc"; + bool home_rc_already_executed = false; - std::string home_dir = sys::env::get_home_directory (); + std::string initfile = sys::env::getenv ("OCTAVE_INITFILE"); - std::string home_rc = sys::env::make_absolute (initfile, home_dir); - - std::string local_rc; + if (initfile.empty ()) + initfile = ".octaverc"; - if (! home_rc.empty ()) - { - int status = safe_source_file (home_rc, context, verbose, - require_file); + std::string home_dir = sys::env::get_home_directory (); + + std::string home_rc = sys::env::make_absolute (initfile, home_dir); + + std::string local_rc; - if (status) - exit_status = status; + if (! home_rc.empty ()) + { + int status = safe_source_file (home_rc, context, verbose, + require_file); - // Names alone are not enough. - - sys::file_stat fs_home_rc (home_rc); + if (status) + exit_status = status; - if (fs_home_rc) - { - // We want to check for curr_dir after executing home_rc - // because doing that may change the working directory. + // Names alone are not enough. - local_rc = sys::env::make_absolute (initfile); + sys::file_stat fs_home_rc (home_rc); - home_rc_already_executed = same_file (home_rc, local_rc); - } - } + if (fs_home_rc) + { + // We want to check for curr_dir after executing home_rc + // because doing that may change the working directory. - if (! home_rc_already_executed) - { - if (local_rc.empty ()) local_rc = sys::env::make_absolute (initfile); - int status = safe_source_file (local_rc, context, verbose, - require_file); + home_rc_already_executed = same_file (home_rc, local_rc); + } + } - if (status) - exit_status = status; - } - } + if (! home_rc_already_executed) + { + if (local_rc.empty ()) + local_rc = sys::env::make_absolute (initfile); - if (m_interactive && verbose) - std::cout << std::endl; + int status = safe_source_file (local_rc, context, verbose, + require_file); - return exit_status; - } + if (status) + exit_status = status; + } + } - // Execute any code specified with --eval 'CODE' + if (m_interactive && verbose) + std::cout << std::endl; - int interpreter::execute_eval_option_code (void) - { - if (! m_app_context) - return 0; + return exit_status; +} + +// Execute any code specified with --eval 'CODE' - const cmdline_options& options = m_app_context->options (); - - std::string code_to_eval = options.code_to_eval (); +int interpreter::execute_eval_option_code (void) +{ + if (! m_app_context) + return 0; - unwind_protect_var upv (m_interactive, false); + const cmdline_options& options = m_app_context->options (); - int parse_status = 0; + std::string code_to_eval = options.code_to_eval (); + + unwind_protect_var upv (m_interactive, false); - try - { - eval_string (code_to_eval, false, parse_status, 0); - } - catch (const interrupt_exception&) - { - recover_from_exception (); + int parse_status = 0; - return 1; - } - catch (const execution_exception& ee) - { - handle_exception (ee); + try + { + eval_string (code_to_eval, false, parse_status, 0); + } + catch (const interrupt_exception&) + { + recover_from_exception (); - return 1; - } + return 1; + } + catch (const execution_exception& ee) + { + handle_exception (ee); - return parse_status; - } + return 1; + } - int interpreter::execute_command_line_file (void) - { - if (! m_app_context) - return 0; + return parse_status; +} - const cmdline_options& options = m_app_context->options (); +int interpreter::execute_command_line_file (void) +{ + if (! m_app_context) + return 0; - string_vector args = options.all_args (); + const cmdline_options& options = m_app_context->options (); - void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive; - unwind_action restore_interactive (interactive_fptr, this, m_interactive); + string_vector args = options.all_args (); - unwind_action restore_argv (&application::intern_argv, m_app_context, args); + void (interpreter::*interactive_fptr) (bool) = &interpreter::interactive; + unwind_action restore_interactive (interactive_fptr, this, m_interactive); + + unwind_action restore_argv (&application::intern_argv, m_app_context, args); - unwind_action restore_nargin (&interpreter::intern_nargin, this, - args.numel () - 1); + unwind_action restore_nargin (&interpreter::intern_nargin, this, + args.numel () - 1); - void (application::*program_invocation_name_fptr) (const std::string&) - = &application::program_invocation_name; - unwind_action restore_program_invocation_name - (program_invocation_name_fptr, m_app_context, - application::program_invocation_name ()); + void (application::*program_invocation_name_fptr) (const std::string&) + = &application::program_invocation_name; + unwind_action restore_program_invocation_name + (program_invocation_name_fptr, m_app_context, + application::program_invocation_name ()); - void (application::*program_name_fptr) (const std::string&) - = &application::program_name; - unwind_action restore_program_name - (program_name_fptr, m_app_context, application::program_name ()); + void (application::*program_name_fptr) (const std::string&) + = &application::program_name; + unwind_action restore_program_name + (program_name_fptr, m_app_context, application::program_name ()); - m_interactive = false; + m_interactive = false; - // If we are running an executable script (#! /bin/octave) then - // we should only see the args passed to the script. + // If we are running an executable script (#! /bin/octave) then + // we should only see the args passed to the script. - string_vector script_args = options.remaining_args (); + string_vector script_args = options.remaining_args (); - m_app_context->intern_argv (script_args); - intern_nargin (script_args.numel () - 1); + m_app_context->intern_argv (script_args); + intern_nargin (script_args.numel () - 1); - std::string fname = script_args[0]; + std::string fname = script_args[0]; - m_app_context->set_program_names (fname); + m_app_context->set_program_names (fname); - std::string context; - bool verbose = false; - bool require_file = true; + std::string context; + bool verbose = false; + bool require_file = true; + + return safe_source_file (fname, context, verbose, require_file); +} - return safe_source_file (fname, context, verbose, require_file); - } +int interpreter::main_loop (void) +{ + command_editor::add_event_hook (release_unreferenced_dynamic_libraries); - int interpreter::main_loop (void) - { - command_editor::add_event_hook (release_unreferenced_dynamic_libraries); + return m_evaluator.repl (); +} - return m_evaluator.repl (); - } +int interpreter::server_loop (void) +{ + return m_evaluator.server_loop (); +} - int interpreter::server_loop (void) - { - return m_evaluator.server_loop (); - } +tree_evaluator& interpreter::get_evaluator (void) +{ + return m_evaluator; +} - tree_evaluator& interpreter::get_evaluator (void) - { - return m_evaluator; - } +stream_list& interpreter::get_stream_list (void) +{ + return m_stream_list; +} - stream_list& interpreter::get_stream_list (void) - { - return m_stream_list; - } +url_handle_manager& interpreter::get_url_handle_manager (void) +{ + return m_url_handle_manager; +} - url_handle_manager& interpreter::get_url_handle_manager (void) - { - return m_url_handle_manager; - } +symbol_scope +interpreter::get_top_scope (void) const +{ + return m_evaluator.get_top_scope (); +} - symbol_scope - interpreter::get_top_scope (void) const - { - return m_evaluator.get_top_scope (); - } +symbol_scope +interpreter::get_current_scope (void) const +{ + return m_evaluator.get_current_scope (); +} - symbol_scope - interpreter::get_current_scope (void) const - { - return m_evaluator.get_current_scope (); - } +symbol_scope +interpreter::require_current_scope (const std::string& who) const +{ + symbol_scope scope = get_current_scope (); + + if (! scope) + error ("%s: symbol table scope missing", who.c_str ()); - symbol_scope - interpreter::require_current_scope (const std::string& who) const - { - symbol_scope scope = get_current_scope (); + return scope; +} - if (! scope) - error ("%s: symbol table scope missing", who.c_str ()); +profiler& interpreter::get_profiler (void) +{ + return m_evaluator.get_profiler (); +} - return scope; - } +int interpreter::chdir (const std::string& dir) +{ + std::string xdir = sys::file_ops::tilde_expand (dir); - profiler& interpreter::get_profiler (void) - { - return m_evaluator.get_profiler (); - } + int cd_ok = sys::env::chdir (xdir); - int interpreter::chdir (const std::string& dir) - { - std::string xdir = sys::file_ops::tilde_expand (dir); + if (! cd_ok) + error ("%s: %s", dir.c_str (), std::strerror (errno)); + + Vlast_chdir_time.stamp (); - int cd_ok = sys::env::chdir (xdir); + // FIXME: should these actions be handled as a list of functions + // to call so users can add their own chdir handlers? - if (! cd_ok) - error ("%s: %s", dir.c_str (), std::strerror (errno)); - - Vlast_chdir_time.stamp (); + m_load_path.read_dir_config ("."); + m_load_path.update (); - // FIXME: should these actions be handled as a list of functions - // to call so users can add their own chdir handlers? + m_event_manager.directory_changed (sys::env::get_current_directory ()); - m_load_path.read_dir_config ("."); - m_load_path.update (); - - m_event_manager.directory_changed (sys::env::get_current_directory ()); + return cd_ok; +} - return cd_ok; - } +void interpreter::mlock (bool skip_first) const +{ + m_evaluator.mlock (skip_first); +} - void interpreter::mlock (bool skip_first) const - { - m_evaluator.mlock (skip_first); - } +void interpreter::munlock (bool skip_first) const +{ + m_evaluator.munlock (skip_first); +} - void interpreter::munlock (bool skip_first) const - { - m_evaluator.munlock (skip_first); - } +bool interpreter::mislocked (bool skip_first) const +{ + return m_evaluator.mislocked (skip_first); +} + +void interpreter::munlock (const char *nm) +{ + if (! nm) + error ("munlock: invalid value for NAME"); - bool interpreter::mislocked (bool skip_first) const - { - return m_evaluator.mislocked (skip_first); - } + munlock (std::string (nm)); +} - void interpreter::munlock (const char *nm) - { - if (! nm) - error ("munlock: invalid value for NAME"); +void interpreter::munlock (const std::string& nm) +{ + octave_value val = m_symbol_table.find_function (nm); - munlock (std::string (nm)); - } + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - void interpreter::munlock (const std::string& nm) - { - octave_value val = m_symbol_table.find_function (nm); + if (fcn) + fcn->unlock (); + } +} - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); +bool interpreter::mislocked (const char *nm) +{ + if (! nm) + error ("mislocked: invalid value for NAME"); - if (fcn) - fcn->unlock (); - } - } + return mislocked (std::string (nm)); +} + +bool interpreter::mislocked (const std::string& nm) +{ + bool retval = false; - bool interpreter::mislocked (const char *nm) - { - if (! nm) - error ("mislocked: invalid value for NAME"); + octave_value val = m_symbol_table.find_function (nm); - return mislocked (std::string (nm)); - } + if (val.is_defined ()) + { + octave_function *fcn = val.function_value (); - bool interpreter::mislocked (const std::string& nm) - { - bool retval = false; - - octave_value val = m_symbol_table.find_function (nm); + if (fcn) + retval = fcn->islocked (); + } - if (val.is_defined ()) - { - octave_function *fcn = val.function_value (); + return retval; +} - if (fcn) - retval = fcn->islocked (); - } +std::string interpreter::mfilename (const std::string& opt) const +{ + return m_evaluator.mfilename (opt); +} - return retval; - } +octave_value_list interpreter::eval_string (const std::string& eval_str, + bool silent, int& parse_status, + int nargout) +{ + return m_evaluator.eval_string (eval_str, silent, parse_status, nargout); +} - std::string interpreter::mfilename (const std::string& opt) const - { - return m_evaluator.mfilename (opt); - } +octave_value interpreter::eval_string (const std::string& eval_str, + bool silent, int& parse_status) +{ + return m_evaluator.eval_string (eval_str, silent, parse_status); +} - octave_value_list interpreter::eval_string (const std::string& eval_str, - bool silent, int& parse_status, - int nargout) - { - return m_evaluator.eval_string (eval_str, silent, parse_status, nargout); - } +octave_value_list interpreter::eval_string (const octave_value& arg, + bool silent, int& parse_status, + int nargout) +{ + return m_evaluator.eval_string (arg, silent, parse_status, nargout); +} - octave_value interpreter::eval_string (const std::string& eval_str, - bool silent, int& parse_status) - { - return m_evaluator.eval_string (eval_str, silent, parse_status); - } +octave_value_list interpreter::eval (const std::string& try_code, + int nargout) +{ + return m_evaluator.eval (try_code, nargout); +} - octave_value_list interpreter::eval_string (const octave_value& arg, - bool silent, int& parse_status, - int nargout) - { - return m_evaluator.eval_string (arg, silent, parse_status, nargout); - } +octave_value_list interpreter::eval (const std::string& try_code, + const std::string& catch_code, + int nargout) +{ + return m_evaluator.eval (try_code, catch_code, nargout); +} - octave_value_list interpreter::eval (const std::string& try_code, +octave_value_list interpreter::evalin (const std::string& context, + const std::string& try_code, int nargout) - { - return m_evaluator.eval (try_code, nargout); - } +{ + return m_evaluator.evalin (context, try_code, nargout); +} - octave_value_list interpreter::eval (const std::string& try_code, +octave_value_list interpreter::evalin (const std::string& context, + const std::string& try_code, const std::string& catch_code, int nargout) - { - return m_evaluator.eval (try_code, catch_code, nargout); - } +{ + return m_evaluator.evalin (context, try_code, catch_code, nargout); +} - octave_value_list interpreter::evalin (const std::string& context, - const std::string& try_code, - int nargout) - { - return m_evaluator.evalin (context, try_code, nargout); - } +//! Evaluate an Octave function (built-in or interpreted) and return +//! the list of result values. +//! +//! @param name The name of the function to call. +//! @param args The arguments to the function. +//! @param nargout The number of output arguments expected. +//! @return A list of output values. The length of the list is not +//! necessarily the same as @c nargout. - octave_value_list interpreter::evalin (const std::string& context, - const std::string& try_code, - const std::string& catch_code, - int nargout) - { - return m_evaluator.evalin (context, try_code, catch_code, nargout); - } +octave_value_list interpreter::feval (const char *name, + const octave_value_list& args, + int nargout) +{ + return feval (std::string (name), args, nargout); +} - //! Evaluate an Octave function (built-in or interpreted) and return - //! the list of result values. - //! - //! @param name The name of the function to call. - //! @param args The arguments to the function. - //! @param nargout The number of output arguments expected. - //! @return A list of output values. The length of the list is not - //! necessarily the same as @c nargout. +octave_value_list interpreter::feval (const std::string& name, + const octave_value_list& args, + int nargout) +{ + octave_value fcn = m_symbol_table.find_function (name, args); + + if (fcn.is_undefined ()) + error ("feval: function '%s' not found", name.c_str ()); + + octave_function *of = fcn.function_value (); - octave_value_list interpreter::feval (const char *name, - const octave_value_list& args, - int nargout) - { - return feval (std::string (name), args, nargout); - } + return of->call (m_evaluator, nargout, args); +} - octave_value_list interpreter::feval (const std::string& name, - const octave_value_list& args, - int nargout) - { - octave_value fcn = m_symbol_table.find_function (name, args); +octave_value_list interpreter::feval (octave_function *fcn, + const octave_value_list& args, + int nargout) +{ + if (fcn) + return fcn->call (m_evaluator, nargout, args); - if (fcn.is_undefined ()) - error ("feval: function '%s' not found", name.c_str ()); - - octave_function *of = fcn.function_value (); + return octave_value_list (); +} - return of->call (m_evaluator, nargout, args); - } - - octave_value_list interpreter::feval (octave_function *fcn, - const octave_value_list& args, - int nargout) - { - if (fcn) - return fcn->call (m_evaluator, nargout, args); +octave_value_list interpreter::feval (const octave_value& val, + const octave_value_list& args, + int nargout) +{ + // FIXME: do we really want to silently return an empty ovl if + // the function object is undefined? It's essentially what the + // version above that accepts a pointer to an octave_function + // object does and some code was apparently written to rely on it + // (for example, __ode15__). - return octave_value_list (); - } + if (val.is_undefined ()) + return ovl (); - octave_value_list interpreter::feval (const octave_value& val, - const octave_value_list& args, - int nargout) - { - // FIXME: do we really want to silently return an empty ovl if - // the function object is undefined? It's essentially what the - // version above that accepts a pointer to an octave_function - // object does and some code was apparently written to rely on it - // (for example, __ode15__). + if (val.is_function ()) + { + return feval (val.function_value (), args, nargout); + } + else if (val.is_function_handle () || val.is_inline_function ()) + { + // This covers function handles, inline functions, and anonymous + // functions. - if (val.is_undefined ()) - return ovl (); + std::list arg_list; + arg_list.push_back (args); - if (val.is_function ()) - { - return feval (val.function_value (), args, nargout); - } - else if (val.is_function_handle () || val.is_inline_function ()) - { - // This covers function handles, inline functions, and anonymous - // functions. - - std::list arg_list; - arg_list.push_back (args); + // FIXME: could we make octave_value::subsref a const method? + // It would be difficult because there are instances of + // incrementing the reference count inside subsref methods, + // which means they can't be const with the current way of + // handling reference counting. - // FIXME: could we make octave_value::subsref a const method? - // It would be difficult because there are instances of - // incrementing the reference count inside subsref methods, - // which means they can't be const with the current way of - // handling reference counting. + octave_value xval = val; + return xval.subsref ("(", arg_list, nargout); + } + else if (val.is_string ()) + { + return feval (val.string_value (), args, nargout); + } + else + error ("feval: first argument must be a string, inline function, or a function handle"); - octave_value xval = val; - return xval.subsref ("(", arg_list, nargout); - } - else if (val.is_string ()) - { - return feval (val.string_value (), args, nargout); - } - else - error ("feval: first argument must be a string, inline function, or a function handle"); + return ovl (); +} - return ovl (); - } +//! Evaluate an Octave function (built-in or interpreted) and return +//! the list of result values. +//! +//! @param args The first element of @c args is the function to call. +//! It may be the name of the function as a string, a function +//! handle, or an inline function. The remaining arguments are +//! passed to the function. +//! @param nargout The number of output arguments expected. +//! @return A list of output values. The length of the list is not +//! necessarily the same as @c nargout. - //! Evaluate an Octave function (built-in or interpreted) and return - //! the list of result values. - //! - //! @param args The first element of @c args is the function to call. - //! It may be the name of the function as a string, a function - //! handle, or an inline function. The remaining arguments are - //! passed to the function. - //! @param nargout The number of output arguments expected. - //! @return A list of output values. The length of the list is not - //! necessarily the same as @c nargout. +octave_value_list interpreter::feval (const octave_value_list& args, + int nargout) +{ + if (args.length () == 0) + error ("feval: first argument must be a string, inline function, or a function handle"); - octave_value_list interpreter::feval (const octave_value_list& args, - int nargout) - { - if (args.length () == 0) - error ("feval: first argument must be a string, inline function, or a function handle"); + octave_value f_arg = args(0); + + octave_value_list tmp_args = args.slice (1, args.length () - 1, true); + + return feval (f_arg, tmp_args, nargout); +} - octave_value f_arg = args(0); +octave_value interpreter::make_function_handle (const std::string& name) +{ + return m_evaluator.make_fcn_handle (name); +} - octave_value_list tmp_args = args.slice (1, args.length () - 1, true); - - return feval (f_arg, tmp_args, nargout); - } +void interpreter::install_variable (const std::string& name, + const octave_value& value, bool global) +{ + m_evaluator.install_variable (name, value, global); +} - octave_value interpreter::make_function_handle (const std::string& name) - { - return m_evaluator.make_fcn_handle (name); - } +octave_value interpreter::global_varval (const std::string& name) const +{ + return m_evaluator.global_varval (name); +} - void interpreter::install_variable (const std::string& name, - const octave_value& value, bool global) - { - m_evaluator.install_variable (name, value, global); - } +void interpreter::global_assign (const std::string& name, + const octave_value& val) +{ + m_evaluator.global_assign (name, val); +} - octave_value interpreter::global_varval (const std::string& name) const - { - return m_evaluator.global_varval (name); - } +octave_value interpreter::top_level_varval (const std::string& name) const +{ + return m_evaluator.top_level_varval (name); +} - void interpreter::global_assign (const std::string& name, - const octave_value& val) - { - m_evaluator.global_assign (name, val); - } +void interpreter::top_level_assign (const std::string& name, + const octave_value& val) +{ + m_evaluator.top_level_assign (name, val); +} - octave_value interpreter::top_level_varval (const std::string& name) const - { - return m_evaluator.top_level_varval (name); - } +bool interpreter::is_variable (const std::string& name) const +{ + return m_evaluator.is_variable (name); +} - void interpreter::top_level_assign (const std::string& name, - const octave_value& val) - { - m_evaluator.top_level_assign (name, val); - } +bool interpreter::is_local_variable (const std::string& name) const +{ + return m_evaluator.is_local_variable (name); +} - bool interpreter::is_variable (const std::string& name) const - { - return m_evaluator.is_variable (name); - } +octave_value interpreter::varval (const std::string& name) const +{ + return m_evaluator.varval (name); +} - bool interpreter::is_local_variable (const std::string& name) const - { - return m_evaluator.is_local_variable (name); - } +void interpreter::assign (const std::string& name, + const octave_value& val) +{ + m_evaluator.assign (name, val); +} - octave_value interpreter::varval (const std::string& name) const - { - return m_evaluator.varval (name); - } +void interpreter::assignin (const std::string& context, + const std::string& name, + const octave_value& val) +{ + m_evaluator.assignin (context, name, val); +} - void interpreter::assign (const std::string& name, - const octave_value& val) - { - m_evaluator.assign (name, val); - } +void interpreter::source_file (const std::string& file_name, + const std::string& context, bool verbose, + bool require_file) +{ + m_evaluator.source_file (file_name, context, verbose, require_file); +} - void interpreter::assignin (const std::string& context, - const std::string& name, - const octave_value& val) - { - m_evaluator.assignin (context, name, val); - } +bool interpreter::at_top_level (void) const +{ + return m_evaluator.at_top_level (); +} + +bool interpreter::isglobal (const std::string& name) const +{ + return m_evaluator.is_global (name); +} - void interpreter::source_file (const std::string& file_name, - const std::string& context, bool verbose, - bool require_file) - { - m_evaluator.source_file (file_name, context, verbose, require_file); - } +octave_value interpreter::find (const std::string& name) +{ + return m_evaluator.find (name); +} - bool interpreter::at_top_level (void) const - { - return m_evaluator.at_top_level (); - } - - bool interpreter::isglobal (const std::string& name) const - { - return m_evaluator.is_global (name); - } +void interpreter::clear_all (bool force) +{ + m_evaluator.clear_all (force); +} - octave_value interpreter::find (const std::string& name) - { - return m_evaluator.find (name); - } +void interpreter::clear_objects (void) +{ + m_evaluator.clear_objects (); +} - void interpreter::clear_all (bool force) - { - m_evaluator.clear_all (force); - } +void interpreter::clear_variable (const std::string& name) +{ + m_evaluator.clear_variable (name); +} - void interpreter::clear_objects (void) - { - m_evaluator.clear_objects (); - } +void interpreter::clear_variable_pattern (const std::string& pattern) +{ + m_evaluator.clear_variable_pattern (pattern); +} - void interpreter::clear_variable (const std::string& name) - { - m_evaluator.clear_variable (name); - } +void interpreter::clear_variable_regexp (const std::string& pattern) +{ + m_evaluator.clear_variable_regexp (pattern); +} - void interpreter::clear_variable_pattern (const std::string& pattern) - { - m_evaluator.clear_variable_pattern (pattern); - } +void interpreter::clear_variables (void) +{ + m_evaluator.clear_variables (); +} - void interpreter::clear_variable_regexp (const std::string& pattern) - { - m_evaluator.clear_variable_regexp (pattern); - } +void interpreter::clear_global_variable (const std::string& name) +{ + m_evaluator.clear_global_variable (name); +} - void interpreter::clear_variables (void) - { - m_evaluator.clear_variables (); - } +void interpreter::clear_global_variable_pattern (const std::string& pattern) +{ + m_evaluator.clear_global_variable_pattern (pattern); +} - void interpreter::clear_global_variable (const std::string& name) - { - m_evaluator.clear_global_variable (name); - } +void interpreter::clear_global_variable_regexp (const std::string& pattern) +{ + m_evaluator.clear_global_variable_regexp (pattern); +} - void interpreter::clear_global_variable_pattern (const std::string& pattern) - { - m_evaluator.clear_global_variable_pattern (pattern); - } +void interpreter::clear_global_variables (void) +{ + m_evaluator.clear_global_variables (); +} - void interpreter::clear_global_variable_regexp (const std::string& pattern) - { - m_evaluator.clear_global_variable_regexp (pattern); - } +void interpreter::clear_functions (bool force) +{ + m_symbol_table.clear_functions (force); +} - void interpreter::clear_global_variables (void) - { - m_evaluator.clear_global_variables (); - } +void interpreter::clear_function (const std::string& name) +{ + m_symbol_table.clear_function (name); +} - void interpreter::clear_functions (bool force) - { - m_symbol_table.clear_functions (force); - } +void interpreter::clear_symbol (const std::string& name) +{ + m_evaluator.clear_symbol (name); +} - void interpreter::clear_function (const std::string& name) - { - m_symbol_table.clear_function (name); - } +void interpreter::clear_function_pattern (const std::string& pat) +{ + m_symbol_table.clear_function_pattern (pat); +} - void interpreter::clear_symbol (const std::string& name) - { - m_evaluator.clear_symbol (name); - } +void interpreter::clear_function_regexp (const std::string& pat) +{ + m_symbol_table.clear_function_regexp (pat); +} - void interpreter::clear_function_pattern (const std::string& pat) - { - m_symbol_table.clear_function_pattern (pat); - } +void interpreter::clear_symbol_pattern (const std::string& pat) +{ + return m_evaluator.clear_symbol_pattern (pat); +} - void interpreter::clear_function_regexp (const std::string& pat) - { - m_symbol_table.clear_function_regexp (pat); - } +void interpreter::clear_symbol_regexp (const std::string& pat) +{ + return m_evaluator.clear_symbol_regexp (pat); +} - void interpreter::clear_symbol_pattern (const std::string& pat) - { - return m_evaluator.clear_symbol_pattern (pat); - } +std::list interpreter::global_variable_names (void) +{ + return m_evaluator.global_variable_names (); +} - void interpreter::clear_symbol_regexp (const std::string& pat) - { - return m_evaluator.clear_symbol_regexp (pat); - } +std::list interpreter::top_level_variable_names (void) +{ + return m_evaluator.top_level_variable_names (); +} - std::list interpreter::global_variable_names (void) - { - return m_evaluator.global_variable_names (); - } +std::list interpreter::variable_names (void) +{ + return m_evaluator.variable_names (); +} - std::list interpreter::top_level_variable_names (void) - { - return m_evaluator.top_level_variable_names (); - } +std::list interpreter::user_function_names (void) +{ + return m_symbol_table.user_function_names (); +} - std::list interpreter::variable_names (void) - { - return m_evaluator.variable_names (); - } +std::list interpreter::autoloaded_functions (void) const +{ + return m_evaluator.autoloaded_functions (); +} + +// May be used to send an interrupt signal to the the interpreter from +// another thread (for example, the GUI). - std::list interpreter::user_function_names (void) - { - return m_symbol_table.user_function_names (); - } +void interpreter::interrupt (void) +{ + static int sigint = 0; + static bool first = true; - std::list interpreter::autoloaded_functions (void) const - { - return m_evaluator.autoloaded_functions (); - } - - // May be used to send an interrupt signal to the the interpreter from - // another thread (for example, the GUI). - - void interpreter::interrupt (void) - { - static int sigint = 0; - static bool first = true; + if (first) + { + octave_get_sig_number ("SIGINT", &sigint); + first = false; + } - if (first) - { - octave_get_sig_number ("SIGINT", &sigint); - first = false; - } + // Send SIGINT to Octave and (optionally) all other processes in its + // process group. The signal handler for SIGINT will set a global + // variable indicating an interrupt has happened. That variable is + // checked in many places in the Octave interpreter and eventually + // results in an interrupt_exception being thrown. Finally, that + // exception is caught and returns control to one of the + // read-eval-print loops or to the server loop. We use a signal + // instead of just setting the global variables here so that we will + // probably send interrupt signals to any subprocesses as well as + // interrupt execution of the interpreter. - // Send SIGINT to Octave and (optionally) all other processes in its - // process group. The signal handler for SIGINT will set a global - // variable indicating an interrupt has happened. That variable is - // checked in many places in the Octave interpreter and eventually - // results in an interrupt_exception being thrown. Finally, that - // exception is caught and returns control to one of the - // read-eval-print loops or to the server loop. We use a signal - // instead of just setting the global variables here so that we will - // probably send interrupt signals to any subprocesses as well as - // interrupt execution of the interpreter. + pid_t pid + = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper (); - pid_t pid - = m_interrupt_all_in_process_group ? 0 : octave_getpid_wrapper (); + octave_kill_wrapper (pid, sigint); +} + +void interpreter::pause (void) +{ + // FIXME: To be reliable, these tree_evaluator functions must be + // made thread safe. - octave_kill_wrapper (pid, sigint); - } - - void interpreter::pause (void) - { - // FIXME: To be reliable, these tree_evaluator functions must be - // made thread safe. + m_evaluator.break_on_next_statement (true); + m_evaluator.reset_debug_state (); +} - m_evaluator.break_on_next_statement (true); - m_evaluator.reset_debug_state (); - } +void interpreter::stop (void) +{ + // FIXME: To be reliable, these tree_evaluator functions must be + // made thread safe. - void interpreter::stop (void) - { - // FIXME: To be reliable, these tree_evaluator functions must be - // made thread safe. + if (m_evaluator.in_debug_repl ()) + m_evaluator.dbquit (true); + else + interrupt (); +} - if (m_evaluator.in_debug_repl ()) - m_evaluator.dbquit (true); - else - interrupt (); - } +void interpreter::resume (void) +{ + // FIXME: To be reliable, these tree_evaluator functions must be + // made thread safe. + + // FIXME: Should there be any feeback about not doing anything if + // not in debug mode? - void interpreter::resume (void) - { - // FIXME: To be reliable, these tree_evaluator functions must be - // made thread safe. + if (m_evaluator.in_debug_repl ()) + m_evaluator.dbcont (); +} - // FIXME: Should there be any feeback about not doing anything if - // not in debug mode? - - if (m_evaluator.in_debug_repl ()) - m_evaluator.dbcont (); - } +// Provided for convenience. Will be removed once we eliminate the +// old terminal widget. +bool interpreter::experimental_terminal_widget (void) const +{ + if (! m_app_context) + return false; - // Provided for convenience. Will be removed once we eliminate the - // old terminal widget. - bool interpreter::experimental_terminal_widget (void) const - { - if (! m_app_context) - return false; + // Embedded interpreters don't execute command line options. + const cmdline_options& options = m_app_context->options (); + + return options.experimental_terminal_widget (); +} - // Embedded interpreters don't execute command line options. - const cmdline_options& options = m_app_context->options (); +void interpreter::add_debug_watch_expression (const std::string& expr) +{ + m_evaluator.add_debug_watch_expression (expr); +} - return options.experimental_terminal_widget (); - } - - void interpreter::add_debug_watch_expression (const std::string& expr) - { - m_evaluator.add_debug_watch_expression (expr); - } +void interpreter::remove_debug_watch_expression (const std::string& expr) +{ + m_evaluator.remove_debug_watch_expression (expr); +} - void interpreter::remove_debug_watch_expression (const std::string& expr) - { - m_evaluator.remove_debug_watch_expression (expr); - } +void interpreter::clear_debug_watch_expressions (void) +{ + m_evaluator.clear_debug_watch_expressions (); +} + +std::set interpreter::debug_watch_expressions (void) const +{ + return m_evaluator.debug_watch_expressions (); +} - void interpreter::clear_debug_watch_expressions (void) - { - m_evaluator.clear_debug_watch_expressions (); - } +void interpreter::handle_exception (const execution_exception& ee) +{ + m_error_system.save_exception (ee); - std::set interpreter::debug_watch_expressions (void) const - { - return m_evaluator.debug_watch_expressions (); - } + // FIXME: use a separate stream instead of std::cerr directly so that + // error messages can be redirected more easily? Pass the message + // to an event manager function? + m_error_system.display_exception (ee); - void interpreter::handle_exception (const execution_exception& ee) - { - m_error_system.save_exception (ee); + recover_from_exception (); +} - // FIXME: use a separate stream instead of std::cerr directly so that - // error messages can be redirected more easily? Pass the message - // to an event manager function? - m_error_system.display_exception (ee); +void interpreter::recover_from_exception (void) +{ + if (octave_interrupt_state) + m_event_manager.interpreter_interrupted (); - recover_from_exception (); - } - - void interpreter::recover_from_exception (void) - { - if (octave_interrupt_state) - m_event_manager.interpreter_interrupted (); + can_interrupt = true; + octave_interrupt_state = 0; + octave_signal_caught = 0; + octave_restore_signal_mask (); + catch_interrupts (); +} - can_interrupt = true; - octave_interrupt_state = 0; - octave_signal_caught = 0; - octave_restore_signal_mask (); - catch_interrupts (); - } +void interpreter::mark_for_deletion (const std::string& file) +{ + m_tmp_files.insert (file); +} - void interpreter::mark_for_deletion (const std::string& file) - { - m_tmp_files.insert (file); - } +void interpreter::cleanup_tmp_files (void) +{ + m_tmp_files.cleanup (); +} - void interpreter::cleanup_tmp_files (void) - { - m_tmp_files.cleanup (); - } +void interpreter::quit (int exit_status, bool force, bool confirm) +{ + if (! force) + { + try + { + bool cancel = false; - void interpreter::quit (int exit_status, bool force, bool confirm) - { - if (! force) - { - try - { - bool cancel = false; + if (symbol_exist ("finish.m", "file")) + { + unwind_protect_var upv1 (m_executing_finish_script, true); + unwind_protect_var upv2 (m_cancel_quit); + + evalin ("base", "finish", 0); - if (symbol_exist ("finish.m", "file")) - { - unwind_protect_var upv1 (m_executing_finish_script, true); - unwind_protect_var upv2 (m_cancel_quit); + cancel = m_cancel_quit; + } - evalin ("base", "finish", 0); + if (cancel) + return; - cancel = m_cancel_quit; - } - - if (cancel) - return; + // Check for confirmation. - // Check for confirmation. + if (confirm && ! m_event_manager.confirm_shutdown ()) + return; + } + catch (const execution_exception&) + { + // Catch execution_exceptions so we don't throw an + // exit_exception if there is an in finish.m. But throw it + // again so that will be handled as any other + // execution_exception by the evaluator. This way, errors + // will be ignored properly and we won't exit if quit is + // called recursively from finish.m. - if (confirm && ! m_event_manager.confirm_shutdown ()) - return; - } - catch (const execution_exception&) - { - // Catch execution_exceptions so we don't throw an - // exit_exception if there is an in finish.m. But throw it - // again so that will be handled as any other - // execution_exception by the evaluator. This way, errors - // will be ignored properly and we won't exit if quit is - // called recursively from finish.m. + throw; + } + } - throw; - } - } + throw exit_exception (exit_status); +} - throw exit_exception (exit_status); - } +void interpreter::add_atexit_fcn (const std::string& fname) +{ + if (m_executing_atexit) + return; - void interpreter::add_atexit_fcn (const std::string& fname) - { - if (m_executing_atexit) - return; + m_atexit_fcns.push_front (fname); +} - m_atexit_fcns.push_front (fname); - } - - bool interpreter::remove_atexit_fcn (const std::string& fname) - { - bool found = false; +bool interpreter::remove_atexit_fcn (const std::string& fname) +{ + bool found = false; - for (auto it = m_atexit_fcns.begin (); - it != m_atexit_fcns.end (); it++) - { - if (*it == fname) - { - m_atexit_fcns.erase (it); - found = true; - break; - } - } + for (auto it = m_atexit_fcns.begin (); + it != m_atexit_fcns.end (); it++) + { + if (*it == fname) + { + m_atexit_fcns.erase (it); + found = true; + break; + } + } + + return found; +} - return found; - } +// What internal options get configured by --traditional. - // What internal options get configured by --traditional. +void interpreter::maximum_braindamage (void) +{ + m_input_system.PS1 (">> "); + m_input_system.PS2 (""); - void interpreter::maximum_braindamage (void) - { - m_input_system.PS1 (">> "); - m_input_system.PS2 (""); + m_evaluator.PS4 (""); - m_evaluator.PS4 (""); + m_load_save_system.crash_dumps_octave_core (false); + m_load_save_system.save_default_options ("-mat-binary"); + + m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%"); - m_load_save_system.crash_dumps_octave_core (false); - m_load_save_system.save_default_options ("-mat-binary"); - - m_history_system.timestamp_format_string ("%%-- %D %I:%M %p --%%"); - - m_error_system.beep_on_error (true); + m_error_system.beep_on_error (true); - Fconfirm_recursive_rmdir (octave_value (false)); - Foptimize_diagonal_matrix (octave_value (false)); - Foptimize_permutation_matrix (octave_value (false)); - Foptimize_range (octave_value (false)); - Ffixed_point_format (octave_value (true)); - Fprint_empty_dimensions (octave_value (false)); - Fprint_struct_array_contents (octave_value (true)); - Fstruct_levels_to_print (octave_value (0)); + Fconfirm_recursive_rmdir (octave_value (false)); + Foptimize_diagonal_matrix (octave_value (false)); + Foptimize_permutation_matrix (octave_value (false)); + Foptimize_range (octave_value (false)); + Ffixed_point_format (octave_value (true)); + Fprint_empty_dimensions (octave_value (false)); + Fprint_struct_array_contents (octave_value (true)); + Fstruct_levels_to_print (octave_value (0)); - m_error_system.disable_warning ("Octave:abbreviated-property-match"); - m_error_system.disable_warning ("Octave:colon-nonscalar-argument"); - m_error_system.disable_warning ("Octave:data-file-in-path"); - m_error_system.disable_warning ("Octave:empty-index"); - m_error_system.disable_warning ("Octave:function-name-clash"); - m_error_system.disable_warning ("Octave:possible-matlab-short-circuit-operator"); - } + m_error_system.disable_warning ("Octave:abbreviated-property-match"); + m_error_system.disable_warning ("Octave:colon-nonscalar-argument"); + m_error_system.disable_warning ("Octave:data-file-in-path"); + m_error_system.disable_warning ("Octave:empty-index"); + m_error_system.disable_warning ("Octave:function-name-clash"); + m_error_system.disable_warning ("Octave:possible-matlab-short-circuit-operator"); +} - void interpreter::execute_pkg_add (const std::string& dir) - { - try - { - m_load_path.execute_pkg_add (dir); - } - catch (const interrupt_exception&) - { - recover_from_exception (); - } - catch (const execution_exception& ee) - { - handle_exception (ee); - } - } +void interpreter::execute_pkg_add (const std::string& dir) +{ + try + { + m_load_path.execute_pkg_add (dir); + } + catch (const interrupt_exception&) + { + recover_from_exception (); + } + catch (const execution_exception& ee) + { + handle_exception (ee); + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/interpreter.h --- a/libinterp/corefcn/interpreter.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/interpreter.h Thu Dec 01 20:05:44 2022 -0800 @@ -72,581 +72,581 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class profiler; - class child_list; - class push_parser; +class profiler; +class child_list; +class push_parser; - // The time we last time we changed directories. - extern sys::time Vlast_chdir_time; +// The time we last time we changed directories. +extern sys::time Vlast_chdir_time; - // The application object contains a pointer to the current - // interpreter and the interpreter contains a pointer back to the - // application context so we need a forward declaration for one (or - // both) of them... +// The application object contains a pointer to the current +// interpreter and the interpreter contains a pointer back to the +// application context so we need a forward declaration for one (or +// both) of them... - class application; +class application; + +class temporary_file_list +{ +public: - class temporary_file_list - { - public: + temporary_file_list (void) : m_files () { } + + // No copying! - temporary_file_list (void) : m_files () { } + temporary_file_list (const temporary_file_list&) = delete; - // No copying! - - temporary_file_list (const temporary_file_list&) = delete; + temporary_file_list& operator = (const temporary_file_list&) = delete; - temporary_file_list& operator = (const temporary_file_list&) = delete; + ~temporary_file_list (void); - ~temporary_file_list (void); + void insert (const std::string& file); - void insert (const std::string& file); + void cleanup (void); - void cleanup (void); +private: - private: + // List of temporary files to delete when we exit. + std::set m_files; - // List of temporary files to delete when we exit. - std::set m_files; +}; - }; +class OCTINTERP_API interpreter +{ +public: - class OCTINTERP_API interpreter - { - public: + // Create an interpreter object and perform basic initialization. - // Create an interpreter object and perform basic initialization. + interpreter (application *app_context = nullptr); - interpreter (application *app_context = nullptr); + // No copying, at least not yet... - // No copying, at least not yet... + interpreter (const interpreter&) = delete; - interpreter (const interpreter&) = delete; + interpreter& operator = (const interpreter&) = delete; - interpreter& operator = (const interpreter&) = delete; + // Clean up the interpreter object. - // Clean up the interpreter object. + ~interpreter (void); - ~interpreter (void); + void intern_nargin (octave_idx_type nargs); - void intern_nargin (octave_idx_type nargs); + // If creating an embedded interpreter, you may inhibit reading + // the command history file by calling initialize_history with + // read_history_file = false prior to calling initialize. - // If creating an embedded interpreter, you may inhibit reading - // the command history file by calling initialize_history with - // read_history_file = false prior to calling initialize. + void initialize_history (bool read_history_file = false); - void initialize_history (bool read_history_file = false); + // If creating an embedded interpreter, you may inhibit setting + // the default compiled-in path by calling initialize_load_path + // with set_initial_path = false prior calling initialize. After + // that, you can add directories to the load path to set up a + // custom path. - // If creating an embedded interpreter, you may inhibit setting - // the default compiled-in path by calling initialize_load_path - // with set_initial_path = false prior calling initialize. After - // that, you can add directories to the load path to set up a - // custom path. + void initialize_load_path (bool set_initial_path = true); - void initialize_load_path (bool set_initial_path = true); + // Load command line history, set the load path. - // Load command line history, set the load path. + void initialize (void); - void initialize (void); + // Note: GET_LINE_AND_EVAL is only used by new experimental terminal + // widget. - // Note: GET_LINE_AND_EVAL is only used by new experimental terminal - // widget. + void get_line_and_eval (void); - void get_line_and_eval (void); + // Parse a line of input. If input ends at a complete statement + // boundary, execute the resulting parse tree. Useful to handle + // parsing user input when running in server mode. - // Parse a line of input. If input ends at a complete statement - // boundary, execute the resulting parse tree. Useful to handle - // parsing user input when running in server mode. + void parse_and_execute (const std::string& input, bool& incomplete_parse); - void parse_and_execute (const std::string& input, bool& incomplete_parse); + // Initialize the interpreter (if not already done by an explicit + // call to initialize), execute startup files, --eval option code, + // script files, and/or interactive commands. - // Initialize the interpreter (if not already done by an explicit - // call to initialize), execute startup files, --eval option code, - // script files, and/or interactive commands. + int execute (void); + + bool server_mode (void) const { return m_evaluator.server_mode (); } - int execute (void); - - bool server_mode (void) const { return m_evaluator.server_mode (); } + bool interactive (void) const + { + return m_interactive; + } - bool interactive (void) const - { - return m_interactive; - } + void interactive (bool arg) + { + m_interactive = arg; + } - void interactive (bool arg) - { - m_interactive = arg; - } + void read_site_files (bool flag) + { + m_read_site_files = flag; + } - void read_site_files (bool flag) - { - m_read_site_files = flag; - } + void read_init_files (bool flag) + { + m_read_init_files = flag; + } - void read_init_files (bool flag) - { - m_read_init_files = flag; - } + void verbose (bool flag) + { + m_verbose = flag; + } - void verbose (bool flag) - { - m_verbose = flag; - } + void traditional (bool flag) + { + m_traditional = flag; + } - void traditional (bool flag) - { - m_traditional = flag; - } + bool traditional (void) const + { + return m_traditional; + } - bool traditional (void) const - { - return m_traditional; - } + void inhibit_startup_message (bool flag) + { + m_inhibit_startup_message = flag; + } - void inhibit_startup_message (bool flag) - { - m_inhibit_startup_message = flag; - } + bool in_top_level_repl (void) const + { + return m_evaluator.in_top_level_repl (); + } - bool in_top_level_repl (void) const - { - return m_evaluator.in_top_level_repl (); - } + bool initialized (void) const + { + return m_initialized; + } - bool initialized (void) const - { - return m_initialized; - } + void interrupt_all_in_process_group (bool b) + { + m_interrupt_all_in_process_group = b; + } - void interrupt_all_in_process_group (bool b) - { - m_interrupt_all_in_process_group = b; - } + bool interrupt_all_in_process_group (void) const + { + return m_interrupt_all_in_process_group; + } - bool interrupt_all_in_process_group (void) const - { - return m_interrupt_all_in_process_group; - } + application * get_app_context (void) + { + return m_app_context; + } - application *get_app_context (void) - { - return m_app_context; - } + display_info& get_display_info (void) + { + return m_display_info; + } - display_info& get_display_info (void) - { - return m_display_info; - } - - environment& get_environment (void) - { - return m_environment; - } + environment& get_environment (void) + { + return m_environment; + } - settings& get_settings (void) - { - return m_settings; - } + settings& get_settings (void) + { + return m_settings; + } - error_system& get_error_system (void) - { - return m_error_system; - } + error_system& get_error_system (void) + { + return m_error_system; + } + + tree_evaluator& get_evaluator (void); - tree_evaluator& get_evaluator (void); + help_system& get_help_system (void) + { + return m_help_system; + } - help_system& get_help_system (void) - { - return m_help_system; - } + input_system& get_input_system (void) + { + return m_input_system; + } - input_system& get_input_system (void) - { - return m_input_system; - } + output_system& get_output_system (void) + { + return m_output_system; + } - output_system& get_output_system (void) - { - return m_output_system; - } + history_system& get_history_system (void) + { + return m_history_system; + } - history_system& get_history_system (void) - { - return m_history_system; - } + dynamic_loader& get_dynamic_loader (void) + { + return m_dynamic_loader; + } - dynamic_loader& get_dynamic_loader (void) - { - return m_dynamic_loader; - } + load_path& get_load_path (void) + { + return m_load_path; + } - load_path& get_load_path (void) - { - return m_load_path; - } + load_save_system& get_load_save_system (void) + { + return m_load_save_system; + } - load_save_system& get_load_save_system (void) - { - return m_load_save_system; - } + type_info& get_type_info (void) + { + return m_type_info; + } - type_info& get_type_info (void) - { - return m_type_info; - } + symbol_table& get_symbol_table (void) + { + return m_symbol_table; + } + + symbol_scope get_top_scope (void) const; + symbol_scope get_current_scope (void) const; + symbol_scope require_current_scope (const std::string& who) const; - symbol_table& get_symbol_table (void) - { - return m_symbol_table; - } + profiler& get_profiler (void); + + stream_list& get_stream_list (void); - symbol_scope get_top_scope (void) const; - symbol_scope get_current_scope (void) const; - symbol_scope require_current_scope (const std::string& who) const; + child_list& get_child_list (void) + { + return m_child_list; + } - profiler& get_profiler (void); + url_handle_manager& get_url_handle_manager (void); - stream_list& get_stream_list (void); + cdef_manager& get_cdef_manager (void) + { + return m_cdef_manager; + } - child_list& get_child_list (void) - { - return m_child_list; - } - - url_handle_manager& get_url_handle_manager (void); + gtk_manager& get_gtk_manager (void) + { + return m_gtk_manager; + } - cdef_manager& get_cdef_manager (void) - { - return m_cdef_manager; - } + event_manager& get_event_manager (void) + { + return m_event_manager; + } - gtk_manager& get_gtk_manager (void) - { - return m_gtk_manager; - } + gh_manager& get_gh_manager (void) + { + return *m_gh_manager; + } - event_manager& get_event_manager (void) - { - return m_event_manager; - } + // Any Octave code that needs to change the current directory should + // call this function instead of calling the system chdir function + // directly so that the load-path and GUI may be notified of the + // change. - gh_manager& get_gh_manager (void) - { - return *m_gh_manager; - } + int chdir (const std::string& dir); - // Any Octave code that needs to change the current directory should - // call this function instead of calling the system chdir function - // directly so that the load-path and GUI may be notified of the - // change. + void mlock (bool skip_first = false) const; + void munlock (bool skip_first = false) const; + bool mislocked (bool skip_first = false) const; - int chdir (const std::string& dir); + // NOTE: since we have a version that accepts a bool argument, we + // can't rely on automatic conversion from char* to std::string. + void munlock (const char *nm); + void munlock (const std::string& nm); - void mlock (bool skip_first = false) const; - void munlock (bool skip_first = false) const; - bool mislocked (bool skip_first = false) const; + bool mislocked (const char *nm); + bool mislocked (const std::string& nm); - // NOTE: since we have a version that accepts a bool argument, we - // can't rely on automatic conversion from char* to std::string. - void munlock (const char *nm); - void munlock (const std::string& nm); + std::string mfilename (const std::string& opt = "") const; + + octave_value_list eval_string (const std::string& eval_str, bool silent, + int& parse_status, int nargout); - bool mislocked (const char *nm); - bool mislocked (const std::string& nm); + octave_value eval_string (const std::string& eval_str, bool silent, + int& parse_status); - std::string mfilename (const std::string& opt = "") const; + octave_value_list eval_string (const octave_value& arg, bool silent, + int& parse_status, int nargout); - octave_value_list eval_string (const std::string& eval_str, bool silent, - int& parse_status, int nargout); + octave_value_list eval (const std::string& try_code, int nargout); - octave_value eval_string (const std::string& eval_str, bool silent, - int& parse_status); + octave_value_list eval (const std::string& try_code, + const std::string& catch_code, int nargout); - octave_value_list eval_string (const octave_value& arg, bool silent, - int& parse_status, int nargout); + octave_value_list evalin (const std::string& context, + const std::string& try_code, int nargout); - octave_value_list eval (const std::string& try_code, int nargout); - - octave_value_list eval (const std::string& try_code, + octave_value_list evalin (const std::string& context, + const std::string& try_code, const std::string& catch_code, int nargout); - octave_value_list evalin (const std::string& context, - const std::string& try_code, int nargout); + octave_value_list + feval (const char *name, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - octave_value_list evalin (const std::string& context, - const std::string& try_code, - const std::string& catch_code, int nargout); - - octave_value_list - feval (const char *name, - const octave_value_list& args = octave_value_list (), - int nargout = 0); + octave_value_list + feval (const std::string& name, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - octave_value_list - feval (const std::string& name, - const octave_value_list& args = octave_value_list (), - int nargout = 0); + octave_value_list + feval (octave_function *fcn, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - octave_value_list - feval (octave_function *fcn, - const octave_value_list& args = octave_value_list (), - int nargout = 0); + octave_value_list + feval (const octave_value& f_arg, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - octave_value_list - feval (const octave_value& f_arg, - const octave_value_list& args = octave_value_list (), - int nargout = 0); + octave_value_list feval (const octave_value_list& args, int nargout = 0); + + octave_value make_function_handle (const std::string& name); - octave_value_list feval (const octave_value_list& args, int nargout = 0); + void install_variable (const std::string& name, const octave_value& value, + bool global); - octave_value make_function_handle (const std::string& name); + void set_global_value (const std::string& name, const octave_value& value); - void install_variable (const std::string& name, const octave_value& value, - bool global); + octave_value global_varval (const std::string& name) const; - void set_global_value (const std::string& name, const octave_value& value); + void global_assign (const std::string& name, + const octave_value& val = octave_value ()); - octave_value global_varval (const std::string& name) const; + octave_value top_level_varval (const std::string& name) const; - void global_assign (const std::string& name, - const octave_value& val = octave_value ()); + void top_level_assign (const std::string& name, + const octave_value& val = octave_value ()); - octave_value top_level_varval (const std::string& name) const; + bool is_variable (const std::string& name) const; - void top_level_assign (const std::string& name, - const octave_value& val = octave_value ()); + bool is_local_variable (const std::string& name) const; - bool is_variable (const std::string& name) const; - - bool is_local_variable (const std::string& name) const; + octave_value varval (const std::string& name) const; - octave_value varval (const std::string& name) const; + void assign (const std::string& name, + const octave_value& val = octave_value ()); - void assign (const std::string& name, + void assignin (const std::string& context, const std::string& varname, const octave_value& val = octave_value ()); - void assignin (const std::string& context, const std::string& varname, - const octave_value& val = octave_value ()); + void source_file (const std::string& file_name, + const std::string& context = "", + bool verbose = false, bool require_file = true); + + bool at_top_level (void) const; - void source_file (const std::string& file_name, - const std::string& context = "", - bool verbose = false, bool require_file = true); + bool isglobal (const std::string& name) const; - bool at_top_level (void) const; + octave_value find (const std::string& name); - bool isglobal (const std::string& name) const; - - octave_value find (const std::string& name); + void clear_all (bool force = false); - void clear_all (bool force = false); + void clear_objects (void); - void clear_objects (void); + void clear_variable (const std::string& name); - void clear_variable (const std::string& name); + void clear_variable_pattern (const std::string& pattern); - void clear_variable_pattern (const std::string& pattern); + void clear_variable_regexp (const std::string& pattern); - void clear_variable_regexp (const std::string& pattern); + void clear_variables (void); - void clear_variables (void); + void clear_global_variable (const std::string& name); - void clear_global_variable (const std::string& name); + void clear_global_variable_pattern (const std::string& pattern); - void clear_global_variable_pattern (const std::string& pattern); + void clear_global_variable_regexp (const std::string& pattern); - void clear_global_variable_regexp (const std::string& pattern); + void clear_global_variables (void); - void clear_global_variables (void); + void clear_functions (bool force = false); - void clear_functions (bool force = false); + void clear_function (const std::string& name); - void clear_function (const std::string& name); + void clear_symbol (const std::string& name); - void clear_symbol (const std::string& name); + void clear_function_pattern (const std::string& pat); - void clear_function_pattern (const std::string& pat); + void clear_function_regexp (const std::string& pat); - void clear_function_regexp (const std::string& pat); + void clear_symbol_pattern (const std::string& pat); - void clear_symbol_pattern (const std::string& pat); + void clear_symbol_regexp (const std::string& pat); - void clear_symbol_regexp (const std::string& pat); + std::list variable_names (void); - std::list variable_names (void); + std::list top_level_variable_names (void); - std::list top_level_variable_names (void); + std::list global_variable_names (void); - std::list global_variable_names (void); + std::list user_function_names (void); - std::list user_function_names (void); + std::list autoloaded_functions (void) const; - std::list autoloaded_functions (void) const; - - void interrupt (void); + void interrupt (void); - // Pause interpreter execution at the next available statement and - // enter the debugger. - void pause (void); + // Pause interpreter execution at the next available statement and + // enter the debugger. + void pause (void); - // Exit debugger or stop execution and return to the top-level REPL - // or server loop. - void stop (void); + // Exit debugger or stop execution and return to the top-level REPL + // or server loop. + void stop (void); - // Add EXPR to the set of expressions that may be evaluated when the - // debugger stops at a breakpoint. - void add_debug_watch_expression (const std::string& expr); + // Add EXPR to the set of expressions that may be evaluated when the + // debugger stops at a breakpoint. + void add_debug_watch_expression (const std::string& expr); - // Remove EXPR from the set of expressions that may be evaluated - // when the debugger stops at a breakpoint. - void remove_debug_watch_expression (const std::string& expr); + // Remove EXPR from the set of expressions that may be evaluated + // when the debugger stops at a breakpoint. + void remove_debug_watch_expression (const std::string& expr); - // Clear the set of expressions that may be evaluated when the - // debugger stops at a breakpoint. - void clear_debug_watch_expressions (void); + // Clear the set of expressions that may be evaluated when the + // debugger stops at a breakpoint. + void clear_debug_watch_expressions (void); - // Return the set of expressions that may be evaluated when the - // debugger stops at a breakpoint. - std::set debug_watch_expressions (void) const; + // Return the set of expressions that may be evaluated when the + // debugger stops at a breakpoint. + std::set debug_watch_expressions (void) const; - // Resume interpreter execution if paused. - void resume (void); + // Resume interpreter execution if paused. + void resume (void); + + // Provided for convenience. Will be removed once we eliminate the + // old terminal widget. + bool experimental_terminal_widget (void) const; - // Provided for convenience. Will be removed once we eliminate the - // old terminal widget. - bool experimental_terminal_widget (void) const; + void handle_exception (const execution_exception& ee); + + void recover_from_exception (void); - void handle_exception (const execution_exception& ee); + void mark_for_deletion (const std::string& file); - void recover_from_exception (void); - - void mark_for_deletion (const std::string& file); + void cleanup_tmp_files (void); - void cleanup_tmp_files (void); + void quit (int exit_status, bool force = false, bool confirm = true); - void quit (int exit_status, bool force = false, bool confirm = true); - - void cancel_quit (bool flag) { m_cancel_quit = flag; } + void cancel_quit (bool flag) { m_cancel_quit = flag; } - bool executing_finish_script (void) const - { - return m_executing_finish_script; - } + bool executing_finish_script (void) const + { + return m_executing_finish_script; + } - void add_atexit_fcn (const std::string& fname); + void add_atexit_fcn (const std::string& fname); - bool remove_atexit_fcn (const std::string& fname); + bool remove_atexit_fcn (const std::string& fname); + + static interpreter * the_interpreter (void) { return m_instance; } - static interpreter * the_interpreter (void) { return m_instance; } +private: - private: + void display_startup_message (void) const; - void display_startup_message (void) const; + int execute_startup_files (void); - int execute_startup_files (void); + int execute_eval_option_code (void); - int execute_eval_option_code (void); + int execute_command_line_file (void); - int execute_command_line_file (void); + int main_loop (void); - int main_loop (void); + int server_loop (void); - int server_loop (void); + void shutdown (void); - void shutdown (void); + void execute_atexit_fcns (void); - void execute_atexit_fcns (void); - - void maximum_braindamage (void); + void maximum_braindamage (void); - void execute_pkg_add (const std::string& dir); + void execute_pkg_add (const std::string& dir); - //-------- + //-------- - // The interpreter instance; Currently it is only possible to - // have one, so OCTAVE_THREAD_LOCAL will normally be defined to be - // empty. Eventually we would like to allow multiple interpreters - // to be active at once, but they will still be limited to one per - // thread. When that is possible, OCTAVE_THREAD_LOCAL can be - // replaced by the C++ thread_local keyword. For now, use a macro - // to allow experimenting with thread_local storage. + // The interpreter instance; Currently it is only possible to + // have one, so OCTAVE_THREAD_LOCAL will normally be defined to be + // empty. Eventually we would like to allow multiple interpreters + // to be active at once, but they will still be limited to one per + // thread. When that is possible, OCTAVE_THREAD_LOCAL can be + // replaced by the C++ thread_local keyword. For now, use a macro + // to allow experimenting with thread_local storage. - OCTAVE_THREAD_LOCAL static interpreter *m_instance; + OCTAVE_THREAD_LOCAL static interpreter *m_instance; - application *m_app_context; + application *m_app_context; - temporary_file_list m_tmp_files; + temporary_file_list m_tmp_files; - std::list m_atexit_fcns; + std::list m_atexit_fcns; - display_info m_display_info; + display_info m_display_info; - environment m_environment; + environment m_environment; - settings m_settings; + settings m_settings; - error_system m_error_system; + error_system m_error_system; - tree_evaluator m_evaluator; + tree_evaluator m_evaluator; - help_system m_help_system; + help_system m_help_system; - input_system m_input_system; + input_system m_input_system; - output_system m_output_system; + output_system m_output_system; - history_system m_history_system; + history_system m_history_system; - dynamic_loader m_dynamic_loader; + dynamic_loader m_dynamic_loader; - load_path m_load_path; + load_path m_load_path; - load_save_system m_load_save_system; + load_save_system m_load_save_system; - type_info m_type_info; + type_info m_type_info; - symbol_table m_symbol_table; + symbol_table m_symbol_table; - stream_list m_stream_list; + stream_list m_stream_list; - child_list m_child_list; + child_list m_child_list; - url_handle_manager m_url_handle_manager; + url_handle_manager m_url_handle_manager; - cdef_manager m_cdef_manager; + cdef_manager m_cdef_manager; - gtk_manager m_gtk_manager; + gtk_manager m_gtk_manager; - event_manager m_event_manager; + event_manager m_event_manager; - gh_manager *m_gh_manager; + gh_manager *m_gh_manager; - // TRUE means this is an interactive interpreter (forced or not). - bool m_interactive; + // TRUE means this is an interactive interpreter (forced or not). + bool m_interactive; - bool m_read_site_files; + bool m_read_site_files; - bool m_read_init_files; + bool m_read_init_files; - bool m_verbose; + bool m_verbose; - bool m_traditional; + bool m_traditional; - bool m_inhibit_startup_message; + bool m_inhibit_startup_message; - bool m_load_path_initialized; + bool m_load_path_initialized; - bool m_history_initialized; + bool m_history_initialized; - bool m_interrupt_all_in_process_group; + bool m_interrupt_all_in_process_group; - bool m_cancel_quit; + bool m_cancel_quit; - bool m_executing_finish_script; + bool m_executing_finish_script; - bool m_executing_atexit; + bool m_executing_atexit; - bool m_initialized; - }; + bool m_initialized; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/inv.cc --- a/libinterp/corefcn/inv.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/inv.cc Thu Dec 01 20:05:44 2022 -0800 @@ -232,10 +232,10 @@ %! assert (isa (rcond, "double")); %!assert (inv (single ([1, 2; 3, 4])), single ([-2, 1; 1.5, -0.5]), -%! 5*eps ("single")) +%! 5* eps ("single")) %!test %! [xinv, rcond] = inv (single ([1,2;3,4])); -%! assert (xinv, single ([-2, 1; 1.5, -0.5]), 5*eps ("single")); +%! assert (xinv, single ([-2, 1; 1.5, -0.5]), 5* eps ("single")); %! assert (isa (rcond, "single")); ## Basic test for integer inputs diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/jsondecode.cc --- a/libinterp/corefcn/jsondecode.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/jsondecode.cc Thu Dec 01 20:05:44 2022 -0800 @@ -134,7 +134,7 @@ octave_idx_type index = 0; for (const auto& elem : val.GetArray ()) retval(index++) = elem.IsNull () ? octave_NaN - : decode_number (elem).double_value (); + : decode_number (elem).double_value (); return retval; } @@ -250,7 +250,7 @@ { for (octave_idx_type k = 0; k < struct_cell.numel (); ++k) value(k) = struct_cell(k).scalar_map_value () - .getfield (field_names(i)); + .getfield (field_names(i)); struct_array.assign (field_names(i), value); } } @@ -299,7 +299,7 @@ bool is_bool = cell(0).is_bool_matrix (); bool is_struct = cell(0).isstruct (); string_vector field_names = is_struct ? cell(0).map_value ().fieldnames () - : string_vector (); + : string_vector (); dim_vector sub_array_dims = cell(0).dims (); octave_idx_type sub_array_ndims = cell(0).ndims (); octave_idx_type cell_numel = cell.numel (); @@ -349,7 +349,7 @@ for (octave_idx_type k = 0; k < cell_numel; ++k) { Cell sub_array_value = cell(k).map_value () - .getfield (field_names(j)); + .getfield (field_names(j)); for (octave_idx_type i = 0; i < sub_array_numel; ++i) value(k + i * cell_numel) = sub_array_value(i); } @@ -421,8 +421,8 @@ // RapidJSON doesn't have kBoolean Type it has kTrueType and kFalseType if (! ((current_elem_type == rapidjson::kTrueType && array_type == rapidjson::kFalseType) - || (current_elem_type == rapidjson::kFalseType - && array_type == rapidjson::kTrueType))) + || (current_elem_type == rapidjson::kFalseType + && array_type == rapidjson::kTrueType))) same_type = false; } @@ -610,7 +610,7 @@ make_valid_name_options *options = use_makeValidName ? new make_valid_name_options (make_valid_name_params) - : nullptr; + : nullptr; unwind_action del_opts ([options] (void) { if (options) delete options; }); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/jsonencode.cc --- a/libinterp/corefcn/jsonencode.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/jsonencode.cc Thu Dec 01 20:05:44 2022 -0800 @@ -418,10 +418,10 @@ // "Octave:classdef-to-struct" warning and re-enable it. { octave::unwind_action restore_warning_state - ([] (const octave_value_list& old_warning_state) - { - octave::set_warning_state (old_warning_state); - }, octave::set_warning_state ("Octave:classdef-to-struct", "off")); + ([] (const octave_value_list& old_warning_state) + { + octave::set_warning_state (old_warning_state); + }, octave::set_warning_state ("Octave:classdef-to-struct", "off")); encode_struct (writer, obj.scalar_map_value ().getfield ("map"), ConvertInfAndNaN); @@ -429,10 +429,10 @@ else if (obj.isobject ()) { octave::unwind_action restore_warning_state - ([] (const octave_value_list& old_warning_state) - { - octave::set_warning_state (old_warning_state); - }, octave::set_warning_state ("Octave:classdef-to-struct", "off")); + ([] (const octave_value_list& old_warning_state) + { + octave::set_warning_state (old_warning_state); + }, octave::set_warning_state ("Octave:classdef-to-struct", "off")); encode_struct (writer, obj.scalar_map_value (), ConvertInfAndNaN); } @@ -625,8 +625,8 @@ { # if defined (HAVE_RAPIDJSON_PRETTYWRITER) rapidjson::PrettyWriter, - rapidjson::UTF8<>, rapidjson::CrtAllocator, - rapidjson::kWriteNanAndInfFlag> writer (json); + rapidjson::UTF8<>, rapidjson::CrtAllocator, + rapidjson::kWriteNanAndInfFlag> writer (json); writer.SetIndent (' ', 2); encode (writer, args(0), ConvertInfAndNaN); # endif @@ -634,8 +634,8 @@ else { rapidjson::Writer, - rapidjson::UTF8<>, rapidjson::CrtAllocator, - rapidjson::kWriteNanAndInfFlag> writer (json); + rapidjson::UTF8<>, rapidjson::CrtAllocator, + rapidjson::kWriteNanAndInfFlag> writer (json); encode (writer, args(0), ConvertInfAndNaN); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/latex-text-renderer.cc --- a/libinterp/corefcn/latex-text-renderer.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/latex-text-renderer.cc Thu Dec 01 20:05:44 2022 -0800 @@ -43,490 +43,490 @@ OCTAVE_BEGIN_NAMESPACE(octave) - std::string - quote_string (std::string str) +std::string +quote_string (std::string str) +{ + return ('"' + str + '"'); +} + +class +OCTINTERP_API +latex_renderer : public base_text_renderer +{ + +public: + + latex_renderer (void) + : m_fontsize (10.0), m_fontname ("cmr"), m_tmp_dir (), + m_color (dim_vector (1, 3), 0), m_latex_binary ("latex"), + m_dvipng_binary ("dvipng"), m_dvisvg_binary ("dvisvgm"), + m_debug (false), m_testing (true) { - return ('"' + str + '"'); + std::string bin = sys::env::getenv ("OCTAVE_LATEX_BINARY"); + if (! bin.empty ()) + m_latex_binary = quote_string (bin); + + bin = sys::env::getenv ("OCTAVE_DVIPNG_BINARY"); + if (! bin.empty ()) + m_dvipng_binary = quote_string (bin); + + bin = sys::env::getenv ("OCTAVE_DVISVG_BINARY"); + if (! bin.empty ()) + m_dvisvg_binary = quote_string (bin); + + m_debug = ! sys::env::getenv ("OCTAVE_LATEX_DEBUG_FLAG").empty (); + } + + ~latex_renderer (void) + { + if (! m_tmp_dir.empty () && ! m_debug) + sys::recursive_rmdir (m_tmp_dir); } - class - OCTINTERP_API - latex_renderer : public base_text_renderer + void set_font (const std::string& /*name*/, const std::string& /*weight*/, + const std::string& /*angle*/, double size) { - - public: - - latex_renderer (void) - : m_fontsize (10.0), m_fontname ("cmr"), m_tmp_dir (), - m_color (dim_vector (1, 3), 0), m_latex_binary ("latex"), - m_dvipng_binary ("dvipng"), m_dvisvg_binary ("dvisvgm"), - m_debug (false), m_testing (true) - { - std::string bin = sys::env::getenv ("OCTAVE_LATEX_BINARY"); - if (! bin.empty ()) - m_latex_binary = quote_string (bin); - - bin = sys::env::getenv ("OCTAVE_DVIPNG_BINARY"); - if (! bin.empty ()) - m_dvipng_binary = quote_string (bin); - - bin = sys::env::getenv ("OCTAVE_DVISVG_BINARY"); - if (! bin.empty ()) - m_dvisvg_binary = quote_string (bin); - - m_debug = ! sys::env::getenv ("OCTAVE_LATEX_DEBUG_FLAG").empty (); - } - - ~latex_renderer (void) - { - if (! m_tmp_dir.empty () && ! m_debug) - sys::recursive_rmdir (m_tmp_dir); - } - - void set_font (const std::string& /*name*/, const std::string& /*weight*/, - const std::string& /*angle*/, double size) - { - m_fontsize = size; - } - - void set_color (const Matrix& c) - { - if (c.numel () == 3) - { - m_color(0) = static_cast (c (0) * 255); - m_color(1) = static_cast (c (1) * 255); - m_color(2) = static_cast (c (2) * 255); - } - } - - Matrix get_extent (text_element* /*elt*/, double /*rotation*/) - { - return Matrix (1, 2, 0.0); - } - - Matrix get_extent (const std::string& txt, double rotation, - const caseless_str& interpreter) - { - Matrix bbox; - uint8NDArray pixels; - - text_to_pixels (txt, pixels, bbox, 0, 0, rotation, interpreter, false); - - return bbox.extract_n (0, 2, 1, 2); - } - - void text_to_strlist (const std::string& txt, - std::list& lst, - Matrix& bbox, int halign, int valign, double rotation, - const caseless_str& interp) - { - uint8NDArray pixels; - text_to_pixels (txt, pixels, bbox, halign, valign, rotation, - interp, false); - - text_renderer::font fnt; - text_renderer::string str ("", fnt, 0.0, 0.0); - str.set_color (m_color); + m_fontsize = size; + } - gh_manager& gh_mgr = octave::__get_gh_manager__ (); - - gh_manager::latex_data ldata = gh_mgr.get_latex_data (key (txt, halign)); - - str.set_svg_element (ldata.second); - - lst.push_back (str); - } - - void text_to_pixels (const std::string& txt, uint8NDArray& pxls, - Matrix& bbox, int halign, int valign, double rotation, - const caseless_str& interpreter, - bool handle_rotation); - - void set_anti_aliasing (bool /*val*/) { } - - octave_map get_system_fonts (void) { return octave_map (); } - - bool ok (void); - - private: - - std::string key (const std::string& txt, int halign) - { - return (txt + ":" - + std::to_string (m_fontsize) + ":" - + std::to_string (halign) + ":" - + std::to_string (m_color(0)) + ":" - + std::to_string (m_color(1)) + ":" - + std::to_string (m_color(2))); - } - - void warn_helper (std::string caller, std::string txt, std::string cmd, - process_execution_result result); - - uint8NDArray render (const std::string& txt, int halign = 0); - - bool read_image (const std::string& png_file, uint8NDArray& data) const; + void set_color (const Matrix& c) + { + if (c.numel () == 3) + { + m_color(0) = static_cast (c (0) * 255); + m_color(1) = static_cast (c (1) * 255); + m_color(2) = static_cast (c (2) * 255); + } + } - std::string write_tex_file (const std::string& txt, int halign); - - private: - double m_fontsize; - std::string m_fontname; - std::string m_tmp_dir; - uint8NDArray m_color; - std::string m_latex_binary; - std::string m_dvipng_binary; - std::string m_dvisvg_binary; - bool m_debug; - bool m_testing; - - }; - - bool - latex_renderer::ok (void) + Matrix get_extent (text_element * /*elt*/, double /*rotation*/) { - // Only run the test once in a session - static bool tested = false; - - static bool isok = false; - - if (! tested) - { - tested = true; - - // For testing, render a questoin mark - uint8NDArray pixels = render ("?"); - - if (! pixels.isempty ()) - isok = true; - else - warning_with_id ("Octave:LaTeX:internal-error", - "latex_renderer: a run-time test failed and the 'latex' interpreter has been disabled."); - } - - m_testing = false; - - return isok; + return Matrix (1, 2, 0.0); } - std::string - latex_renderer::write_tex_file (const std::string& txt, int halign) + Matrix get_extent (const std::string& txt, double rotation, + const caseless_str& interpreter) { - if (m_tmp_dir.empty ()) - { - //Create the temporary directory -#if defined (OCTAVE_USE_WINDOWS_API) - static std::string base_tmp_dir; - - if (base_tmp_dir.empty ()) - { - base_tmp_dir = sys::env::get_temp_directory (); - - // Make sure we don't get short 8.3 path on Windows since some - // versions of latex on that platform don't support them - // (see bug #62779) - if (base_tmp_dir.find ('~') != std::string::npos) - base_tmp_dir = sys::canonicalize_file_name (base_tmp_dir); - } - - m_tmp_dir = sys::tempnam (base_tmp_dir, "latex"); -#else - m_tmp_dir = sys::tempnam ("", "latex"); -#endif - - if (sys::mkdir (m_tmp_dir, 0700) != 0) - { - warning_with_id ("Octave:LaTeX:internal-error", - "latex_renderer: unable to create temp directory"); - return std::string (); - } - } - - std::string base_file_name - = sys::file_ops::concat (m_tmp_dir, "default"); + Matrix bbox; + uint8NDArray pixels; - // Duplicate \n characters and align multi-line strings based on - // horizontalalignment - std::string latex_txt (txt); - std::size_t pos = 0; - - while (true) - { - pos = txt.find_first_of ("\n", pos); - - if (pos == std::string::npos) - break; - - latex_txt.replace (pos, 1, "\n\n"); - - pos += 1; - } + text_to_pixels (txt, pixels, bbox, 0, 0, rotation, interpreter, false); - std::string env ("flushleft"); - if (halign == 1) - env = "center"; - else if (halign == 2) - env = "flushright"; - - latex_txt = std::string ("\\begin{" ) + env + "}\n" - + latex_txt + "\n" - + "\\end{" + env + "}\n"; - - // Write to temporary .tex file - std::ofstream file; - file.open (base_file_name + ".tex"); - file << "\\documentclass[10pt, varwidth]{standalone}\n" - << "\\usepackage{amsmath}\n" - << "\\usepackage[utf8]{inputenc}\n" - << "\\begin{document}\n" - << latex_txt << "\n" - << "\\end{document}"; - file.close (); - - return base_file_name; + return bbox.extract_n (0, 2, 1, 2); } - bool - latex_renderer::read_image (const std::string& png_file, - uint8NDArray& data) const + void text_to_strlist (const std::string& txt, + std::list& lst, + Matrix& bbox, int halign, int valign, double rotation, + const caseless_str& interp) { - uint8NDArray alpha; - uint8NDArray rgb; - int height; - int width; - - try - { - // First get the image size to build the argument to __magick_read__ - octave_value_list retval = F__magick_ping__ (ovl (png_file), 1); - - octave_scalar_map info - = retval(0).xscalar_map_value ("latex_renderer::read_image: " - "Wrong type for info"); - height = info.getfield ("rows").int_value (); - width = info.getfield ("columns").int_value (); - Cell region (dim_vector(1, 2)); - region(0) = range (1.0, height); - region(1) = range (1.0, width); - info.setfield ("region", region); - info.setfield ("index", octave_value (1)); - - // Retrieve the alpha map - retval = F__magick_read__ (ovl (png_file, info), 3); - - alpha = retval(2).xuint8_array_value ("latex_renderer::read_image: " - "Wrong type for alpha"); - } - catch (const execution_exception& ee) - { - warning_with_id ("Octave:LaTeX:internal-error", - "latex_renderer:: failed to read png data. %s", - ee.message ().c_str ()); - - interpreter& interp = __get_interpreter__ (); - - interp.recover_from_exception (); + uint8NDArray pixels; + text_to_pixels (txt, pixels, bbox, halign, valign, rotation, + interp, false); - return false; - } - - data = uint8NDArray (dim_vector (4, width, height), - static_cast (0)); - - for (int i = 0; i < height; i++) - { - for (int j = 0; j < width; j++) - { - data(0, j, i) = m_color(0); - data(1, j, i) = m_color(1); - data(2, j, i) = m_color(2); - data(3, j, i) = alpha(height-i-1, j); - } - } - - return true; - } + text_renderer::font fnt; + text_renderer::string str ("", fnt, 0.0, 0.0); + str.set_color (m_color); - void - latex_renderer::warn_helper (std::string caller, std::string txt, - std::string cmd, process_execution_result result) - { - if (m_testing && ! m_debug) - return; - - if (! m_debug) - warning_with_id ("Octave:LaTeX:internal-error", - "latex_renderer: unable to compile \"%s\"", - txt.c_str ()); - else - warning_with_id ("Octave:LaTeX:internal-error", - "latex_renderer: %s failed for string \"%s\"\n\ -* Command:\n\t%s\n\n* Error:\n%s\n\n* Stdout:\n%s", - caller.c_str (), txt.c_str (), cmd.c_str (), - result.err_msg ().c_str (), - result.stdout_output ().c_str ()); - } - - uint8NDArray - latex_renderer::render (const std::string& txt, int halign) - { - // Render if it was not already done gh_manager& gh_mgr = octave::__get_gh_manager__ (); gh_manager::latex_data ldata = gh_mgr.get_latex_data (key (txt, halign)); - if (! ldata.first.isempty ()) - return ldata.first; + str.set_svg_element (ldata.second); - uint8NDArray data; + lst.push_back (str); + } - // First write the base .tex file - std::string base_file_name = write_tex_file (txt, halign); + void text_to_pixels (const std::string& txt, uint8NDArray& pxls, + Matrix& bbox, int halign, int valign, double rotation, + const caseless_str& interpreter, + bool handle_rotation); - if (base_file_name.empty ()) - return data; + void set_anti_aliasing (bool /*val*/) { } + + octave_map get_system_fonts (void) { return octave_map (); } + + bool ok (void); + +private: - // Generate DVI file - std::string tex_file = quote_string (base_file_name + ".tex"); - std::string dvi_file = quote_string (base_file_name + ".dvi"); - std::string log_file = quote_string (base_file_name + ".log"); + std::string key (const std::string& txt, int halign) + { + return (txt + ":" + + std::to_string (m_fontsize) + ":" + + std::to_string (halign) + ":" + + std::to_string (m_color(0)) + ":" + + std::to_string (m_color(1)) + ":" + + std::to_string (m_color(2))); + } + + void warn_helper (std::string caller, std::string txt, std::string cmd, + process_execution_result result); + + uint8NDArray render (const std::string& txt, int halign = 0); - process_execution_result result; - std::string cmd = (m_latex_binary + " -interaction=nonstopmode " - + "-output-directory=" + quote_string (m_tmp_dir) + " " - + tex_file); + bool read_image (const std::string& png_file, uint8NDArray& data) const; + + std::string write_tex_file (const std::string& txt, int halign); -#if defined (OCTAVE_USE_WINDOWS_API) - cmd = quote_string (cmd); -#endif +private: + double m_fontsize; + std::string m_fontname; + std::string m_tmp_dir; + uint8NDArray m_color; + std::string m_latex_binary; + std::string m_dvipng_binary; + std::string m_dvisvg_binary; + bool m_debug; + bool m_testing; - result = run_command_and_return_output (cmd); +}; - if (result.exit_status () != 0) - { - warn_helper ("latex", txt, cmd, result); +bool +latex_renderer::ok (void) +{ + // Only run the test once in a session + static bool tested = false; + + static bool isok = false; + + if (! tested) + { + tested = true; - if (txt != "?") - { - write_tex_file ("?", halign); + // For testing, render a questoin mark + uint8NDArray pixels = render ("?"); + + if (! pixels.isempty ()) + isok = true; + else + warning_with_id ("Octave:LaTeX:internal-error", + "latex_renderer: a run-time test failed and the 'latex' interpreter has been disabled."); + } + + m_testing = false; - result = run_command_and_return_output (cmd); - if (result.exit_status () != 0) - return data; - } - else - return data; - } + return isok; +} - double size_factor = m_fontsize / 10.0; - +std::string +latex_renderer::write_tex_file (const std::string& txt, int halign) +{ + if (m_tmp_dir.empty ()) + { + //Create the temporary directory +#if defined (OCTAVE_USE_WINDOWS_API) + static std::string base_tmp_dir; - // Convert DVI to SVG, read file and store its content for later use in - // gl2ps_print - std::string svg_file = base_file_name + ".svg"; + if (base_tmp_dir.empty ()) + { + base_tmp_dir = sys::env::get_temp_directory (); - cmd = (m_dvisvg_binary + " -n " - + "-TS" + std::to_string (size_factor) + " " - + "-v1 -o " + quote_string (svg_file) + " " - + dvi_file); + // Make sure we don't get short 8.3 path on Windows since some + // versions of latex on that platform don't support them + // (see bug #62779) + if (base_tmp_dir.find ('~') != std::string::npos) + base_tmp_dir = sys::canonicalize_file_name (base_tmp_dir); + } -#if defined (OCTAVE_USE_WINDOWS_API) - cmd = quote_string (cmd); + m_tmp_dir = sys::tempnam (base_tmp_dir, "latex"); +#else + m_tmp_dir = sys::tempnam ("", "latex"); #endif - result = run_command_and_return_output (cmd); + if (sys::mkdir (m_tmp_dir, 0700) != 0) + { + warning_with_id ("Octave:LaTeX:internal-error", + "latex_renderer: unable to create temp directory"); + return std::string (); + } + } + + std::string base_file_name + = sys::file_ops::concat (m_tmp_dir, "default"); + + // Duplicate \n characters and align multi-line strings based on + // horizontalalignment + std::string latex_txt (txt); + std::size_t pos = 0; + + while (true) + { + pos = txt.find_first_of ("\n", pos); + + if (pos == std::string::npos) + break; + + latex_txt.replace (pos, 1, "\n\n"); + + pos += 1; + } + + std::string env ("flushleft"); + if (halign == 1) + env = "center"; + else if (halign == 2) + env = "flushright"; + + latex_txt = std::string ("\\begin{" ) + env + "}\n" + + latex_txt + "\n" + + "\\end{" + env + "}\n"; - if (result.exit_status () != 0) - { - warn_helper ("dvisvg", txt, cmd, result); - return data; - } + // Write to temporary .tex file + std::ofstream file; + file.open (base_file_name + ".tex"); + file << "\\documentclass[10pt, varwidth]{standalone}\n" + << "\\usepackage{amsmath}\n" + << "\\usepackage[utf8]{inputenc}\n" + << "\\begin{document}\n" + << latex_txt << "\n" + << "\\end{document}"; + file.close (); + + return base_file_name; +} + +bool +latex_renderer::read_image (const std::string& png_file, + uint8NDArray& data) const +{ + uint8NDArray alpha; + uint8NDArray rgb; + int height; + int width; + + try + { + // First get the image size to build the argument to __magick_read__ + octave_value_list retval = F__magick_ping__ (ovl (png_file), 1); + + octave_scalar_map info + = retval(0).xscalar_map_value ("latex_renderer::read_image: " + "Wrong type for info"); + height = info.getfield ("rows").int_value (); + width = info.getfield ("columns").int_value (); + Cell region (dim_vector(1, 2)); + region(0) = range (1.0, height); + region(1) = range (1.0, width); + info.setfield ("region", region); + info.setfield ("index", octave_value (1)); + + // Retrieve the alpha map + retval = F__magick_read__ (ovl (png_file, info), 3); - std::ifstream svg_stream (svg_file); - std::string svg_string; - svg_string.assign (std::istreambuf_iterator (svg_stream), - std::istreambuf_iterator ()); + alpha = retval(2).xuint8_array_value ("latex_renderer::read_image: " + "Wrong type for alpha"); + } + catch (const execution_exception& ee) + { + warning_with_id ("Octave:LaTeX:internal-error", + "latex_renderer:: failed to read png data. %s", + ee.message ().c_str ()); + + interpreter& interp = __get_interpreter__ (); + + interp.recover_from_exception (); + + return false; + } + + data = uint8NDArray (dim_vector (4, width, height), + static_cast (0)); + + for (int i = 0; i < height; i++) + { + for (int j = 0; j < width; j++) + { + data(0, j, i) = m_color(0); + data(1, j, i) = m_color(1); + data(2, j, i) = m_color(2); + data(3, j, i) = alpha(height-i-1, j); + } + } + + return true; +} + +void +latex_renderer::warn_helper (std::string caller, std::string txt, + std::string cmd, process_execution_result result) +{ + if (m_testing && ! m_debug) + return; - // Convert DVI to PNG, read file and format pixel data for later use in - // OpenGL - std::string png_file = base_file_name + ".png"; + if (! m_debug) + warning_with_id ("Octave:LaTeX:internal-error", + "latex_renderer: unable to compile \"%s\"", + txt.c_str ()); + else + warning_with_id ("Octave:LaTeX:internal-error", + "latex_renderer: %s failed for string \"%s\"\n\ +* Command:\n\t%s\n\n* Error:\n%s\n\n* Stdout:\n%s", + caller.c_str (), txt.c_str (), cmd.c_str (), + result.err_msg ().c_str (), + result.stdout_output ().c_str ()); +} + +uint8NDArray +latex_renderer::render (const std::string& txt, int halign) +{ + // Render if it was not already done + gh_manager& gh_mgr = octave::__get_gh_manager__ (); + + gh_manager::latex_data ldata = gh_mgr.get_latex_data (key (txt, halign)); - cmd = (m_dvipng_binary + " " + dvi_file + " " - + "-q -o " + quote_string (png_file) + " " - + "-bg Transparent -D " - + std::to_string (std::floor (72.0 * size_factor))); + if (! ldata.first.isempty ()) + return ldata.first; + + uint8NDArray data; + + // First write the base .tex file + std::string base_file_name = write_tex_file (txt, halign); + + if (base_file_name.empty ()) + return data; + + // Generate DVI file + std::string tex_file = quote_string (base_file_name + ".tex"); + std::string dvi_file = quote_string (base_file_name + ".dvi"); + std::string log_file = quote_string (base_file_name + ".log"); + + process_execution_result result; + std::string cmd = (m_latex_binary + " -interaction=nonstopmode " + + "-output-directory=" + quote_string (m_tmp_dir) + " " + + tex_file); #if defined (OCTAVE_USE_WINDOWS_API) - cmd = quote_string (cmd); + cmd = quote_string (cmd); #endif - result = run_command_and_return_output (cmd); + result = run_command_and_return_output (cmd); + + if (result.exit_status () != 0) + { + warn_helper ("latex", txt, cmd, result); + + if (txt != "?") + { + write_tex_file ("?", halign); - if (result.exit_status () != 0) - { - warn_helper ("dvipng", txt, cmd, result); + result = run_command_and_return_output (cmd); + if (result.exit_status () != 0) + return data; + } + else return data; - } + } + + double size_factor = m_fontsize / 10.0; + - if (! read_image (png_file, data)) - return data; + // Convert DVI to SVG, read file and store its content for later use in + // gl2ps_print + std::string svg_file = base_file_name + ".svg"; + + cmd = (m_dvisvg_binary + " -n " + + "-TS" + std::to_string (size_factor) + " " + + "-v1 -o " + quote_string (svg_file) + " " + + dvi_file); - // Cache pixel and svg data for this string - ldata.first = data; - ldata.second = svg_string; +#if defined (OCTAVE_USE_WINDOWS_API) + cmd = quote_string (cmd); +#endif + + result = run_command_and_return_output (cmd); - gh_mgr.set_latex_data (key (txt, halign), ldata); + if (result.exit_status () != 0) + { + warn_helper ("dvisvg", txt, cmd, result); + return data; + } - if (m_debug) - std::cout << "* Caching " << key (txt, halign) << std::endl; + std::ifstream svg_stream (svg_file); + std::string svg_string; + svg_string.assign (std::istreambuf_iterator (svg_stream), + std::istreambuf_iterator ()); + + // Convert DVI to PNG, read file and format pixel data for later use in + // OpenGL + std::string png_file = base_file_name + ".png"; - return data; - } + cmd = (m_dvipng_binary + " " + dvi_file + " " + + "-q -o " + quote_string (png_file) + " " + + "-bg Transparent -D " + + std::to_string (std::floor (72.0 * size_factor))); + +#if defined (OCTAVE_USE_WINDOWS_API) + cmd = quote_string (cmd); +#endif + + result = run_command_and_return_output (cmd); - void - latex_renderer::text_to_pixels (const std::string& txt, uint8NDArray& pixels, - Matrix& bbox, int halign, int valign, - double rotation, - const caseless_str& /*interpreter*/, - bool handle_rotation) - { - // Return early for empty strings - if (txt.empty ()) - { - bbox = Matrix (1, 4, 0.0); - return; - } + if (result.exit_status () != 0) + { + warn_helper ("dvipng", txt, cmd, result); + return data; + } + + if (! read_image (png_file, data)) + return data; - if (ok ()) - pixels = render (txt, halign); - else - pixels = uint8NDArray (dim_vector (4, 1, 1), static_cast (0)); + // Cache pixel and svg data for this string + ldata.first = data; + ldata.second = svg_string; + + gh_mgr.set_latex_data (key (txt, halign), ldata); - if (pixels.ndims () < 3 || pixels.isempty ()) - return; // nothing to render + if (m_debug) + std::cout << "* Caching " << key (txt, halign) << std::endl; + + return data; +} - // Store unrotated bbox size - bbox = Matrix (1, 4, 0.0); - bbox (2) = pixels.dim2 (); - bbox (3) = pixels.dim3 (); +void +latex_renderer::text_to_pixels (const std::string& txt, uint8NDArray& pixels, + Matrix& bbox, int halign, int valign, + double rotation, + const caseless_str& /*interpreter*/, + bool handle_rotation) +{ + // Return early for empty strings + if (txt.empty ()) + { + bbox = Matrix (1, 4, 0.0); + return; + } - // Now rotate pixels if necessary - int rot_mode = rotation_to_mode (rotation); + if (ok ()) + pixels = render (txt, halign); + else + pixels = uint8NDArray (dim_vector (4, 1, 1), static_cast (0)); - if (! pixels.isempty ()) - rotate_pixels (pixels, rot_mode); + if (pixels.ndims () < 3 || pixels.isempty ()) + return; // nothing to render - // Move X0 and Y0 depending on alignments and eventually swap values - // for text rotated 90° 180° or 270° - fix_bbox_anchor (bbox, halign, valign, rot_mode, handle_rotation); - } + // Store unrotated bbox size + bbox = Matrix (1, 4, 0.0); + bbox (2) = pixels.dim2 (); + bbox (3) = pixels.dim3 (); + + // Now rotate pixels if necessary + int rot_mode = rotation_to_mode (rotation); + + if (! pixels.isempty ()) + rotate_pixels (pixels, rot_mode); - base_text_renderer * - make_latex_text_renderer (void) - { - latex_renderer *renderer = new latex_renderer (); + // Move X0 and Y0 depending on alignments and eventually swap values + // for text rotated 90° 180° or 270° + fix_bbox_anchor (bbox, halign, valign, rot_mode, handle_rotation); +} - return renderer; - } +base_text_renderer * +make_latex_text_renderer (void) +{ + latex_renderer *renderer = new latex_renderer (); + + return renderer; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/latex-text-renderer.h --- a/libinterp/corefcn/latex-text-renderer.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/latex-text-renderer.h Thu Dec 01 20:05:44 2022 -0800 @@ -30,9 +30,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class base_text_renderer; +class base_text_renderer; - extern base_text_renderer * make_latex_text_renderer (void); +extern base_text_renderer * make_latex_text_renderer (void); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/load-path.cc --- a/libinterp/corefcn/load-path.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/load-path.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,2411 +51,2411 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Canonicalize file name (keeping the path relative) if it exists. - // Return it unmodified otherwise. - - static std::string - maybe_canonicalize (const std::string& dir_arg) - { - bool is_absolute_path = sys::env::absolute_pathname (dir_arg); - - std::string canonical_dir = sys::canonicalize_file_name (dir_arg); - std::string dir; - if (canonical_dir.empty ()) - dir = dir_arg; - else - { - dir = canonical_dir; - - if (! is_absolute_path) - { - // Remove current path from absolute path generated by - // canonicalize_file_name. - std::string cwd = sys::canonicalize_file_name ("."); - if (dir.compare (0, cwd.length (), cwd) == 0) - dir.erase (0, cwd.length ()+1); - if (dir.empty ()) - dir = "."; - } - } - - return dir; - } - - static void - maybe_add_path_elts (std::string& path, const std::string& dir) - { - std::string tpath = genpath (maybe_canonicalize (dir)); - - if (! tpath.empty ()) - { - if (path.empty ()) - path = tpath; - else - path += directory_path::path_sep_str () + tpath; - } - } - - static std::list - split_path (const std::string& p) - { - std::list retval; - - std::size_t beg = 0; - std::size_t end = p.find (directory_path::path_sep_char ()); - - std::size_t len = p.length (); - - while (end != std::string::npos) - { - std::string elt = p.substr (beg, end-beg); - - if (! elt.empty ()) - retval.push_back (elt); - - beg = end + 1; - - if (beg == len) +// Canonicalize file name (keeping the path relative) if it exists. +// Return it unmodified otherwise. + +static std::string +maybe_canonicalize (const std::string& dir_arg) +{ + bool is_absolute_path = sys::env::absolute_pathname (dir_arg); + + std::string canonical_dir = sys::canonicalize_file_name (dir_arg); + std::string dir; + if (canonical_dir.empty ()) + dir = dir_arg; + else + { + dir = canonical_dir; + + if (! is_absolute_path) + { + // Remove current path from absolute path generated by + // canonicalize_file_name. + std::string cwd = sys::canonicalize_file_name ("."); + if (dir.compare (0, cwd.length (), cwd) == 0) + dir.erase (0, cwd.length ()+1); + if (dir.empty ()) + dir = "."; + } + } + + return dir; +} + +static void +maybe_add_path_elts (std::string& path, const std::string& dir) +{ + std::string tpath = genpath (maybe_canonicalize (dir)); + + if (! tpath.empty ()) + { + if (path.empty ()) + path = tpath; + else + path += directory_path::path_sep_str () + tpath; + } +} + +static std::list +split_path (const std::string& p) +{ + std::list retval; + + std::size_t beg = 0; + std::size_t end = p.find (directory_path::path_sep_char ()); + + std::size_t len = p.length (); + + while (end != std::string::npos) + { + std::string elt = p.substr (beg, end-beg); + + if (! elt.empty ()) + retval.push_back (elt); + + beg = end + 1; + + if (beg == len) + break; + + end = p.find (directory_path::path_sep_char (), beg); + } + + std::string elt = p.substr (beg); + + if (! elt.empty ()) + retval.push_back (elt); + + return retval; +} + +// Strip trailing directory separators. + +static std::string +strip_trailing_separators (const std::string& dir_arg) +{ + std::string dir = dir_arg; + + std::size_t k = dir.length (); + + while (k > 1 && sys::file_ops::is_dir_sep (dir[k-1])) + k--; + + if (k < dir.length ()) + dir.resize (k); + + return dir; +} + +// Should we cache all files in private directories, or is it OK to just +// look them up each time as needed? + +static std::string +find_private_file (const std::string& fname) +{ + std::string retval; + + // Look in private directory corresponding to current function (if + // any). + + symbol_scope scope = __get_current_scope__ (); + + octave_user_code *curr_code = scope ? scope.user_code () : nullptr; + + if (curr_code) + { + // Even for private functions, dir_name doesn't contain the + // "private" directory component so we append it here in all + // cases. + + std::string dir_name = curr_code->dir_name (); + + if (! dir_name.empty ()) + { + std::string pfname = dir_name + sys::file_ops::dir_sep_str () + + "private" + sys::file_ops::dir_sep_str () + + fname; + + sys::file_stat fs (pfname); + + if (fs.exists () && fs.is_reg ()) + retval = pfname; + } + } + + return retval; +} + +// True if a path is contained in a path list separated by path_sep_char + +static bool +in_path_list (const std::string& path_list, const std::string& path) +{ + std::size_t ps = path.size (); + std::size_t pls = path_list.size (); + std::size_t pos = path_list.find (path); + char psc = directory_path::path_sep_char (); + while (pos != std::string::npos) + { + if ((pos == 0 || path_list[pos-1] == psc) + && (pos + ps == pls || path_list[pos + ps] == psc)) + return true; + else + pos = path_list.find (path, pos + 1); + } + + return false; +} + +static void +rehash_internal (void) +{ + load_path& lp = __get_load_path__ (); + + lp.update (); + + // Signal the GUI allowing updating the load path dialog + event_manager& evmgr = __get_event_manager__ (); + evmgr.update_path_dialog (); + + // FIXME: maybe we should rename this variable since it is being + // used for more than keeping track of the prompt time. + + // This will force updated functions to be found. + Vlast_prompt_time.stamp (); +} + +//! Check if directory contains modified subdirectories. +//! +//! @param d directory to check +//! @param last_checked time of last check +//! +//! Path patterns that need to be checked for modifications: +//! +//! private/ +//! +//! @class/ +//! @class/private/ +//! +//! +namespace/ +//! +namespace/private/ +//! +namespace/@class/ +//! +namespace/@class/private/ +//! +//! Recursion into sub-namespaces: +//! +//! +namespace/+subnamespace/ +//! +//! @return true if directory contains modified subdirectories + +static bool +subdirs_modified (const std::string& d, const sys::time& last_checked) +{ + sys::dir_entry dir (d); + + if (dir) + { + string_vector flist = dir.read (); + + octave_idx_type len = flist.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + std::string fname = flist[i]; + + std::string full_name = sys::file_ops::concat (d, fname); + + sys::file_stat fs (full_name); + + // Check if directory AND if relevant (@,+,private) + // AND (if modified OR recursion into (@,+) sub-directories) + if (fs && fs.is_dir () + && (fname[0] == '@' || fname[0] == '+' || fname == "private") + && ((fs.mtime () + fs.time_resolution () > last_checked) + || ((fname[0] == '@' || fname[0] == '+') + && subdirs_modified (full_name, last_checked)))) + return true; + } + } + else + { + std::string msg = dir.error (); + warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); + } + + return false; +} + +std::string load_path::s_sys_path; +load_path::abs_dir_cache_type load_path::s_abs_dir_cache; + +load_path::load_path (interpreter& interp) + : add_hook ([=] (const std::string& dir) { this->execute_pkg_add (dir); }), +remove_hook ([=] (const std::string& dir) { this->execute_pkg_del (dir); }), +m_interpreter (interp), m_package_map (), m_top_level_package (), +m_dir_info_list (), m_init_dirs (), m_command_line_path () +{ } + +void +load_path::initialize (bool set_initial_path) +{ + s_sys_path = ""; + + if (set_initial_path) + { + maybe_add_path_elts (s_sys_path, config::local_ver_oct_file_dir ()); + maybe_add_path_elts (s_sys_path, config::local_api_oct_file_dir ()); + maybe_add_path_elts (s_sys_path, config::local_oct_file_dir ()); + maybe_add_path_elts (s_sys_path, config::local_ver_fcn_file_dir ()); + maybe_add_path_elts (s_sys_path, config::local_api_fcn_file_dir ()); + maybe_add_path_elts (s_sys_path, config::local_fcn_file_dir ()); + maybe_add_path_elts (s_sys_path, config::oct_file_dir ()); + maybe_add_path_elts (s_sys_path, config::fcn_file_dir ()); + maybe_add_path_elts (s_sys_path, config::oct_data_dir ()); + } + + std::string tpath = load_path::m_command_line_path; + + if (tpath.empty ()) + tpath = sys::env::getenv ("OCTAVE_PATH"); + + std::string xpath; + + if (! tpath.empty ()) + { + xpath = tpath; + + if (! s_sys_path.empty ()) + xpath += directory_path::path_sep_str () + s_sys_path; + } + else + xpath = s_sys_path; + + set (xpath, false, true); +} + +void +load_path::clear (void) +{ + m_dir_info_list.clear (); + + m_top_level_package.clear (); + + m_package_map.clear (); +} + +void +load_path::set (const std::string& p, bool warn, bool is_init) +{ + // Use a list when we need to preserve order. + std::list elts = split_path (p); + + for (auto& elt : elts) + elt = maybe_canonicalize (elt); + + // Use a set when we need to search and order is not important. + std::set elts_set (elts.begin (), elts.end ()); + + if (is_init) + m_init_dirs = elts_set; + else + { + for (const auto& init_dir : m_init_dirs) + { + if (elts_set.find (init_dir) == elts_set.end ()) + { + warning_with_id ("Octave:remove-init-dir", + "default load path altered. Some built-in functions may not be found. Try restoredefaultpath() to recover it."); + break; + } + } + } + + // Temporarily disable add hook. + + unwind_protect frame; + frame.protect_var (add_hook); + + add_hook = nullptr; + + clear (); + + for (const auto& elt : elts) + append (elt, warn); + + // Restore add hook and execute for all newly added directories. + frame.run_first (); + + // FIXME: Shouldn't the test for add_hook be outside the for loop? + // Why not use const here? Does add_hook change dir_info_list? + for (auto& di : m_dir_info_list) + { + if (add_hook) + add_hook (di.dir_name); + } + + // Always prepend current directory. + prepend (".", warn); +} + +void +load_path::append (const std::string& dir, bool warn) +{ + if (! dir.empty ()) + add (dir, true, warn); +} + +void +load_path::prepend (const std::string& dir, bool warn) +{ + if (! dir.empty ()) + add (dir, false, warn); +} + +bool +load_path::remove (const std::string& dir_arg) +{ + bool retval = false; + + if (! dir_arg.empty ()) + { + if (same_file (dir_arg, ".")) + { + warning (R"(rmpath: can't remove "." from path)"); + + // Avoid additional warnings. + retval = true; + } + else + { + std::string dir = sys::file_ops::tilde_expand (dir_arg); + + dir = strip_trailing_separators (dir); + + auto i = find_dir_info (dir); + + if (i != m_dir_info_list.end ()) + { + retval = true; + + if (remove_hook) + remove_hook (dir); + + dir_info& di = *i; + + remove (di); + + m_dir_info_list.erase (i); + } + } + } + + return retval; +} + +void +load_path::update (void) +{ + // I don't see a better way to do this because we need to + // preserve the correct directory ordering for new files that + // have appeared. + + m_top_level_package.clear (); + + m_package_map.clear (); + + for (auto& di : m_dir_info_list) + { + bool ok = di.update (); + + if (! ok) + warning_with_id + ("Octave:load-path:update-failed", + "load-path: update failed for '%s', removing from path", + di.dir_name.c_str ()); + else + add (di, true, "", true); + } +} + +bool +load_path::contains_canonical (const std::string& dir) const +{ + bool retval = false; + + for (const auto& d : m_dir_info_list) + { + if (same_file (dir, d.dir_name)) + { + retval = true; break; - - end = p.find (directory_path::path_sep_char (), beg); - } - - std::string elt = p.substr (beg); - - if (! elt.empty ()) - retval.push_back (elt); - - return retval; - } - - // Strip trailing directory separators. - - static std::string - strip_trailing_separators (const std::string& dir_arg) - { - std::string dir = dir_arg; - - std::size_t k = dir.length (); - - while (k > 1 && sys::file_ops::is_dir_sep (dir[k-1])) - k--; - - if (k < dir.length ()) - dir.resize (k); - - return dir; - } - - // Should we cache all files in private directories, or is it OK to just - // look them up each time as needed? - - static std::string - find_private_file (const std::string& fname) - { - std::string retval; - - // Look in private directory corresponding to current function (if - // any). - - symbol_scope scope = __get_current_scope__ (); - - octave_user_code *curr_code = scope ? scope.user_code () : nullptr; - - if (curr_code) - { - // Even for private functions, dir_name doesn't contain the - // "private" directory component so we append it here in all - // cases. - - std::string dir_name = curr_code->dir_name (); - - if (! dir_name.empty ()) - { - std::string pfname = dir_name + sys::file_ops::dir_sep_str () - + "private" + sys::file_ops::dir_sep_str () - + fname; - - sys::file_stat fs (pfname); - - if (fs.exists () && fs.is_reg ()) - retval = pfname; - } - } - - return retval; - } - - // True if a path is contained in a path list separated by path_sep_char - - static bool - in_path_list (const std::string& path_list, const std::string& path) - { - std::size_t ps = path.size (); - std::size_t pls = path_list.size (); - std::size_t pos = path_list.find (path); - char psc = directory_path::path_sep_char (); - while (pos != std::string::npos) - { - if ((pos == 0 || path_list[pos-1] == psc) - && (pos + ps == pls || path_list[pos + ps] == psc)) - return true; - else - pos = path_list.find (path, pos + 1); - } - - return false; - } - - static void - rehash_internal (void) - { - load_path& lp = __get_load_path__ (); - - lp.update (); - - // Signal the GUI allowing updating the load path dialog - event_manager& evmgr = __get_event_manager__ (); - evmgr.update_path_dialog (); - - // FIXME: maybe we should rename this variable since it is being - // used for more than keeping track of the prompt time. - - // This will force updated functions to be found. - Vlast_prompt_time.stamp (); - } - - //! Check if directory contains modified subdirectories. - //! - //! @param d directory to check - //! @param last_checked time of last check - //! - //! Path patterns that need to be checked for modifications: - //! - //! private/ - //! - //! @class/ - //! @class/private/ - //! - //! +namespace/ - //! +namespace/private/ - //! +namespace/@class/ - //! +namespace/@class/private/ - //! - //! Recursion into sub-namespaces: - //! - //! +namespace/+subnamespace/ - //! - //! @return true if directory contains modified subdirectories - - static bool - subdirs_modified (const std::string& d, const sys::time& last_checked) - { - sys::dir_entry dir (d); - - if (dir) - { - string_vector flist = dir.read (); - - octave_idx_type len = flist.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - std::string fname = flist[i]; - - std::string full_name = sys::file_ops::concat (d, fname); - - sys::file_stat fs (full_name); - - // Check if directory AND if relevant (@,+,private) - // AND (if modified OR recursion into (@,+) sub-directories) - if (fs && fs.is_dir () - && (fname[0] == '@' || fname[0] == '+' || fname == "private") - && ((fs.mtime () + fs.time_resolution () > last_checked) - || ((fname[0] == '@' || fname[0] == '+') - && subdirs_modified (full_name, last_checked)))) - return true; - } - } - else - { - std::string msg = dir.error (); - warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); - } - - return false; - } - - std::string load_path::s_sys_path; - load_path::abs_dir_cache_type load_path::s_abs_dir_cache; - - load_path::load_path (interpreter& interp) - : add_hook ([=] (const std::string& dir) { this->execute_pkg_add (dir); }), - remove_hook ([=] (const std::string& dir) { this->execute_pkg_del (dir); }), - m_interpreter (interp), m_package_map (), m_top_level_package (), - m_dir_info_list (), m_init_dirs (), m_command_line_path () - { } - - void - load_path::initialize (bool set_initial_path) - { - s_sys_path = ""; - - if (set_initial_path) - { - maybe_add_path_elts (s_sys_path, config::local_ver_oct_file_dir ()); - maybe_add_path_elts (s_sys_path, config::local_api_oct_file_dir ()); - maybe_add_path_elts (s_sys_path, config::local_oct_file_dir ()); - maybe_add_path_elts (s_sys_path, config::local_ver_fcn_file_dir ()); - maybe_add_path_elts (s_sys_path, config::local_api_fcn_file_dir ()); - maybe_add_path_elts (s_sys_path, config::local_fcn_file_dir ()); - maybe_add_path_elts (s_sys_path, config::oct_file_dir ()); - maybe_add_path_elts (s_sys_path, config::fcn_file_dir ()); - maybe_add_path_elts (s_sys_path, config::oct_data_dir ()); - } - - std::string tpath = load_path::m_command_line_path; - - if (tpath.empty ()) - tpath = sys::env::getenv ("OCTAVE_PATH"); - - std::string xpath; - - if (! tpath.empty ()) - { - xpath = tpath; - - if (! s_sys_path.empty ()) - xpath += directory_path::path_sep_str () + s_sys_path; - } - else - xpath = s_sys_path; - - set (xpath, false, true); - } - - void - load_path::clear (void) - { - m_dir_info_list.clear (); - - m_top_level_package.clear (); - - m_package_map.clear (); - } - - void - load_path::set (const std::string& p, bool warn, bool is_init) - { - // Use a list when we need to preserve order. - std::list elts = split_path (p); - - for (auto& elt : elts) - elt = maybe_canonicalize (elt); - - // Use a set when we need to search and order is not important. - std::set elts_set (elts.begin (), elts.end ()); - - if (is_init) - m_init_dirs = elts_set; - else - { - for (const auto& init_dir : m_init_dirs) - { - if (elts_set.find (init_dir) == elts_set.end ()) - { - warning_with_id ("Octave:remove-init-dir", - "default load path altered. Some built-in functions may not be found. Try restoredefaultpath() to recover it."); - break; - } - } - } - - // Temporarily disable add hook. - - unwind_protect frame; - frame.protect_var (add_hook); - - add_hook = nullptr; - - clear (); - - for (const auto& elt : elts) - append (elt, warn); - - // Restore add hook and execute for all newly added directories. - frame.run_first (); - - // FIXME: Shouldn't the test for add_hook be outside the for loop? - // Why not use const here? Does add_hook change dir_info_list? - for (auto& di : m_dir_info_list) - { - if (add_hook) - add_hook (di.dir_name); - } - - // Always prepend current directory. - prepend (".", warn); - } - - void - load_path::append (const std::string& dir, bool warn) - { - if (! dir.empty ()) - add (dir, true, warn); - } - - void - load_path::prepend (const std::string& dir, bool warn) - { - if (! dir.empty ()) - add (dir, false, warn); - } - - bool - load_path::remove (const std::string& dir_arg) - { - bool retval = false; - - if (! dir_arg.empty ()) - { - if (same_file (dir_arg, ".")) - { - warning (R"(rmpath: can't remove "." from path)"); - - // Avoid additional warnings. - retval = true; - } - else - { - std::string dir = sys::file_ops::tilde_expand (dir_arg); - - dir = strip_trailing_separators (dir); - - auto i = find_dir_info (dir); - - if (i != m_dir_info_list.end ()) - { - retval = true; - - if (remove_hook) - remove_hook (dir); - - dir_info& di = *i; - - remove (di); - - m_dir_info_list.erase (i); - } - } - } - - return retval; - } - - void - load_path::update (void) - { - // I don't see a better way to do this because we need to - // preserve the correct directory ordering for new files that - // have appeared. - - m_top_level_package.clear (); - - m_package_map.clear (); - - for (auto& di : m_dir_info_list) - { - bool ok = di.update (); - - if (! ok) - warning_with_id - ("Octave:load-path:update-failed", - "load-path: update failed for '%s', removing from path", - di.dir_name.c_str ()); - else - add (di, true, "", true); - } - } - - bool - load_path::contains_canonical (const std::string& dir) const - { - bool retval = false; - - for (const auto& d : m_dir_info_list) - { - if (same_file (dir, d.dir_name)) - { - retval = true; - break; - } - } - - return retval; - } - - bool - load_path::contains_file_in_dir (const std::string& file, - const std::string& dir) - { - bool ok = false; - bool addpath_option = true; - - std::string curr_dir = sys::env::get_current_directory (); - - if (same_file (curr_dir, dir)) - ok = true; - else - { - bool dir_in_load_path = contains_canonical (dir); - - // get base name, allowing "@class/method.m" (bug #41514) - std::string base_file = (file.length () > dir.length ()) - ? file.substr (dir.length () + 1) - : sys::env::base_pathname (file); - - std::string lp_file = find_file (base_file); - - if (dir_in_load_path) - { - if (same_file (lp_file, file)) - ok = true; - } - else - { - // File directory is not in path. Is the file in the path in - // the current directory? If so, then changing the current - // directory will be needed. Adding directory to path is - // not enough because the file in the current directory would - // still be found. - - if (same_file (lp_file, base_file)) - { - if (same_file (curr_dir, dir)) - ok = true; - else - addpath_option = false; - } - } - } - - if (! ok) - { - event_manager& evmgr = m_interpreter.get_event_manager (); - - int action - = evmgr.debug_cd_or_addpath_error (file, dir, addpath_option); - - switch (action) - { - case 1: - m_interpreter.chdir (dir); + } + } + + return retval; +} + +bool +load_path::contains_file_in_dir (const std::string& file, + const std::string& dir) +{ + bool ok = false; + bool addpath_option = true; + + std::string curr_dir = sys::env::get_current_directory (); + + if (same_file (curr_dir, dir)) + ok = true; + else + { + bool dir_in_load_path = contains_canonical (dir); + + // get base name, allowing "@class/method.m" (bug #41514) + std::string base_file = (file.length () > dir.length ()) + ? file.substr (dir.length () + 1) + : sys::env::base_pathname (file); + + std::string lp_file = find_file (base_file); + + if (dir_in_load_path) + { + if (same_file (lp_file, file)) ok = true; - break; - - case 2: + } + else + { + // File directory is not in path. Is the file in the path in + // the current directory? If so, then changing the current + // directory will be needed. Adding directory to path is + // not enough because the file in the current directory would + // still be found. + + if (same_file (lp_file, base_file)) { - prepend (dir); - ok = true; + if (same_file (curr_dir, dir)) + ok = true; + else + addpath_option = false; } - break; - - default: - break; - } - } - - return ok; - } - - std::list - load_path::overloads (const std::string& meth) const - { - std::list retval; - - // update (); - - m_top_level_package.overloads (meth, retval); - - for (const auto& nm_ldr : m_package_map) - nm_ldr.second.overloads (meth, retval); - - return retval; - } - - std::list - load_path::get_all_package_names (bool only_top_level) const - { - std::list retval; - - for (const auto& dir_ldr : m_package_map) - { - if (! only_top_level || dir_ldr.first.find ('.') == std::string::npos) - retval.push_back (dir_ldr.first); - } - - return retval; - } - - std::string - load_path::find_file (const std::string& file) const - { - std::string retval; - - if (sys::env::absolute_pathname (file) - || sys::env::rooted_relative_pathname (file)) - { - sys::file_stat fs (file); - - return fs.exists () ? file : retval; - } - else - { - std::string tfile = find_private_file (file); - - if (! tfile.empty ()) - return tfile; - } - - if (file.find_first_of (sys::file_ops::dir_sep_chars ()) - != std::string::npos) - { - // Given name has a directory separator, so append it to each - // element of the load path in turn. - for (const auto& di : m_dir_info_list) - { - std::string tfile = sys::file_ops::concat (di.abs_dir_name, file); - - sys::file_stat fs (tfile); - - if (fs.exists ()) - return tfile; - } - } - else - { - // Look in cache. - for (const auto & di : m_dir_info_list) - { - string_vector all_files = di.all_files; - - octave_idx_type len = all_files.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - if (all_files[i] == file) - return sys::file_ops::concat (di.abs_dir_name, file); - } - } - } - - return retval; - } - - std::string - load_path::find_dir (const std::string& dir) const - { - std::string retval; - - if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos - && (sys::env::absolute_pathname (dir) - || sys::env::rooted_relative_pathname (dir))) - { - sys::file_stat fs (dir); - - if (fs.exists () && fs.is_dir ()) - return dir; - } - else - { - std::string canon_dir = maybe_canonicalize (dir); - for (const auto& di : m_dir_info_list) - { - std::string dname = di.abs_dir_name; - - std::size_t dname_len = dname.length (); - - if (dname.substr (dname_len - 1) - == sys::file_ops::dir_sep_str ()) - { - dname = dname.substr (0, dname_len - 1); - dname_len--; - } - - std::size_t dir_len = canon_dir.length (); - - if (dname_len > dir_len - && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1]) - && canon_dir == dname.substr (dname_len - dir_len)) - { - sys::file_stat fs (di.dir_name); - - if (fs.exists () && fs.is_dir ()) - return di.abs_dir_name; - } - } - } - - return retval; - } - - string_vector - load_path::find_matching_dirs (const std::string& dir) const - { - std::list retlist; - - if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos - && (sys::env::absolute_pathname (dir) - || sys::env::rooted_relative_pathname (dir))) - { - sys::file_stat fs (dir); - - if (fs.exists () && fs.is_dir ()) - retlist.push_back (dir); - } - else - { - std::string canon_dir = maybe_canonicalize (dir); - for (const auto& di : m_dir_info_list) - { - std::string dname = di.abs_dir_name; - - std::size_t dname_len = dname.length (); - - if (dname.substr (dname_len - 1) - == sys::file_ops::dir_sep_str ()) - { - dname = dname.substr (0, dname_len - 1); - dname_len--; - } - - std::size_t dir_len = canon_dir.length (); - - if (dname_len > dir_len - && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1]) - && canon_dir == dname.substr (dname_len - dir_len)) - { - sys::file_stat fs (di.dir_name); - - if (fs.exists () && fs.is_dir ()) - retlist.push_back (di.abs_dir_name); - } - } - } - - return retlist; - } - - std::string - load_path::find_first_of (const string_vector& flist) const - { - std::string retval; - - std::string dir_name; - std::string file_name; - - octave_idx_type flen = flist.numel (); - octave_idx_type rel_flen = 0; - - string_vector rel_flist (flen); - - for (octave_idx_type i = 0; i < flen; i++) - { - std::string file = flist[i]; - - if (file.find_first_of (sys::file_ops::dir_sep_chars ()) - != std::string::npos) - { - if (sys::env::absolute_pathname (file) - || sys::env::rooted_relative_pathname (file)) - { - sys::file_stat fs (file); - - if (fs.exists ()) - return file; - } - else - { - for (const auto& di : m_dir_info_list) - { - std::string tfile; - tfile = sys::file_ops::concat (di.abs_dir_name, file); - - sys::file_stat fs (tfile); - - if (fs.exists ()) - return tfile; - } - } - } - else - rel_flist[rel_flen++] = file; - } - - rel_flist.resize (rel_flen); - - for (const auto& di : m_dir_info_list) - { - string_vector all_files = di.all_files; - - octave_idx_type len = all_files.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - for (octave_idx_type j = 0; j < rel_flen; j++) - { - if (all_files[i] == rel_flist[j]) - { - dir_name = di.abs_dir_name; - file_name = rel_flist[j]; - - goto done; - } - } - } - } - - done: - - if (! dir_name.empty ()) - retval = sys::file_ops::concat (dir_name, file_name); - - return retval; - } - - string_vector - load_path::find_all_first_of (const string_vector& flist) const - { - std::list retlist; - - std::string dir_name; - std::string file_name; - - octave_idx_type flen = flist.numel (); - octave_idx_type rel_flen = 0; - - string_vector rel_flist (flen); - - for (octave_idx_type i = 0; i < flen; i++) - { - std::string file = flist[i]; - - if (file.find_first_of (sys::file_ops::dir_sep_chars ()) - != std::string::npos) + } + } + + if (! ok) + { + event_manager& evmgr = m_interpreter.get_event_manager (); + + int action + = evmgr.debug_cd_or_addpath_error (file, dir, addpath_option); + + switch (action) + { + case 1: + m_interpreter.chdir (dir); + ok = true; + break; + + case 2: { - if (sys::env::absolute_pathname (file) - || sys::env::rooted_relative_pathname (file)) - { - sys::file_stat fs (file); - - if (fs.exists ()) - retlist.push_back (file); - } - else - { - for (const auto& di : m_dir_info_list) - { - std::string tfile; - tfile = sys::file_ops::concat (di.abs_dir_name, file); - - sys::file_stat fs (tfile); - - if (fs.exists ()) - retlist.push_back (tfile); - } - } - } - else - rel_flist[rel_flen++] = file; - } - - rel_flist.resize (rel_flen); - - for (const auto& di : m_dir_info_list) - { - string_vector all_files = di.all_files; - - octave_idx_type len = all_files.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - for (octave_idx_type j = 0; j < rel_flen; j++) - { - if (all_files[i] == rel_flist[j]) - retlist.push_back (sys::file_ops::concat (di.abs_dir_name, - rel_flist[j])); - } - } - } - - return retlist; - } - - string_vector - load_path::dirs (void) const - { - std::size_t len = m_dir_info_list.size (); - - string_vector retval (len); - - octave_idx_type k = 0; - - for (const auto& di : m_dir_info_list) - retval[k++] = di.dir_name; - - return retval; - } - - std::list - load_path::dir_list (void) const - { - std::list retval; - - for (const auto& di : m_dir_info_list) - retval.push_back (di.dir_name); - - return retval; - } - - string_vector - load_path::files (const std::string& dir, bool omit_exts) const - { - string_vector retval; - - const_dir_info_list_iterator p = find_dir_info (dir); - - if (p != m_dir_info_list.end ()) - retval = p->fcn_files; - - if (omit_exts) - { - octave_idx_type len = retval.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - std::string fname = retval[i]; - - std::size_t pos = fname.rfind ('.'); - - if (pos != std::string::npos) - retval[i] = fname.substr (0, pos); - } - } - - return retval; - } - - string_vector - load_path::fcn_names (void) const - { - return m_top_level_package.fcn_names (); - } - - std::string - load_path::path (void) const - { - std::string xpath; - - string_vector xdirs = load_path::dirs (); - - octave_idx_type len = xdirs.numel (); - - if (len > 0) - xpath = xdirs[0]; - - for (octave_idx_type i = 1; i < len; i++) - xpath += directory_path::path_sep_str () + xdirs[i]; - - return xpath; - } - - void - load_path::display (std::ostream& os) const - { - for (const auto& di : m_dir_info_list) - { - string_vector fcn_files = di.fcn_files; - - if (! fcn_files.empty ()) - { - os << "\n*** function files in " << di.dir_name << ":\n\n"; - - fcn_files.list_in_columns (os); - } - - const dir_info::method_file_map_type& method_file_map - = di.method_file_map; - - if (! method_file_map.empty ()) - { - for (const auto& cls_ci : method_file_map) - { - os << "\n*** methods in " << di.dir_name - << "/@" << cls_ci.first << ":\n\n"; - - const dir_info::class_info& ci = cls_ci.second; - - string_vector method_files = get_file_list (ci.method_file_map); - - method_files.list_in_columns (os); - } - } - } - - m_top_level_package.display (os); - - for (const auto& nm_ldr : m_package_map) - nm_ldr.second.display (os); - } - - void - load_path::execute_pkg_add (const std::string& dir) - { - execute_pkg_add_or_del (dir, "PKG_ADD"); - } - - void - load_path::execute_pkg_del (const std::string& dir) - { - execute_pkg_add_or_del (dir, "PKG_DEL"); - } - - void load_path::execute_pkg_add_or_del (const std::string& dir, - const std::string& script_file) - { - if (! octave_interpreter_ready) - return; - - std::string file = sys::file_ops::concat (dir, script_file); - - sys::file_stat fs (file); - - if (fs.exists ()) - source_file (file, "base"); - } - - // FIXME: maybe we should also maintain a map to speed up this method of - // access. - - load_path::const_dir_info_list_iterator - load_path::find_dir_info (const std::string& dir_arg) const - { - std::string dir = sys::file_ops::tilde_expand (dir_arg); - - dir = maybe_canonicalize (dir); - - auto retval = m_dir_info_list.cbegin (); - - while (retval != m_dir_info_list.cend ()) - { - if (retval->dir_name == dir) - break; - - retval++; - } - - return retval; - } - - load_path::dir_info_list_iterator - load_path::find_dir_info (const std::string& dir_arg) - { - std::string dir = sys::file_ops::tilde_expand (dir_arg); - - dir = maybe_canonicalize (dir); - - auto retval = m_dir_info_list.begin (); - - while (retval != m_dir_info_list.end ()) - { - if (retval->dir_name == dir) - break; - - retval++; - } - - return retval; - } - - bool - load_path::contains (const std::string& dir) const - { - return find_dir_info (dir) != m_dir_info_list.end (); - } - - void - load_path::move (dir_info_list_iterator i, bool at_end) - { - if (m_dir_info_list.size () > 1) - { - dir_info di = *i; - - m_dir_info_list.erase (i); - - if (at_end) - m_dir_info_list.push_back (di); - else - m_dir_info_list.push_front (di); - - move (di, at_end); - } - } - - void - load_path::move (const dir_info& di, bool at_end, const std::string& pname) - { - package_info& l = get_package (pname); - - l.move (di, at_end); - - dir_info::package_dir_map_type package_dir_map = di.package_dir_map; - - for (const auto& pkg_di : package_dir_map) - { - std::string full_name = pkg_di.first; - - if (! pname.empty ()) - full_name = pname + '.' + full_name; - - move (pkg_di.second, at_end, full_name); - } - } - - void - load_path::add (const std::string& dir_arg, bool at_end, bool warn) - { - std::size_t len = dir_arg.length (); - - if (len > 1 && dir_arg.substr (len-2) == "//") - warning_with_id ("Octave:recursive-path-search", - "trailing '//' is no longer special in search path elements"); - - std::string dir = sys::file_ops::tilde_expand (dir_arg); - - dir = strip_trailing_separators (dir); - - dir = maybe_canonicalize (dir); - - auto i = find_dir_info (dir); - - if (i != m_dir_info_list.end ()) - move (i, at_end); - else - { - sys::file_stat fs (dir); - - if (fs) - { - if (fs.is_dir ()) - { - read_dir_config (dir); - - dir_info di (dir); - - if (at_end) - m_dir_info_list.push_back (di); - else - m_dir_info_list.push_front (di); - - add (di, at_end); - - if (add_hook) - add_hook (dir); - } - else if (warn) - warning ("addpath: %s: not a directory", dir_arg.c_str ()); - } - else if (warn) - { - std::string msg = fs.error (); - warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ()); + prepend (dir); + ok = true; } - } - - // FIXME: is there a better way to do this? - - i = find_dir_info ("."); - - if (i != m_dir_info_list.end ()) - move (i, false); - } - - void - load_path::remove (const dir_info& di, const std::string& pname) - { - package_info& l = get_package (pname); - - l.remove (di); - - dir_info::package_dir_map_type package_dir_map = di.package_dir_map; - - for (const auto& pkg_di : package_dir_map) - { - std::string full_name = pkg_di.first; - - if (! pname.empty ()) - full_name = pname + '.' + full_name; - - remove (pkg_di.second, full_name); - } - } - - void - load_path::read_dir_config (const std::string& dir) const - { - // use canonicalized path as key - const std::string key = sys::canonicalize_file_name (dir); - - // read file with directory configuration - const std::string - conf_file = key + sys::file_ops::dir_sep_str () + ".oct-config"; - - FILE* cfile = sys::fopen (conf_file, "rb"); - - if (! cfile) - { - // reset directory encoding - input_system& input_sys = __get_input_system__ (); - - std::string enc_val = "delete"; - input_sys.set_dir_encoding (key, enc_val); - return; - } - - unwind_action close_file ([cfile] (void) { fclose (cfile); }); - - // find line with character encoding and read it - bool eof = false; - const std::string enc_prop = "encoding"; - while (! eof) - { - std::string conf_str = fgets (cfile, eof); - - // delete any preceeding whitespace - auto it = std::find_if_not (conf_str.begin (), conf_str.end (), - [] (unsigned char c) - { return std::isblank (c); }); - conf_str.erase (conf_str.begin (), it); - - // match identifier - if (conf_str.compare (0, enc_prop.size (), enc_prop) == 0) - { - // skip delimiter characters - std::size_t pos = conf_str.find_first_not_of (" \t=:", - enc_prop.size ()); - if (pos == std::string::npos) - continue; - - std::string enc_val = conf_str.substr (pos); - - // take alphanumeric and '-' characters - it = std::find_if_not (enc_val.begin (), enc_val.end (), - [] (unsigned char c) - { return std::isalnum (c) || c == '-'; }); - enc_val.erase(it, enc_val.end ()); - - if (enc_val.empty ()) - continue; - - // set encoding for this directory in input system - input_system& input_sys = __get_input_system__ (); - input_sys.set_dir_encoding (key, enc_val); - return; - } - } - - // reset directory encoding - input_system& input_sys = __get_input_system__ (); - - std::string enc_val = "delete"; - input_sys.set_dir_encoding (dir, enc_val); - - } - - bool - load_path::is_package (const std::string& name) const - { - for (const auto& di : m_dir_info_list) - { - if (di.is_package (name)) - return true; - } - - return false; - } - - void - load_path::add (const dir_info& di, bool at_end, - const std::string& pname, bool updating) - { - package_info& l = get_package (pname); - - l.add (di, at_end, updating); - - dir_info::package_dir_map_type package_dir_map = di.package_dir_map; - - for (const auto& pkg_di : package_dir_map) - { - std::string full_name = pkg_di.first; - - if (! pname.empty ()) - full_name = pname + '.' + full_name; - - add (pkg_di.second, at_end, full_name); - } - } - - string_vector - load_path::get_file_list (const load_path::dir_info::fcn_file_map_type& lst) const - { - octave_idx_type n = lst.size (); - - string_vector retval (n); - - octave_idx_type count = 0; - - for (const auto& nm_typ : lst) - { - std::string nm = nm_typ.first; - - int types = nm_typ.second; - - if (types & load_path::OCT_FILE) - nm += ".oct"; - else if (types & load_path::MEX_FILE) - nm += ".mex"; - else - nm += ".m"; - - retval[count++] = nm; - } - - return retval; - } - - load_path::dir_info::fcn_file_map_type - get_fcn_files (const std::string& d) - { - load_path::dir_info::fcn_file_map_type retval; - - string_vector flist; - std::string msg; - - if (! sys::get_dirlist (d, flist, msg)) - warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); - else - { - octave_idx_type len = flist.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - std::string fname = flist[i]; - - std::size_t pos = fname.rfind ('.'); - - if (pos != std::string::npos) - { - std::string base = fname.substr (0, pos); - std::string ext = fname.substr (pos); - - if (valid_identifier (base)) - { - int t = 0; - - if (ext == ".m") - t = load_path::M_FILE; - else if (ext == ".oct") - t = load_path::OCT_FILE; - else if (ext == ".mex") - t = load_path::MEX_FILE; - - if (t) - { - load_path::dir_info::fcn_file_map_iterator p - = retval.find (base); - - if (p == retval.end ()) - retval[base] = t; - else - p->second |= t; - } - } - } - } - } - - return retval; - } - - bool - load_path::dir_info::update (void) - { - sys::file_stat fs (dir_name); - - if (! fs) - { - std::string msg = fs.error (); - warning_with_id ("Octave:load-path:dir-info:update-failed", - "load_path: %s: %s", dir_name.c_str (), msg.c_str ()); - + break; + + default: + break; + } + } + + return ok; +} + +std::list +load_path::overloads (const std::string& meth) const +{ + std::list retval; + + // update (); + + m_top_level_package.overloads (meth, retval); + + for (const auto& nm_ldr : m_package_map) + nm_ldr.second.overloads (meth, retval); + + return retval; +} + +std::list +load_path::get_all_package_names (bool only_top_level) const +{ + std::list retval; + + for (const auto& dir_ldr : m_package_map) + { + if (! only_top_level || dir_ldr.first.find ('.') == std::string::npos) + retval.push_back (dir_ldr.first); + } + + return retval; +} + +std::string +load_path::find_file (const std::string& file) const +{ + std::string retval; + + if (sys::env::absolute_pathname (file) + || sys::env::rooted_relative_pathname (file)) + { + sys::file_stat fs (file); + + return fs.exists () ? file : retval; + } + else + { + std::string tfile = find_private_file (file); + + if (! tfile.empty ()) + return tfile; + } + + if (file.find_first_of (sys::file_ops::dir_sep_chars ()) + != std::string::npos) + { + // Given name has a directory separator, so append it to each + // element of the load path in turn. + for (const auto& di : m_dir_info_list) + { + std::string tfile = sys::file_ops::concat (di.abs_dir_name, file); + + sys::file_stat fs (tfile); + + if (fs.exists ()) + return tfile; + } + } + else + { + // Look in cache. + for (const auto& di : m_dir_info_list) + { + string_vector all_files = di.all_files; + + octave_idx_type len = all_files.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + if (all_files[i] == file) + return sys::file_ops::concat (di.abs_dir_name, file); + } + } + } + + return retval; +} + +std::string +load_path::find_dir (const std::string& dir) const +{ + std::string retval; + + if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos + && (sys::env::absolute_pathname (dir) + || sys::env::rooted_relative_pathname (dir))) + { + sys::file_stat fs (dir); + + if (fs.exists () && fs.is_dir ()) + return dir; + } + else + { + std::string canon_dir = maybe_canonicalize (dir); + for (const auto& di : m_dir_info_list) + { + std::string dname = di.abs_dir_name; + + std::size_t dname_len = dname.length (); + + if (dname.substr (dname_len - 1) + == sys::file_ops::dir_sep_str ()) + { + dname = dname.substr (0, dname_len - 1); + dname_len--; + } + + std::size_t dir_len = canon_dir.length (); + + if (dname_len > dir_len + && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1]) + && canon_dir == dname.substr (dname_len - dir_len)) + { + sys::file_stat fs (di.dir_name); + + if (fs.exists () && fs.is_dir ()) + return di.abs_dir_name; + } + } + } + + return retval; +} + +string_vector +load_path::find_matching_dirs (const std::string& dir) const +{ + std::list retlist; + + if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos + && (sys::env::absolute_pathname (dir) + || sys::env::rooted_relative_pathname (dir))) + { + sys::file_stat fs (dir); + + if (fs.exists () && fs.is_dir ()) + retlist.push_back (dir); + } + else + { + std::string canon_dir = maybe_canonicalize (dir); + for (const auto& di : m_dir_info_list) + { + std::string dname = di.abs_dir_name; + + std::size_t dname_len = dname.length (); + + if (dname.substr (dname_len - 1) + == sys::file_ops::dir_sep_str ()) + { + dname = dname.substr (0, dname_len - 1); + dname_len--; + } + + std::size_t dir_len = canon_dir.length (); + + if (dname_len > dir_len + && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1]) + && canon_dir == dname.substr (dname_len - dir_len)) + { + sys::file_stat fs (di.dir_name); + + if (fs.exists () && fs.is_dir ()) + retlist.push_back (di.abs_dir_name); + } + } + } + + return retlist; +} + +std::string +load_path::find_first_of (const string_vector& flist) const +{ + std::string retval; + + std::string dir_name; + std::string file_name; + + octave_idx_type flen = flist.numel (); + octave_idx_type rel_flen = 0; + + string_vector rel_flist (flen); + + for (octave_idx_type i = 0; i < flen; i++) + { + std::string file = flist[i]; + + if (file.find_first_of (sys::file_ops::dir_sep_chars ()) + != std::string::npos) + { + if (sys::env::absolute_pathname (file) + || sys::env::rooted_relative_pathname (file)) + { + sys::file_stat fs (file); + + if (fs.exists ()) + return file; + } + else + { + for (const auto& di : m_dir_info_list) + { + std::string tfile; + tfile = sys::file_ops::concat (di.abs_dir_name, file); + + sys::file_stat fs (tfile); + + if (fs.exists ()) + return tfile; + } + } + } + else + rel_flist[rel_flen++] = file; + } + + rel_flist.resize (rel_flen); + + for (const auto& di : m_dir_info_list) + { + string_vector all_files = di.all_files; + + octave_idx_type len = all_files.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + for (octave_idx_type j = 0; j < rel_flen; j++) + { + if (all_files[i] == rel_flist[j]) + { + dir_name = di.abs_dir_name; + file_name = rel_flist[j]; + + goto done; + } + } + } + } + +done: + + if (! dir_name.empty ()) + retval = sys::file_ops::concat (dir_name, file_name); + + return retval; +} + +string_vector +load_path::find_all_first_of (const string_vector& flist) const +{ + std::list retlist; + + std::string dir_name; + std::string file_name; + + octave_idx_type flen = flist.numel (); + octave_idx_type rel_flen = 0; + + string_vector rel_flist (flen); + + for (octave_idx_type i = 0; i < flen; i++) + { + std::string file = flist[i]; + + if (file.find_first_of (sys::file_ops::dir_sep_chars ()) + != std::string::npos) + { + if (sys::env::absolute_pathname (file) + || sys::env::rooted_relative_pathname (file)) + { + sys::file_stat fs (file); + + if (fs.exists ()) + retlist.push_back (file); + } + else + { + for (const auto& di : m_dir_info_list) + { + std::string tfile; + tfile = sys::file_ops::concat (di.abs_dir_name, file); + + sys::file_stat fs (tfile); + + if (fs.exists ()) + retlist.push_back (tfile); + } + } + } + else + rel_flist[rel_flen++] = file; + } + + rel_flist.resize (rel_flen); + + for (const auto& di : m_dir_info_list) + { + string_vector all_files = di.all_files; + + octave_idx_type len = all_files.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + for (octave_idx_type j = 0; j < rel_flen; j++) + { + if (all_files[i] == rel_flist[j]) + retlist.push_back (sys::file_ops::concat (di.abs_dir_name, + rel_flist[j])); + } + } + } + + return retlist; +} + +string_vector +load_path::dirs (void) const +{ + std::size_t len = m_dir_info_list.size (); + + string_vector retval (len); + + octave_idx_type k = 0; + + for (const auto& di : m_dir_info_list) + retval[k++] = di.dir_name; + + return retval; +} + +std::list +load_path::dir_list (void) const +{ + std::list retval; + + for (const auto& di : m_dir_info_list) + retval.push_back (di.dir_name); + + return retval; +} + +string_vector +load_path::files (const std::string& dir, bool omit_exts) const +{ + string_vector retval; + + const_dir_info_list_iterator p = find_dir_info (dir); + + if (p != m_dir_info_list.end ()) + retval = p->fcn_files; + + if (omit_exts) + { + octave_idx_type len = retval.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + std::string fname = retval[i]; + + std::size_t pos = fname.rfind ('.'); + + if (pos != std::string::npos) + retval[i] = fname.substr (0, pos); + } + } + + return retval; +} + +string_vector +load_path::fcn_names (void) const +{ + return m_top_level_package.fcn_names (); +} + +std::string +load_path::path (void) const +{ + std::string xpath; + + string_vector xdirs = load_path::dirs (); + + octave_idx_type len = xdirs.numel (); + + if (len > 0) + xpath = xdirs[0]; + + for (octave_idx_type i = 1; i < len; i++) + xpath += directory_path::path_sep_str () + xdirs[i]; + + return xpath; +} + +void +load_path::display (std::ostream& os) const +{ + for (const auto& di : m_dir_info_list) + { + string_vector fcn_files = di.fcn_files; + + if (! fcn_files.empty ()) + { + os << "\n*** function files in " << di.dir_name << ":\n\n"; + + fcn_files.list_in_columns (os); + } + + const dir_info::method_file_map_type& method_file_map + = di.method_file_map; + + if (! method_file_map.empty ()) + { + for (const auto& cls_ci : method_file_map) + { + os << "\n*** methods in " << di.dir_name + << "/@" << cls_ci.first << ":\n\n"; + + const dir_info::class_info& ci = cls_ci.second; + + string_vector method_files = get_file_list (ci.method_file_map); + + method_files.list_in_columns (os); + } + } + } + + m_top_level_package.display (os); + + for (const auto& nm_ldr : m_package_map) + nm_ldr.second.display (os); +} + +void +load_path::execute_pkg_add (const std::string& dir) +{ + execute_pkg_add_or_del (dir, "PKG_ADD"); +} + +void +load_path::execute_pkg_del (const std::string& dir) +{ + execute_pkg_add_or_del (dir, "PKG_DEL"); +} + +void load_path::execute_pkg_add_or_del (const std::string& dir, + const std::string& script_file) +{ + if (! octave_interpreter_ready) + return; + + std::string file = sys::file_ops::concat (dir, script_file); + + sys::file_stat fs (file); + + if (fs.exists ()) + source_file (file, "base"); +} + +// FIXME: maybe we should also maintain a map to speed up this method of +// access. + +load_path::const_dir_info_list_iterator +load_path::find_dir_info (const std::string& dir_arg) const +{ + std::string dir = sys::file_ops::tilde_expand (dir_arg); + + dir = maybe_canonicalize (dir); + + auto retval = m_dir_info_list.cbegin (); + + while (retval != m_dir_info_list.cend ()) + { + if (retval->dir_name == dir) + break; + + retval++; + } + + return retval; +} + +load_path::dir_info_list_iterator +load_path::find_dir_info (const std::string& dir_arg) +{ + std::string dir = sys::file_ops::tilde_expand (dir_arg); + + dir = maybe_canonicalize (dir); + + auto retval = m_dir_info_list.begin (); + + while (retval != m_dir_info_list.end ()) + { + if (retval->dir_name == dir) + break; + + retval++; + } + + return retval; +} + +bool +load_path::contains (const std::string& dir) const +{ + return find_dir_info (dir) != m_dir_info_list.end (); +} + +void +load_path::move (dir_info_list_iterator i, bool at_end) +{ + if (m_dir_info_list.size () > 1) + { + dir_info di = *i; + + m_dir_info_list.erase (i); + + if (at_end) + m_dir_info_list.push_back (di); + else + m_dir_info_list.push_front (di); + + move (di, at_end); + } +} + +void +load_path::move (const dir_info& di, bool at_end, const std::string& pname) +{ + package_info& l = get_package (pname); + + l.move (di, at_end); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (const auto& pkg_di : package_dir_map) + { + std::string full_name = pkg_di.first; + + if (! pname.empty ()) + full_name = pname + '.' + full_name; + + move (pkg_di.second, at_end, full_name); + } +} + +void +load_path::add (const std::string& dir_arg, bool at_end, bool warn) +{ + std::size_t len = dir_arg.length (); + + if (len > 1 && dir_arg.substr (len-2) == "//") + warning_with_id ("Octave:recursive-path-search", + "trailing '//' is no longer special in search path elements"); + + std::string dir = sys::file_ops::tilde_expand (dir_arg); + + dir = strip_trailing_separators (dir); + + dir = maybe_canonicalize (dir); + + auto i = find_dir_info (dir); + + if (i != m_dir_info_list.end ()) + move (i, at_end); + else + { + sys::file_stat fs (dir); + + if (fs) + { + if (fs.is_dir ()) + { + read_dir_config (dir); + + dir_info di (dir); + + if (at_end) + m_dir_info_list.push_back (di); + else + m_dir_info_list.push_front (di); + + add (di, at_end); + + if (add_hook) + add_hook (dir); + } + else if (warn) + warning ("addpath: %s: not a directory", dir_arg.c_str ()); + } + else if (warn) + { + std::string msg = fs.error (); + warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ()); + } + } + + // FIXME: is there a better way to do this? + + i = find_dir_info ("."); + + if (i != m_dir_info_list.end ()) + move (i, false); +} + +void +load_path::remove (const dir_info& di, const std::string& pname) +{ + package_info& l = get_package (pname); + + l.remove (di); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (const auto& pkg_di : package_dir_map) + { + std::string full_name = pkg_di.first; + + if (! pname.empty ()) + full_name = pname + '.' + full_name; + + remove (pkg_di.second, full_name); + } +} + +void +load_path::read_dir_config (const std::string& dir) const +{ + // use canonicalized path as key + const std::string key = sys::canonicalize_file_name (dir); + + // read file with directory configuration + const std::string + conf_file = key + sys::file_ops::dir_sep_str () + ".oct-config"; + + FILE *cfile = sys::fopen (conf_file, "rb"); + + if (! cfile) + { + // reset directory encoding + input_system& input_sys = __get_input_system__ (); + + std::string enc_val = "delete"; + input_sys.set_dir_encoding (key, enc_val); + return; + } + + unwind_action close_file ([cfile] (void) { fclose (cfile); }); + + // find line with character encoding and read it + bool eof = false; + const std::string enc_prop = "encoding"; + while (! eof) + { + std::string conf_str = fgets (cfile, eof); + + // delete any preceeding whitespace + auto it = std::find_if_not (conf_str.begin (), conf_str.end (), + [] (unsigned char c) + { return std::isblank (c); }); + conf_str.erase (conf_str.begin (), it); + + // match identifier + if (conf_str.compare (0, enc_prop.size (), enc_prop) == 0) + { + // skip delimiter characters + std::size_t pos = conf_str.find_first_not_of (" \t=:", + enc_prop.size ()); + if (pos == std::string::npos) + continue; + + std::string enc_val = conf_str.substr (pos); + + // take alphanumeric and '-' characters + it = std::find_if_not (enc_val.begin (), enc_val.end (), + [] (unsigned char c) + { return std::isalnum (c) || c == '-'; }); + enc_val.erase(it, enc_val.end ()); + + if (enc_val.empty ()) + continue; + + // set encoding for this directory in input system + input_system& input_sys = __get_input_system__ (); + input_sys.set_dir_encoding (key, enc_val); + return; + } + } + + // reset directory encoding + input_system& input_sys = __get_input_system__ (); + + std::string enc_val = "delete"; + input_sys.set_dir_encoding (dir, enc_val); + +} + +bool +load_path::is_package (const std::string& name) const +{ + for (const auto& di : m_dir_info_list) + { + if (di.is_package (name)) + return true; + } + + return false; +} + +void +load_path::add (const dir_info& di, bool at_end, + const std::string& pname, bool updating) +{ + package_info& l = get_package (pname); + + l.add (di, at_end, updating); + + dir_info::package_dir_map_type package_dir_map = di.package_dir_map; + + for (const auto& pkg_di : package_dir_map) + { + std::string full_name = pkg_di.first; + + if (! pname.empty ()) + full_name = pname + '.' + full_name; + + add (pkg_di.second, at_end, full_name); + } +} + +string_vector +load_path::get_file_list (const load_path::dir_info::fcn_file_map_type& lst) const +{ + octave_idx_type n = lst.size (); + + string_vector retval (n); + + octave_idx_type count = 0; + + for (const auto& nm_typ : lst) + { + std::string nm = nm_typ.first; + + int types = nm_typ.second; + + if (types & load_path::OCT_FILE) + nm += ".oct"; + else if (types & load_path::MEX_FILE) + nm += ".mex"; + else + nm += ".m"; + + retval[count++] = nm; + } + + return retval; +} + +load_path::dir_info::fcn_file_map_type +get_fcn_files (const std::string& d) +{ + load_path::dir_info::fcn_file_map_type retval; + + string_vector flist; + std::string msg; + + if (! sys::get_dirlist (d, flist, msg)) + warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); + else + { + octave_idx_type len = flist.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + std::string fname = flist[i]; + + std::size_t pos = fname.rfind ('.'); + + if (pos != std::string::npos) + { + std::string base = fname.substr (0, pos); + std::string ext = fname.substr (pos); + + if (valid_identifier (base)) + { + int t = 0; + + if (ext == ".m") + t = load_path::M_FILE; + else if (ext == ".oct") + t = load_path::OCT_FILE; + else if (ext == ".mex") + t = load_path::MEX_FILE; + + if (t) + { + load_path::dir_info::fcn_file_map_iterator p + = retval.find (base); + + if (p == retval.end ()) + retval[base] = t; + else + p->second |= t; + } + } + } + } + } + + return retval; +} + +bool +load_path::dir_info::update (void) +{ + sys::file_stat fs (dir_name); + + if (! fs) + { + std::string msg = fs.error (); + warning_with_id ("Octave:load-path:dir-info:update-failed", + "load_path: %s: %s", dir_name.c_str (), msg.c_str ()); + + return false; + } + + if (is_relative) + { + try + { + std::string abs_name = sys::canonicalize_file_name (dir_name); + + const_abs_dir_cache_iterator p = s_abs_dir_cache.find (abs_name); + + if (p != s_abs_dir_cache.end ()) + { + // The directory is in the cache of all directories we have + // visited (indexed by absolute name). If it is out of date, + // initialize it. Otherwise, copy the info from the cache. + // By doing that, we avoid unnecessary calls to stat that can + // slow things down tremendously for large directories. + const dir_info& di = p->second; + + if ((fs.mtime () + fs.time_resolution () + > di.dir_time_last_checked) + || subdirs_modified (dir_name, dir_time_last_checked)) + initialize (); + else + { + // Copy over info from cache, but leave dir_name and + // is_relative unmodified. + abs_dir_name = di.abs_dir_name; + dir_mtime = di.dir_mtime; + dir_time_last_checked = di.dir_time_last_checked; + all_files = di.all_files; + fcn_files = di.fcn_files; + private_file_map = di.private_file_map; + method_file_map = di.method_file_map; + package_dir_map = di.package_dir_map; + } + } + else + { + // We haven't seen this directory before. + initialize (); + } + } + catch (const execution_exception& ee) + { + // Skip updating if we don't know where we are, but don't + // treat it as an error. + + interpreter& interp = __get_interpreter__ (); + + interp.recover_from_exception (); + } + } + // Absolute path, check timestamp to see whether it requires re-caching + else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked + || subdirs_modified (dir_name, dir_time_last_checked)) + initialize (); + + return true; +} + +bool +load_path::dir_info::is_package (const std::string& name) const +{ + std::size_t pos = name.find ('.'); + + if (pos == std::string::npos) + return package_dir_map.find (name) != package_dir_map.end (); + else + { + std::string name_head = name.substr (0, pos); + std::string name_tail = name.substr (pos + 1); + + const_package_dir_map_iterator it = package_dir_map.find (name_head); + + if (it != package_dir_map.end ()) + return it->second.is_package (name_tail); + else return false; - } - - if (is_relative) - { - try - { - std::string abs_name = sys::canonicalize_file_name (dir_name); - - const_abs_dir_cache_iterator p = s_abs_dir_cache.find (abs_name); - - if (p != s_abs_dir_cache.end ()) - { - // The directory is in the cache of all directories we have - // visited (indexed by absolute name). If it is out of date, - // initialize it. Otherwise, copy the info from the cache. - // By doing that, we avoid unnecessary calls to stat that can - // slow things down tremendously for large directories. - const dir_info& di = p->second; - - if ((fs.mtime () + fs.time_resolution () - > di.dir_time_last_checked) - || subdirs_modified (dir_name, dir_time_last_checked)) - initialize (); - else - { - // Copy over info from cache, but leave dir_name and - // is_relative unmodified. - abs_dir_name = di.abs_dir_name; - dir_mtime = di.dir_mtime; - dir_time_last_checked = di.dir_time_last_checked; - all_files = di.all_files; - fcn_files = di.fcn_files; - private_file_map = di.private_file_map; - method_file_map = di.method_file_map; - package_dir_map = di.package_dir_map; - } - } - else - { - // We haven't seen this directory before. - initialize (); - } - } - catch (const execution_exception& ee) - { - // Skip updating if we don't know where we are, but don't - // treat it as an error. - - interpreter& interp = __get_interpreter__ (); - - interp.recover_from_exception (); - } - } - // Absolute path, check timestamp to see whether it requires re-caching - else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked - || subdirs_modified (dir_name, dir_time_last_checked)) - initialize (); - - return true; - } - - bool - load_path::dir_info::is_package (const std::string& name) const - { - std::size_t pos = name.find ('.'); - - if (pos == std::string::npos) - return package_dir_map.find (name) != package_dir_map.end (); - else - { - std::string name_head = name.substr (0, pos); - std::string name_tail = name.substr (pos + 1); - - const_package_dir_map_iterator it = package_dir_map.find (name_head); - - if (it != package_dir_map.end ()) - return it->second.is_package (name_tail); - else - return false; - } - } - - void - load_path::dir_info::initialize (void) - { - is_relative = ! sys::env::absolute_pathname (dir_name); - - dir_time_last_checked = sys::time (static_cast (0)); - - sys::file_stat fs (dir_name); - - if (fs) - { - method_file_map.clear (); - package_dir_map.clear (); - - dir_mtime = fs.mtime (); - dir_time_last_checked = sys::time (); - - get_file_list (dir_name); - - try - { - abs_dir_name = sys::canonicalize_file_name (dir_name); - - // FIXME: nothing is ever removed from this cache of - // directory information, so there could be some resource - // problems. Perhaps it should be pruned from time to time. - - s_abs_dir_cache[abs_dir_name] = *this; - } - catch (const execution_exception&) - { - // Skip updating if we don't know where we are but don't treat - // it as an error. - - interpreter& interp = __get_interpreter__ (); - - interp.recover_from_exception (); - } - } - else - { - std::string msg = fs.error (); - warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ()); - } - } - - void - load_path::dir_info::get_file_list (const std::string& d) - { - string_vector flist; - std::string msg; - - if (! sys::get_dirlist (d, flist, msg)) - { - warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); - return; - } - - octave_idx_type len = flist.numel (); - - all_files.resize (len); - fcn_files.resize (len); - - octave_idx_type all_files_count = 0; - octave_idx_type fcn_files_count = 0; - - for (octave_idx_type i = 0; i < len; i++) - { - std::string fname = flist[i]; - - std::string full_name = sys::file_ops::concat (d, fname); - - sys::file_stat fs (full_name); - - if (fs) - { - if (fs.is_dir ()) - { - if (fname == "private") - get_private_file_map (full_name); - else if (fname[0] == '@') - get_method_file_map (full_name, fname.substr (1)); - else if (fname[0] == '+') - get_package_dir (full_name, fname.substr (1)); - } - else - { - all_files[all_files_count++] = fname; - - std::size_t pos = fname.rfind ('.'); - - if (pos != std::string::npos) - { - std::string ext = fname.substr (pos); - - if (ext == ".m" || ext == ".oct" || ext == ".mex") - { - std::string base = fname.substr (0, pos); - - if (valid_identifier (base)) - fcn_files[fcn_files_count++] = fname; - } - } - } - } - } - - all_files.resize (all_files_count); - fcn_files.resize (fcn_files_count); - } - - void - load_path::dir_info::get_private_file_map (const std::string& d) - { - private_file_map = get_fcn_files (d); - } - - void - load_path::dir_info::get_method_file_map (const std::string& d, - const std::string& class_name) - { - method_file_map[class_name].method_file_map = get_fcn_files (d); - - std::string pd = sys::file_ops::concat (d, "private"); - - sys::file_stat fs (pd); - - if (fs && fs.is_dir ()) - method_file_map[class_name].private_file_map = get_fcn_files (pd); - } - - void - load_path::dir_info::get_package_dir (const std::string& d, - const std::string& package_name) - { - package_dir_map[package_name] = dir_info (d); - } - - void - load_path::package_info::move (const dir_info& di, bool at_end) - { - std::string dir_name = di.abs_dir_name; - - auto s = std::find (m_dir_list.begin (), m_dir_list.end (), dir_name); - - if (s != m_dir_list.end ()) - { - m_dir_list.erase (s); - - if (at_end) - m_dir_list.push_back (dir_name); - else - m_dir_list.push_front (dir_name); - } - - move_fcn_map (dir_name, di.fcn_files, at_end); - - // No need to move elements of private function map. - - move_method_map (dir_name, at_end); - } - - void - load_path::package_info::remove (const dir_info& di) - { - std::string dir = di.abs_dir_name; - - string_vector fcn_files = di.fcn_files; - - m_dir_list.remove (dir); - - remove_fcn_map (dir, fcn_files); - - remove_private_fcn_map (dir); - - remove_method_map (dir); - } - - void - load_path::package_info::display (std::ostream& os) const - { - os << "*** package_info: " - << (m_package_name.empty () ? "" : m_package_name) - << "\n\n"; - - for (const auto& dir : m_dir_list) - os << dir << "\n"; - os << "\n"; - - for (const auto& dir_fnlst : m_private_fcn_map) - { - os << "\n*** private functions in " - << sys::file_ops::concat (dir_fnlst.first, "private") - << ":\n\n"; - - print_fcn_list (os, dir_fnlst.second); - } + } +} + +void +load_path::dir_info::initialize (void) +{ + is_relative = ! sys::env::absolute_pathname (dir_name); + + dir_time_last_checked = sys::time (static_cast (0)); + + sys::file_stat fs (dir_name); + + if (fs) + { + method_file_map.clear (); + package_dir_map.clear (); + + dir_mtime = fs.mtime (); + dir_time_last_checked = sys::time (); + + get_file_list (dir_name); + + try + { + abs_dir_name = sys::canonicalize_file_name (dir_name); + + // FIXME: nothing is ever removed from this cache of + // directory information, so there could be some resource + // problems. Perhaps it should be pruned from time to time. + + s_abs_dir_cache[abs_dir_name] = *this; + } + catch (const execution_exception&) + { + // Skip updating if we don't know where we are but don't treat + // it as an error. + + interpreter& interp = __get_interpreter__ (); + + interp.recover_from_exception (); + } + } + else + { + std::string msg = fs.error (); + warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ()); + } +} + +void +load_path::dir_info::get_file_list (const std::string& d) +{ + string_vector flist; + std::string msg; + + if (! sys::get_dirlist (d, flist, msg)) + { + warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); + return; + } + + octave_idx_type len = flist.numel (); + + all_files.resize (len); + fcn_files.resize (len); + + octave_idx_type all_files_count = 0; + octave_idx_type fcn_files_count = 0; + + for (octave_idx_type i = 0; i < len; i++) + { + std::string fname = flist[i]; + + std::string full_name = sys::file_ops::concat (d, fname); + + sys::file_stat fs (full_name); + + if (fs) + { + if (fs.is_dir ()) + { + if (fname == "private") + get_private_file_map (full_name); + else if (fname[0] == '@') + get_method_file_map (full_name, fname.substr (1)); + else if (fname[0] == '+') + get_package_dir (full_name, fname.substr (1)); + } + else + { + all_files[all_files_count++] = fname; + + std::size_t pos = fname.rfind ('.'); + + if (pos != std::string::npos) + { + std::string ext = fname.substr (pos); + + if (ext == ".m" || ext == ".oct" || ext == ".mex") + { + std::string base = fname.substr (0, pos); + + if (valid_identifier (base)) + fcn_files[fcn_files_count++] = fname; + } + } + } + } + } + + all_files.resize (all_files_count); + fcn_files.resize (fcn_files_count); +} + +void +load_path::dir_info::get_private_file_map (const std::string& d) +{ + private_file_map = get_fcn_files (d); +} + +void +load_path::dir_info::get_method_file_map (const std::string& d, + const std::string& class_name) +{ + method_file_map[class_name].method_file_map = get_fcn_files (d); + + std::string pd = sys::file_ops::concat (d, "private"); + + sys::file_stat fs (pd); + + if (fs && fs.is_dir ()) + method_file_map[class_name].private_file_map = get_fcn_files (pd); +} + +void +load_path::dir_info::get_package_dir (const std::string& d, + const std::string& package_name) +{ + package_dir_map[package_name] = dir_info (d); +} + +void +load_path::package_info::move (const dir_info& di, bool at_end) +{ + std::string dir_name = di.abs_dir_name; + + auto s = std::find (m_dir_list.begin (), m_dir_list.end (), dir_name); + + if (s != m_dir_list.end ()) + { + m_dir_list.erase (s); + + if (at_end) + m_dir_list.push_back (dir_name); + else + m_dir_list.push_front (dir_name); + } + + move_fcn_map (dir_name, di.fcn_files, at_end); + + // No need to move elements of private function map. + + move_method_map (dir_name, at_end); +} + +void +load_path::package_info::remove (const dir_info& di) +{ + std::string dir = di.abs_dir_name; + + string_vector fcn_files = di.fcn_files; + + m_dir_list.remove (dir); + + remove_fcn_map (dir, fcn_files); + + remove_private_fcn_map (dir); + + remove_method_map (dir); +} + +void +load_path::package_info::display (std::ostream& os) const +{ + os << "*** package_info: " + << (m_package_name.empty () ? "" : m_package_name) + << "\n\n"; + + for (const auto& dir : m_dir_list) + os << dir << "\n"; + os << "\n"; + + for (const auto& dir_fnlst : m_private_fcn_map) + { + os << "\n*** private functions in " + << sys::file_ops::concat (dir_fnlst.first, "private") + << ":\n\n"; + + print_fcn_list (os, dir_fnlst.second); + } #if defined (DEBUG_LOAD_PATH) - for (const auto& nm_filst : m_fcn_map) - { - os << nm_filst.first << ":\n"; - - const file_info_list_type& file_info_list = nm_filst.second; - - for (const auto& finfo : file_info_list) - { - os << " " << finfo.dir_name << " ("; - - print_types (os, finfo.types); - - os << ")\n"; - } - } - - for (const auto& cls_fnmap : m_method_map) - { - os << "CLASS " << cls_fnmap.first << ":\n"; - - const fcn_map_type& fm = cls_fnmap.second; - - for (const auto& nm_fnlst : m_fcn_map) - { - os << " " << nm_fnlst.first << ":\n"; - - const file_info_list_type& file_info_list = nm_fnlst.second; - - for (const auto& finfo : file_info_list) - { - os << " " << finfo.dir_name << " ("; - - print_types (os, finfo.types); - - os << ")\n"; - } - } - } - - os << "\n"; + for (const auto& nm_filst : m_fcn_map) + { + os << nm_filst.first << ":\n"; + + const file_info_list_type& file_info_list = nm_filst.second; + + for (const auto& finfo : file_info_list) + { + os << " " << finfo.dir_name << " ("; + + print_types (os, finfo.types); + + os << ")\n"; + } + } + + for (const auto& cls_fnmap : m_method_map) + { + os << "CLASS " << cls_fnmap.first << ":\n"; + + const fcn_map_type& fm = cls_fnmap.second; + + for (const auto& nm_fnlst : m_fcn_map) + { + os << " " << nm_fnlst.first << ":\n"; + + const file_info_list_type& file_info_list = nm_fnlst.second; + + for (const auto& finfo : file_info_list) + { + os << " " << finfo.dir_name << " ("; + + print_types (os, finfo.types); + + os << ")\n"; + } + } + } + + os << "\n"; #endif - } - - std::string - load_path::package_info::find_fcn (const std::string& fcn, - std::string& dir_name, - int type) const - { - std::string retval; - - // update (); - - if (fcn.length () > 0 && fcn[0] == '@') - { - std::size_t pos = fcn.find ('/'); - - if (pos != std::string::npos) - { - std::string class_name = fcn.substr (1, pos-1); - std::string meth = fcn.substr (pos+1); - - retval = find_method (class_name, meth, dir_name); - } - else - retval = ""; - } - else - { - dir_name = ""; - - const_fcn_map_iterator p = m_fcn_map.find (fcn); - - if (p != m_fcn_map.end ()) - { - const file_info_list_type& file_info_list = p->second; - - for (const auto& fi : file_info_list) - { - retval = sys::file_ops::concat (fi.dir_name, fcn); - - if (check_file_type (retval, type, fi.types, - fcn, "load_path::find_fcn")) - { - dir_name = fi.dir_name; - break; - } - else - retval = ""; - } - } - } - - return retval; - } - - std::string - load_path::package_info::find_private_fcn (const std::string& dir, - const std::string& fcn, - int type) const - { - std::string retval; - - // update (); - - const_private_fcn_map_iterator q = m_private_fcn_map.find (dir); - - if (q != m_private_fcn_map.end ()) - { - const dir_info::fcn_file_map_type& fcn_file_map = q->second; - - dir_info::const_fcn_file_map_iterator p = fcn_file_map.find (fcn); - - if (p != fcn_file_map.end ()) - { - std::string fname - = sys::file_ops::concat (sys::file_ops::concat (dir, "private"), - fcn); - - if (check_file_type (fname, type, p->second, fcn, - "load_path::find_private_fcn")) - retval = fname; - } - } - - return retval; - } - - std::string - load_path::package_info::find_method (const std::string& class_name, - const std::string& meth, - std::string& dir_name, - int type) const - { - std::string retval; - - // update (); - - dir_name = ""; - - const_method_map_iterator q = m_method_map.find (class_name); - - if (q != m_method_map.end ()) - { - const fcn_map_type& m = q->second; - - const_fcn_map_iterator p = m.find (meth); - - if (p != m.end ()) - { - const file_info_list_type& file_info_list = p->second; - - for (const auto& fi : file_info_list) - { - retval = sys::file_ops::concat (fi.dir_name, meth); - - bool found = check_file_type (retval, type, fi.types, - meth, "load_path::find_method"); - - if (found) - { - dir_name = fi.dir_name; - break; - } - else - retval = ""; - } - } - } - - return retval; - } - - std::list - load_path::package_info::methods (const std::string& class_name) const - { - std::list retval; - - // update (); - - const_method_map_iterator mtd_map_it = m_method_map.find (class_name); - - if (mtd_map_it != m_method_map.end ()) - { - for (const auto& nm_filst : mtd_map_it->second) - retval.push_back (nm_filst.first); - } - - if (! retval.empty ()) - retval.sort (); - - return retval; - } - - void - load_path::package_info::overloads (const std::string& meth, - std::list& l) const - { - for (const auto& cls_fnmap : m_method_map) - { - const fcn_map_type& m = cls_fnmap.second; - - if (m.find (meth) != m.end ()) - { - std::string class_name = cls_fnmap.first; - - if (! m_package_name.empty ()) - class_name = m_package_name + '.' + class_name; - - l.push_back (class_name); - } - } - } - - string_vector - load_path::package_info::fcn_names (void) const - { - std::size_t len = m_fcn_map.size (); - - string_vector retval (len); - - octave_idx_type count = 0; - - for (const auto& nm_filst : m_fcn_map) - retval[count++] = nm_filst.first; - - return retval; - } - - void - load_path::package_info::add_to_fcn_map (const dir_info& di, - bool at_end, bool updating) - { - std::string dir_name = di.abs_dir_name; - - string_vector fcn_files = di.fcn_files; - - octave_idx_type len = fcn_files.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - std::string fname = fcn_files[i]; - - std::string ext; - std::string base = fname; - - std::size_t pos = fname.rfind ('.'); - - if (pos != std::string::npos) - { - base = fname.substr (0, pos); - ext = fname.substr (pos); - } - - file_info_list_type& file_info_list = m_fcn_map[base]; - - auto p = file_info_list.begin (); - - while (p != file_info_list.end ()) - { - if (p->dir_name == dir_name) - break; - - p++; - } - - int t = 0; - if (ext == ".m") - t = load_path::M_FILE; - else if (ext == ".oct") - t = load_path::OCT_FILE; - else if (ext == ".mex") - t = load_path::MEX_FILE; - - if (p == file_info_list.end ()) - { - // Warn if a built-in or library function is being shadowed, - // but not if we are just updating (rehashing) the list. - - if (! updating) - { - if (file_info_list.empty ()) - { - symbol_table& symtab = __get_symbol_table__ (); - - if (symtab.is_built_in_function_name (base)) - { - std::string fcn_path = sys::file_ops::concat (dir_name, - fname); - - warning_with_id ("Octave:shadowed-function", - "function %s shadows a built-in function", - fcn_path.c_str ()); - } - } - else if (! at_end) - { - file_info& old = file_info_list.front (); - - // FIXME: do we need to be more careful about the - // way we look for old.dir_name in sys_path to avoid - // partial matches? - - // Don't warn about Contents.m files since we expect - // more than one to exist in the load path. - - if (fname != "Contents.m" - && s_sys_path.find (old.dir_name) != std::string::npos - && in_path_list (s_sys_path, old.dir_name)) - { - std::string fcn_path = sys::file_ops::concat (dir_name, - fname); - - warning_with_id ("Octave:shadowed-function", - "function %s shadows a core library function", - fcn_path.c_str ()); - } - } - } - - file_info fi (dir_name, t); - - if (at_end) - file_info_list.push_back (fi); - else - file_info_list.push_front (fi); - } - else - { - file_info& fi = *p; - - fi.types |= t; - } - } - } - - void - load_path::package_info::add_to_private_fcn_map (const dir_info& di) - { - dir_info::fcn_file_map_type private_file_map = di.private_file_map; - - if (! private_file_map.empty ()) - m_private_fcn_map[di.abs_dir_name] = private_file_map; - } - - void - load_path::package_info::add_to_method_map (const dir_info& di, bool at_end) - { - std::string dir_name = di.abs_dir_name; - - // - dir_info::method_file_map_type method_file_map = di.method_file_map; - - for (const auto& cls_ci : method_file_map) - { - std::string class_name = cls_ci.first; - - fcn_map_type& fm = m_method_map[class_name]; - - std::string full_dir_name - = sys::file_ops::concat (dir_name, '@' + class_name); - - const dir_info::class_info& ci = cls_ci.second; - - // - const dir_info::fcn_file_map_type& m = ci.method_file_map; - - for (const auto& nm_typ : m) - { - std::string base = nm_typ.first; - int types = nm_typ.second; - - file_info_list_type& file_info_list = fm[base]; - - auto p2 = file_info_list.begin (); - while (p2 != file_info_list.end ()) - { - if (p2->dir_name == full_dir_name) +} + +std::string +load_path::package_info::find_fcn (const std::string& fcn, + std::string& dir_name, + int type) const +{ + std::string retval; + + // update (); + + if (fcn.length () > 0 && fcn[0] == '@') + { + std::size_t pos = fcn.find ('/'); + + if (pos != std::string::npos) + { + std::string class_name = fcn.substr (1, pos-1); + std::string meth = fcn.substr (pos+1); + + retval = find_method (class_name, meth, dir_name); + } + else + retval = ""; + } + else + { + dir_name = ""; + + const_fcn_map_iterator p = m_fcn_map.find (fcn); + + if (p != m_fcn_map.end ()) + { + const file_info_list_type& file_info_list = p->second; + + for (const auto& fi : file_info_list) + { + retval = sys::file_ops::concat (fi.dir_name, fcn); + + if (check_file_type (retval, type, fi.types, + fcn, "load_path::find_fcn")) + { + dir_name = fi.dir_name; + break; + } + else + retval = ""; + } + } + } + + return retval; +} + +std::string +load_path::package_info::find_private_fcn (const std::string& dir, + const std::string& fcn, + int type) const +{ + std::string retval; + + // update (); + + const_private_fcn_map_iterator q = m_private_fcn_map.find (dir); + + if (q != m_private_fcn_map.end ()) + { + const dir_info::fcn_file_map_type& fcn_file_map = q->second; + + dir_info::const_fcn_file_map_iterator p = fcn_file_map.find (fcn); + + if (p != fcn_file_map.end ()) + { + std::string fname + = sys::file_ops::concat (sys::file_ops::concat (dir, "private"), + fcn); + + if (check_file_type (fname, type, p->second, fcn, + "load_path::find_private_fcn")) + retval = fname; + } + } + + return retval; +} + +std::string +load_path::package_info::find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, + int type) const +{ + std::string retval; + + // update (); + + dir_name = ""; + + const_method_map_iterator q = m_method_map.find (class_name); + + if (q != m_method_map.end ()) + { + const fcn_map_type& m = q->second; + + const_fcn_map_iterator p = m.find (meth); + + if (p != m.end ()) + { + const file_info_list_type& file_info_list = p->second; + + for (const auto& fi : file_info_list) + { + retval = sys::file_ops::concat (fi.dir_name, meth); + + bool found = check_file_type (retval, type, fi.types, + meth, "load_path::find_method"); + + if (found) + { + dir_name = fi.dir_name; break; - - p2++; - } - - if (p2 == file_info_list.end ()) - { - file_info fi (full_dir_name, types); - - if (at_end) - file_info_list.push_back (fi); - else - file_info_list.push_front (fi); - } - else - { - // FIXME: is this possible? - file_info& fi = *p2; - - fi.types = types; - } - } - - // - dir_info::fcn_file_map_type private_file_map = ci.private_file_map; - - if (! private_file_map.empty ()) - m_private_fcn_map[full_dir_name] = private_file_map; - } - } - - void - load_path::package_info::move_fcn_map (const std::string& dir_name, - const string_vector& fcn_files, - bool at_end) - { - octave_idx_type len = fcn_files.numel (); - - for (octave_idx_type k = 0; k < len; k++) - { - std::string fname = fcn_files[k]; - - std::string ext; - std::string base = fname; - - std::size_t pos = fname.rfind ('.'); - - if (pos != std::string::npos) - { - base = fname.substr (0, pos); - ext = fname.substr (pos); - } - - file_info_list_type& file_info_list = m_fcn_map[base]; - - if (file_info_list.size () == 1) - continue; - else - { - for (auto fi_it = file_info_list.begin (); - fi_it != file_info_list.end (); - fi_it++) - { - if (fi_it->dir_name == dir_name) - { - file_info fi_tmp = *fi_it; - - file_info_list.erase (fi_it); - - if (at_end) - file_info_list.push_back (fi_tmp); - else - file_info_list.push_front (fi_tmp); - - break; - } - } - } - } - } - - void - load_path::package_info::move_method_map (const std::string& dir_name, - bool at_end) - { - for (auto& cls_fnmap : m_method_map) - { - std::string class_name = cls_fnmap.first; - - fcn_map_type& fn_map = cls_fnmap.second; - - std::string full_dir_name - = sys::file_ops::concat (dir_name, '@' + class_name); - - for (auto& nm_filst : fn_map) - { - file_info_list_type& file_info_list = nm_filst.second; - - if (file_info_list.size () == 1) - continue; - else - { - for (auto fi_it = file_info_list.begin (); - fi_it != file_info_list.end (); fi_it++) - { - if (fi_it->dir_name == full_dir_name) - { - file_info fi_tmp = *fi_it; - - file_info_list.erase (fi_it); - - if (at_end) - file_info_list.push_back (fi_tmp); - else - file_info_list.push_front (fi_tmp); - - break; - } - } - } - } - } - } - - void - load_path::package_info::remove_fcn_map (const std::string& dir, - const string_vector& fcn_files) - { - octave_idx_type len = fcn_files.numel (); - - for (octave_idx_type k = 0; k < len; k++) - { - std::string fname = fcn_files[k]; - - std::string ext; - std::string base = fname; - - std::size_t pos = fname.rfind ('.'); - - if (pos != std::string::npos) - { - base = fname.substr (0, pos); - ext = fname.substr (pos); - } - - file_info_list_type& file_info_list = m_fcn_map[base]; - - for (auto fi_it = file_info_list.begin (); - fi_it != file_info_list.end (); - fi_it++) - { - if (fi_it->dir_name == dir) - { - file_info_list.erase (fi_it); - - if (file_info_list.empty ()) - m_fcn_map.erase (fname); - + } + else + retval = ""; + } + } + } + + return retval; +} + +std::list +load_path::package_info::methods (const std::string& class_name) const +{ + std::list retval; + + // update (); + + const_method_map_iterator mtd_map_it = m_method_map.find (class_name); + + if (mtd_map_it != m_method_map.end ()) + { + for (const auto& nm_filst : mtd_map_it->second) + retval.push_back (nm_filst.first); + } + + if (! retval.empty ()) + retval.sort (); + + return retval; +} + +void +load_path::package_info::overloads (const std::string& meth, + std::list& l) const +{ + for (const auto& cls_fnmap : m_method_map) + { + const fcn_map_type& m = cls_fnmap.second; + + if (m.find (meth) != m.end ()) + { + std::string class_name = cls_fnmap.first; + + if (! m_package_name.empty ()) + class_name = m_package_name + '.' + class_name; + + l.push_back (class_name); + } + } +} + +string_vector +load_path::package_info::fcn_names (void) const +{ + std::size_t len = m_fcn_map.size (); + + string_vector retval (len); + + octave_idx_type count = 0; + + for (const auto& nm_filst : m_fcn_map) + retval[count++] = nm_filst.first; + + return retval; +} + +void +load_path::package_info::add_to_fcn_map (const dir_info& di, + bool at_end, bool updating) +{ + std::string dir_name = di.abs_dir_name; + + string_vector fcn_files = di.fcn_files; + + octave_idx_type len = fcn_files.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + std::string fname = fcn_files[i]; + + std::string ext; + std::string base = fname; + + std::size_t pos = fname.rfind ('.'); + + if (pos != std::string::npos) + { + base = fname.substr (0, pos); + ext = fname.substr (pos); + } + + file_info_list_type& file_info_list = m_fcn_map[base]; + + auto p = file_info_list.begin (); + + while (p != file_info_list.end ()) + { + if (p->dir_name == dir_name) + break; + + p++; + } + + int t = 0; + if (ext == ".m") + t = load_path::M_FILE; + else if (ext == ".oct") + t = load_path::OCT_FILE; + else if (ext == ".mex") + t = load_path::MEX_FILE; + + if (p == file_info_list.end ()) + { + // Warn if a built-in or library function is being shadowed, + // but not if we are just updating (rehashing) the list. + + if (! updating) + { + if (file_info_list.empty ()) + { + symbol_table& symtab = __get_symbol_table__ (); + + if (symtab.is_built_in_function_name (base)) + { + std::string fcn_path = sys::file_ops::concat (dir_name, + fname); + + warning_with_id ("Octave:shadowed-function", + "function %s shadows a built-in function", + fcn_path.c_str ()); + } + } + else if (! at_end) + { + file_info& old = file_info_list.front (); + + // FIXME: do we need to be more careful about the + // way we look for old.dir_name in sys_path to avoid + // partial matches? + + // Don't warn about Contents.m files since we expect + // more than one to exist in the load path. + + if (fname != "Contents.m" + && s_sys_path.find (old.dir_name) != std::string::npos + && in_path_list (s_sys_path, old.dir_name)) + { + std::string fcn_path = sys::file_ops::concat (dir_name, + fname); + + warning_with_id ("Octave:shadowed-function", + "function %s shadows a core library function", + fcn_path.c_str ()); + } + } + } + + file_info fi (dir_name, t); + + if (at_end) + file_info_list.push_back (fi); + else + file_info_list.push_front (fi); + } + else + { + file_info& fi = *p; + + fi.types |= t; + } + } +} + +void +load_path::package_info::add_to_private_fcn_map (const dir_info& di) +{ + dir_info::fcn_file_map_type private_file_map = di.private_file_map; + + if (! private_file_map.empty ()) + m_private_fcn_map[di.abs_dir_name] = private_file_map; +} + +void +load_path::package_info::add_to_method_map (const dir_info& di, bool at_end) +{ + std::string dir_name = di.abs_dir_name; + + // + dir_info::method_file_map_type method_file_map = di.method_file_map; + + for (const auto& cls_ci : method_file_map) + { + std::string class_name = cls_ci.first; + + fcn_map_type& fm = m_method_map[class_name]; + + std::string full_dir_name + = sys::file_ops::concat (dir_name, '@' + class_name); + + const dir_info::class_info& ci = cls_ci.second; + + // + const dir_info::fcn_file_map_type& m = ci.method_file_map; + + for (const auto& nm_typ : m) + { + std::string base = nm_typ.first; + int types = nm_typ.second; + + file_info_list_type& file_info_list = fm[base]; + + auto p2 = file_info_list.begin (); + while (p2 != file_info_list.end ()) + { + if (p2->dir_name == full_dir_name) break; - } - } - } - } - - void - load_path::package_info::remove_private_fcn_map (const std::string& dir) - { - auto p = m_private_fcn_map.find (dir); - - if (p != m_private_fcn_map.end ()) - m_private_fcn_map.erase (p); - } - - void - load_path::package_info::remove_method_map (const std::string& dir) - { - for (auto& cls_fnmap : m_method_map) - { - std::string class_name = cls_fnmap.first; - - fcn_map_type& fn_map = cls_fnmap.second; - - std::string full_dir_name - = sys::file_ops::concat (dir, '@' + class_name); - - for (auto& nm_filst : fn_map) - { - file_info_list_type& file_info_list = nm_filst.second; - - if (file_info_list.size () == 1) - continue; - else - { - for (auto fi_it = file_info_list.begin (); - fi_it != file_info_list.end (); fi_it++) - { - if (fi_it->dir_name == full_dir_name) - { - file_info_list.erase (fi_it); - // FIXME: if there are no other elements, we - // should remove this element of fn_map but calling - // erase here would invalidate the iterator fi_it. - - break; - } - } - } - } - } - } - - bool - load_path::package_info::check_file_type (std::string& fname, int type, - int possible_types, - const std::string& fcn, - const char *who) const - { - bool retval = false; - - if (type == load_path::OCT_FILE) - { - if ((type & possible_types) == load_path::OCT_FILE) - { - fname += ".oct"; - retval = true; - } - } - else if (type == load_path::M_FILE) - { - if ((type & possible_types) == load_path::M_FILE) - { - fname += ".m"; - retval = true; - } - } - else if (type == load_path::MEX_FILE) - { - if ((type & possible_types) == load_path::MEX_FILE) - { - fname += ".mex"; - retval = true; - } - } - else if (type == (load_path::M_FILE | load_path::OCT_FILE)) - { - if (possible_types & load_path::OCT_FILE) - { - fname += ".oct"; - retval = true; - } - else if (possible_types & load_path::M_FILE) - { - fname += ".m"; - retval = true; - } - } - else if (type == (load_path::M_FILE | load_path::MEX_FILE)) - { - if (possible_types & load_path::MEX_FILE) - { - fname += ".mex"; - retval = true; - } - else if (possible_types & load_path::M_FILE) - { - fname += ".m"; - retval = true; - } - } - else if (type == (load_path::OCT_FILE | load_path::MEX_FILE)) - { - if (possible_types & load_path::OCT_FILE) - { - fname += ".oct"; - retval = true; - } - else if (possible_types & load_path::MEX_FILE) - { - fname += ".mex"; - retval = true; - } - } - else if (type == (load_path::M_FILE | load_path::OCT_FILE - | load_path::MEX_FILE)) - { - if (possible_types & load_path::OCT_FILE) - { - fname += ".oct"; - retval = true; - } - else if (possible_types & load_path::MEX_FILE) - { - fname += ".mex"; - retval = true; - } - else if (possible_types & load_path::M_FILE) - { - fname += ".m"; - retval = true; - } - } - else - error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type); - + + p2++; + } + + if (p2 == file_info_list.end ()) + { + file_info fi (full_dir_name, types); + + if (at_end) + file_info_list.push_back (fi); + else + file_info_list.push_front (fi); + } + else + { + // FIXME: is this possible? + file_info& fi = *p2; + + fi.types = types; + } + } + + // + dir_info::fcn_file_map_type private_file_map = ci.private_file_map; + + if (! private_file_map.empty ()) + m_private_fcn_map[full_dir_name] = private_file_map; + } +} + +void +load_path::package_info::move_fcn_map (const std::string& dir_name, + const string_vector& fcn_files, + bool at_end) +{ + octave_idx_type len = fcn_files.numel (); + + for (octave_idx_type k = 0; k < len; k++) + { + std::string fname = fcn_files[k]; + + std::string ext; + std::string base = fname; + + std::size_t pos = fname.rfind ('.'); + + if (pos != std::string::npos) + { + base = fname.substr (0, pos); + ext = fname.substr (pos); + } + + file_info_list_type& file_info_list = m_fcn_map[base]; + + if (file_info_list.size () == 1) + continue; + else + { + for (auto fi_it = file_info_list.begin (); + fi_it != file_info_list.end (); + fi_it++) + { + if (fi_it->dir_name == dir_name) + { + file_info fi_tmp = *fi_it; + + file_info_list.erase (fi_it); + + if (at_end) + file_info_list.push_back (fi_tmp); + else + file_info_list.push_front (fi_tmp); + + break; + } + } + } + } +} + +void +load_path::package_info::move_method_map (const std::string& dir_name, + bool at_end) +{ + for (auto& cls_fnmap : m_method_map) + { + std::string class_name = cls_fnmap.first; + + fcn_map_type& fn_map = cls_fnmap.second; + + std::string full_dir_name + = sys::file_ops::concat (dir_name, '@' + class_name); + + for (auto& nm_filst : fn_map) + { + file_info_list_type& file_info_list = nm_filst.second; + + if (file_info_list.size () == 1) + continue; + else + { + for (auto fi_it = file_info_list.begin (); + fi_it != file_info_list.end (); fi_it++) + { + if (fi_it->dir_name == full_dir_name) + { + file_info fi_tmp = *fi_it; + + file_info_list.erase (fi_it); + + if (at_end) + file_info_list.push_back (fi_tmp); + else + file_info_list.push_front (fi_tmp); + + break; + } + } + } + } + } +} + +void +load_path::package_info::remove_fcn_map (const std::string& dir, + const string_vector& fcn_files) +{ + octave_idx_type len = fcn_files.numel (); + + for (octave_idx_type k = 0; k < len; k++) + { + std::string fname = fcn_files[k]; + + std::string ext; + std::string base = fname; + + std::size_t pos = fname.rfind ('.'); + + if (pos != std::string::npos) + { + base = fname.substr (0, pos); + ext = fname.substr (pos); + } + + file_info_list_type& file_info_list = m_fcn_map[base]; + + for (auto fi_it = file_info_list.begin (); + fi_it != file_info_list.end (); + fi_it++) + { + if (fi_it->dir_name == dir) + { + file_info_list.erase (fi_it); + + if (file_info_list.empty ()) + m_fcn_map.erase (fname); + + break; + } + } + } +} + +void +load_path::package_info::remove_private_fcn_map (const std::string& dir) +{ + auto p = m_private_fcn_map.find (dir); + + if (p != m_private_fcn_map.end ()) + m_private_fcn_map.erase (p); +} + +void +load_path::package_info::remove_method_map (const std::string& dir) +{ + for (auto& cls_fnmap : m_method_map) + { + std::string class_name = cls_fnmap.first; + + fcn_map_type& fn_map = cls_fnmap.second; + + std::string full_dir_name + = sys::file_ops::concat (dir, '@' + class_name); + + for (auto& nm_filst : fn_map) + { + file_info_list_type& file_info_list = nm_filst.second; + + if (file_info_list.size () == 1) + continue; + else + { + for (auto fi_it = file_info_list.begin (); + fi_it != file_info_list.end (); fi_it++) + { + if (fi_it->dir_name == full_dir_name) + { + file_info_list.erase (fi_it); + // FIXME: if there are no other elements, we + // should remove this element of fn_map but calling + // erase here would invalidate the iterator fi_it. + + break; + } + } + } + } + } +} + +bool +load_path::package_info::check_file_type (std::string& fname, int type, + int possible_types, + const std::string& fcn, + const char *who) const +{ + bool retval = false; + + if (type == load_path::OCT_FILE) + { + if ((type & possible_types) == load_path::OCT_FILE) + { + fname += ".oct"; + retval = true; + } + } + else if (type == load_path::M_FILE) + { + if ((type & possible_types) == load_path::M_FILE) + { + fname += ".m"; + retval = true; + } + } + else if (type == load_path::MEX_FILE) + { + if ((type & possible_types) == load_path::MEX_FILE) + { + fname += ".mex"; + retval = true; + } + } + else if (type == (load_path::M_FILE | load_path::OCT_FILE)) + { + if (possible_types & load_path::OCT_FILE) + { + fname += ".oct"; + retval = true; + } + else if (possible_types & load_path::M_FILE) + { + fname += ".m"; + retval = true; + } + } + else if (type == (load_path::M_FILE | load_path::MEX_FILE)) + { + if (possible_types & load_path::MEX_FILE) + { + fname += ".mex"; + retval = true; + } + else if (possible_types & load_path::M_FILE) + { + fname += ".m"; + retval = true; + } + } + else if (type == (load_path::OCT_FILE | load_path::MEX_FILE)) + { + if (possible_types & load_path::OCT_FILE) + { + fname += ".oct"; + retval = true; + } + else if (possible_types & load_path::MEX_FILE) + { + fname += ".mex"; + retval = true; + } + } + else if (type == (load_path::M_FILE | load_path::OCT_FILE + | load_path::MEX_FILE)) + { + if (possible_types & load_path::OCT_FILE) + { + fname += ".oct"; + retval = true; + } + else if (possible_types & load_path::MEX_FILE) + { + fname += ".mex"; + retval = true; + } + else if (possible_types & load_path::M_FILE) + { + fname += ".m"; + retval = true; + } + } + else + error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type); + + return retval; +} + +void +load_path::package_info::print_types (std::ostream& os, int types) const +{ + bool printed_type = false; + + if (types & load_path::OCT_FILE) + { + os << "oct"; + printed_type = true; + } + + if (types & load_path::MEX_FILE) + { + if (printed_type) + os << '|'; + os << "mex"; + printed_type = true; + } + + if (types & load_path::M_FILE) + { + if (printed_type) + os << '|'; + os << 'm'; + printed_type = true; + } +} + +void +load_path::package_info::print_fcn_list (std::ostream& os, + const load_path::dir_info::fcn_file_map_type& lst) const +{ + for (const auto& nm_typ : lst) + { + os << " " << nm_typ.first << " ("; + + print_types (os, nm_typ.second); + + os << ")\n"; + } +} + +std::string +genpath (const std::string& dirname, const string_vector& skip) +{ + std::string retval; + string_vector dirlist; + std::string msg; + + if (! sys::get_dirlist (dirname, dirlist, msg)) return retval; - } - - void - load_path::package_info::print_types (std::ostream& os, int types) const - { - bool printed_type = false; - - if (types & load_path::OCT_FILE) - { - os << "oct"; - printed_type = true; - } - - if (types & load_path::MEX_FILE) - { - if (printed_type) - os << '|'; - os << "mex"; - printed_type = true; - } - - if (types & load_path::M_FILE) - { - if (printed_type) - os << '|'; - os << 'm'; - printed_type = true; - } - } - - void - load_path::package_info::print_fcn_list (std::ostream& os, - const load_path::dir_info::fcn_file_map_type& lst) const - { - for (const auto& nm_typ : lst) - { - os << " " << nm_typ.first << " ("; - - print_types (os, nm_typ.second); - - os << ")\n"; - } - } - - std::string - genpath (const std::string& dirname, const string_vector& skip) - { - std::string retval; - string_vector dirlist; - std::string msg; - - if (! sys::get_dirlist (dirname, dirlist, msg)) - return retval; - - retval = dirname; - - dirlist = dirlist.sort (false); - - octave_idx_type len = dirlist.numel (); - - for (octave_idx_type i = 0; i < len; i++) - { - std::string elt = dirlist[i]; - - bool skip_p = (elt == "." || elt == ".." || elt[0] == '@' - || elt[0] == '+'); - - if (! skip_p) - { - for (octave_idx_type j = 0; j < skip.numel (); j++) - { - skip_p = (elt == skip[j]); - if (skip_p) - break; - } - - if (! skip_p) - { - std::string nm = sys::file_ops::concat (dirname, elt); - - sys::file_stat fs (nm); - - if (fs && fs.is_dir ()) - retval += (directory_path::path_sep_str () - + genpath (nm, skip)); - } - } - } - - return retval; - } + + retval = dirname; + + dirlist = dirlist.sort (false); + + octave_idx_type len = dirlist.numel (); + + for (octave_idx_type i = 0; i < len; i++) + { + std::string elt = dirlist[i]; + + bool skip_p = (elt == "." || elt == ".." || elt[0] == '@' + || elt[0] == '+'); + + if (! skip_p) + { + for (octave_idx_type j = 0; j < skip.numel (); j++) + { + skip_p = (elt == skip[j]); + if (skip_p) + break; + } + + if (! skip_p) + { + std::string nm = sys::file_ops::concat (dirname, elt); + + sys::file_stat fs (nm); + + if (fs && fs.is_dir ()) + retval += (directory_path::path_sep_str () + + genpath (nm, skip)); + } + } + } + + return retval; +} DEFUN (genpath, args, , doc: /* -*- texinfo -*- @@ -2607,7 +2607,7 @@ else if (nargin == 0 && nargout == 0) { octave_stdout << - "\nOctave's search path contains the following directories:\n\n"; + "\nOctave's search path contains the following directories:\n\n"; string_vector dirs = lp.dirs (); @@ -2723,10 +2723,10 @@ dir.erase (std::unique (it_start, dir.end (), [] (char l, char r) - { - return l == r && sys::file_ops::is_dir_sep (l); - }), - dir.end ()); + { + return l == r && sys::file_ops::is_dir_sep (l); + }), + dir.end ()); auto pos = dir.find_last_of (sys::file_ops::dir_sep_chars ()); if (pos == std::string::npos) @@ -2804,7 +2804,7 @@ for (const auto& dir : dir_elts) { //dir = regexprep (dir_elts{j}, '//+', "/"); - //dir = regexprep (dir, '/$', ""); + //dir = regexprep (dir, '/$', ""); if (! lp.remove (dir)) warning ("rmpath: %s: not found", dir.c_str ()); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/load-path.h --- a/libinterp/corefcn/load-path.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/load-path.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,547 +41,547 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTINTERP_API - load_path +class +OCTINTERP_API +load_path +{ +public: + + load_path (interpreter& interp); + + typedef void (*hook_fcn_ptr) (const std::string& dir); + + load_path (const load_path&) = delete; + + load_path& operator = (const load_path&) = delete; + + ~load_path (void) = default; + + void initialize (bool set_initial_path = false); + + void clear (void); + + void set (const std::string& p, bool warn = false, bool is_init = false); + + void append (const std::string& dir, bool warn = false); + + void prepend (const std::string& dir, bool warn = false); + + bool remove (const std::string& dir); + + void update (void); + + bool contains_canonical (const std::string& dir_name) const; + + bool contains_file_in_dir (const std::string& file_name, + const std::string& dir_name); + + std::string find_method (const std::string& class_name, + const std::string& meth, + std::string& dir_name, + const std::string& pack_name = "") + { + return get_package (pack_name).find_method (class_name, meth, dir_name); + } + + std::string find_method (const std::string& class_name, + const std::string& meth, + const std::string& pack_name = "") + { + std::string dir_name; + return find_method (class_name, meth, dir_name, pack_name); + } + + std::list methods (const std::string& class_name, + const std::string& pack_name = "") + { + return get_package (pack_name).methods (class_name); + } + + std::list overloads (const std::string& meth) const; + + bool find_package (const std::string& package_name) const + { + return (m_package_map.find (package_name) != m_package_map.end ()); + } + + std::list + get_all_package_names (bool only_top_level = true) const; + + std::string find_fcn (const std::string& fcn, std::string& dir_name, + const std::string& pack_name = "") + { + return get_package (pack_name).find_fcn (fcn, dir_name); + } + + std::string find_fcn (const std::string& fcn, + const std::string& pack_name = "") + { + std::string dir_name; + return find_fcn (fcn, dir_name, pack_name); + } + + std::string find_private_fcn (const std::string& dir, + const std::string& fcn, + const std::string& pack_name = "") + { + return get_package (pack_name).find_private_fcn (dir, fcn); + } + + std::string find_fcn_file (const std::string& fcn, + const std::string& pack_name = "") + { + std::string dir_name; + return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE); + } + + std::string find_oct_file (const std::string& fcn, + const std::string& pack_name = "") + { + std::string dir_name; + return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE); + } + + std::string find_mex_file (const std::string& fcn, + const std::string& pack_name = "") + { + std::string dir_name; + return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE); + } + + std::string find_file (const std::string& file) const; + + std::string find_dir (const std::string& dir) const; + + string_vector find_matching_dirs (const std::string& dir) const; + + std::string find_first_of (const string_vector& files) const; + + string_vector find_all_first_of (const string_vector& files) const; + + string_vector dirs (void) const; + + std::list dir_list (void) const; + + string_vector files (const std::string& dir, bool omit_exts = false) const; + + string_vector fcn_names (void) const; + + std::string path (void) const; + + void display (std::ostream& os) const; + + std::function get_add_hook (void) + { + return add_hook; + } + + std::function get_remove_hook (void) + { + return remove_hook; + } + + void set_add_hook (const std::function& f) + { + add_hook = f; + } + + void set_remove_hook (const std::function& f) + { + remove_hook = f; + } + + void read_dir_config (const std::string& dir) const; + + void execute_pkg_add (const std::string& dir); + void execute_pkg_del (const std::string& dir); + + void set_command_line_path (const std::string& p) + { + if (m_command_line_path.empty ()) + m_command_line_path = p; + else + m_command_line_path += directory_path::path_sep_str () + p; + } + + std::string get_command_line_path (void) const + { + return m_command_line_path; + } + + std::string system_path (void) const { return s_sys_path; } + + static const int M_FILE = 1; + static const int OCT_FILE = 2; + static const int MEX_FILE = 4; + +private: + + class dir_info { public: - load_path (interpreter& interp); - - typedef void (*hook_fcn_ptr) (const std::string& dir); - - load_path (const load_path&) = delete; - - load_path& operator = (const load_path&) = delete; + // + typedef std::map fcn_file_map_type; - ~load_path (void) = default; - - void initialize (bool set_initial_path = false); + typedef fcn_file_map_type::const_iterator const_fcn_file_map_iterator; + typedef fcn_file_map_type::iterator fcn_file_map_iterator; - void clear (void); - - void set (const std::string& p, bool warn = false, bool is_init = false); - - void append (const std::string& dir, bool warn = false); + struct class_info + { + public: + class_info (void) : method_file_map (), private_file_map () { } - void prepend (const std::string& dir, bool warn = false); - - bool remove (const std::string& dir); - - void update (void); - - bool contains_canonical (const std::string& dir_name) const; + class_info (const class_info& ci) + : method_file_map (ci.method_file_map), + private_file_map (ci.private_file_map) + { } - bool contains_file_in_dir (const std::string& file_name, - const std::string& dir_name); + class_info& operator = (const class_info& ci) + { + if (this != &ci) + { + method_file_map = ci.method_file_map; + private_file_map = ci.private_file_map; + } + return *this; + } - std::string find_method (const std::string& class_name, - const std::string& meth, - std::string& dir_name, - const std::string& pack_name = "") - { - return get_package (pack_name).find_method (class_name, meth, dir_name); - } + ~class_info (void) = default; - std::string find_method (const std::string& class_name, - const std::string& meth, - const std::string& pack_name = "") - { - std::string dir_name; - return find_method (class_name, meth, dir_name, pack_name); - } + fcn_file_map_type method_file_map; + fcn_file_map_type private_file_map; + }; - std::list methods (const std::string& class_name, - const std::string& pack_name = "") - { - return get_package (pack_name).methods (class_name); - } + // + typedef std::map method_file_map_type; - std::list overloads (const std::string& meth) const; + typedef method_file_map_type::const_iterator const_method_file_map_iterator; + typedef method_file_map_type::iterator method_file_map_iterator; - bool find_package (const std::string& package_name) const - { - return (m_package_map.find (package_name) != m_package_map.end ()); - } + // + typedef std::map package_dir_map_type; - std::list - get_all_package_names (bool only_top_level = true) const; - - std::string find_fcn (const std::string& fcn, std::string& dir_name, - const std::string& pack_name = "") - { - return get_package (pack_name).find_fcn (fcn, dir_name); - } + typedef package_dir_map_type::const_iterator const_package_dir_map_iterator; + typedef package_dir_map_type::iterator package_dir_map_iterator; - std::string find_fcn (const std::string& fcn, - const std::string& pack_name = "") + // This default constructor is only provided so we can create a + // std::map of dir_info objects. You should not use this + // constructor for any other purpose. + dir_info (void) = default; + + dir_info (const std::string& d) + : dir_name (d), abs_dir_name (), is_relative (false), + dir_mtime (), dir_time_last_checked (), all_files (), fcn_files (), + private_file_map (), method_file_map (), package_dir_map () { - std::string dir_name; - return find_fcn (fcn, dir_name, pack_name); - } - - std::string find_private_fcn (const std::string& dir, - const std::string& fcn, - const std::string& pack_name = "") - { - return get_package (pack_name).find_private_fcn (dir, fcn); + initialize (); } - std::string find_fcn_file (const std::string& fcn, - const std::string& pack_name = "") - { - std::string dir_name; - return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE); - } + dir_info (const dir_info&) = default; - std::string find_oct_file (const std::string& fcn, - const std::string& pack_name = "") - { - std::string dir_name; - return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE); - } - - std::string find_mex_file (const std::string& fcn, - const std::string& pack_name = "") - { - std::string dir_name; - return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE); - } + ~dir_info (void) = default; - std::string find_file (const std::string& file) const; - - std::string find_dir (const std::string& dir) const; - - string_vector find_matching_dirs (const std::string& dir) const; - - std::string find_first_of (const string_vector& files) const; - - string_vector find_all_first_of (const string_vector& files) const; + dir_info& operator = (const dir_info&) = default; - string_vector dirs (void) const; - - std::list dir_list (void) const; - - string_vector files (const std::string& dir, bool omit_exts = false) const; - - string_vector fcn_names (void) const; - - std::string path (void) const; - - void display (std::ostream& os) const; + bool update (void); - std::function get_add_hook (void) - { - return add_hook; - } - - std::function get_remove_hook (void) - { - return remove_hook; - } - - void set_add_hook (const std::function& f) - { - add_hook = f; - } - - void set_remove_hook (const std::function& f) - { - remove_hook = f; - } - - void read_dir_config (const std::string& dir) const; + std::string dir_name; + std::string abs_dir_name; + bool is_relative; + sys::time dir_mtime; + sys::time dir_time_last_checked; + string_vector all_files; + string_vector fcn_files; + fcn_file_map_type private_file_map; + method_file_map_type method_file_map; + package_dir_map_type package_dir_map; - void execute_pkg_add (const std::string& dir); - void execute_pkg_del (const std::string& dir); - - void set_command_line_path (const std::string& p) - { - if (m_command_line_path.empty ()) - m_command_line_path = p; - else - m_command_line_path += directory_path::path_sep_str () + p; - } - - std::string get_command_line_path (void) const - { - return m_command_line_path; - } - - std::string system_path (void) const { return s_sys_path; } - - static const int M_FILE = 1; - static const int OCT_FILE = 2; - static const int MEX_FILE = 4; + bool is_package (const std::string& name) const; private: - class dir_info - { - public: + void initialize (void); + + void get_file_list (const std::string& d); + + void get_private_file_map (const std::string& d); + + void get_method_file_map (const std::string& d, + const std::string& class_name); + + void get_package_dir (const std::string& d, + const std::string& package_name); + + friend fcn_file_map_type get_fcn_files (const std::string& d); + }; + + class file_info + { + public: + + file_info (const std::string& d, int t) : dir_name (d), types (t) { } + + file_info (const file_info& fi) + : dir_name (fi.dir_name), types (fi.types) { } + + ~file_info (void) = default; - // - typedef std::map fcn_file_map_type; + file_info& operator = (const file_info& fi) + { + if (&fi != this) + { + dir_name = fi.dir_name; + types = fi.types; + } + + return *this; + } + + std::string dir_name; + int types; + }; - typedef fcn_file_map_type::const_iterator const_fcn_file_map_iterator; - typedef fcn_file_map_type::iterator fcn_file_map_iterator; + // We maintain two ways of looking at the same information. + // + // First, a list of directories and the set of "public" files and + // private files (those found in the special "private" subdirectory) + // in each directory. + // + // Second, a map from filenames (the union of all "public" files for all + // directories, but without filename extensions) to a list of + // corresponding information (directory name and file types). This + // way, we can quickly find shadowed filenames and look up all + // overloaded functions (in the "@" directories used to implement + // classes). + + typedef std::list dir_info_list_type; - struct class_info - { - public: - class_info (void) : method_file_map (), private_file_map () { } + typedef dir_info_list_type::const_iterator const_dir_info_list_iterator; + typedef dir_info_list_type::iterator dir_info_list_iterator; + + typedef std::map abs_dir_cache_type; + + typedef abs_dir_cache_type::const_iterator const_abs_dir_cache_iterator; + typedef abs_dir_cache_type::iterator abs_dir_cache_iterator; + + typedef std::list file_info_list_type; + + typedef file_info_list_type::const_iterator const_file_info_list_iterator; + typedef file_info_list_type::iterator file_info_list_iterator; + + // + typedef std::map fcn_map_type; + + typedef fcn_map_type::const_iterator const_fcn_map_iterator; + typedef fcn_map_type::iterator fcn_map_iterator; + + // > + typedef std::map + private_fcn_map_type; + + typedef private_fcn_map_type::const_iterator const_private_fcn_map_iterator; + typedef private_fcn_map_type::iterator private_fcn_map_iterator; + + // > + typedef std::map method_map_type; - class_info (const class_info& ci) - : method_file_map (ci.method_file_map), - private_file_map (ci.private_file_map) - { } + typedef method_map_type::const_iterator const_method_map_iterator; + typedef method_map_type::iterator method_map_iterator; + + class package_info + { + public: - class_info& operator = (const class_info& ci) + package_info (const std::string& package_name = "") + : m_package_name (package_name), m_dir_list (), m_fcn_map (), + m_private_fcn_map (), + m_method_map () + { } + + package_info (const package_info& l) + : m_package_name (l.m_package_name), m_dir_list (l.m_dir_list), + m_private_fcn_map (l.m_private_fcn_map), m_method_map (l.m_method_map) + { } + + ~package_info (void) = default; + + package_info& operator = (const package_info& l) + { + if (&l != this) { - if (this != &ci) - { - method_file_map = ci.method_file_map; - private_file_map = ci.private_file_map; - } - return *this; + m_package_name = l.m_package_name; + m_dir_list = l.m_dir_list; + m_fcn_map = l.m_fcn_map; + m_private_fcn_map = l.m_private_fcn_map; + m_method_map = l.m_method_map; } - ~class_info (void) = default; + return *this; + } - fcn_file_map_type method_file_map; - fcn_file_map_type private_file_map; - }; + void add (const dir_info& di, bool at_end, bool updating) + { + if (at_end) + m_dir_list.push_back (di.dir_name); + else + m_dir_list.push_front (di.dir_name); - // - typedef std::map method_file_map_type; + add_to_fcn_map (di, at_end, updating); + + add_to_private_fcn_map (di); - typedef method_file_map_type::const_iterator const_method_file_map_iterator; - typedef method_file_map_type::iterator method_file_map_iterator; + add_to_method_map (di, at_end); + } + + void move (const dir_info& di, bool at_end); + + void remove (const dir_info& di); - // - typedef std::map package_dir_map_type; + void clear (void) + { + m_dir_list.clear (); - typedef package_dir_map_type::const_iterator const_package_dir_map_iterator; - typedef package_dir_map_type::iterator package_dir_map_iterator; + m_fcn_map.clear (); + + m_private_fcn_map.clear (); + + m_method_map.clear (); + } - // This default constructor is only provided so we can create a - // std::map of dir_info objects. You should not use this - // constructor for any other purpose. - dir_info (void) = default; + void display (std::ostream& out) const; + + std::string + find_fcn (const std::string& fcn, std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string + find_private_fcn (const std::string& dir, const std::string& fcn, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::string + find_method (const std::string& class_name, const std::string& meth, + std::string& dir_name, + int type = M_FILE | OCT_FILE | MEX_FILE) const; + + std::list methods (const std::string& class_name) const; - dir_info (const std::string& d) - : dir_name (d), abs_dir_name (), is_relative (false), - dir_mtime (), dir_time_last_checked (), all_files (), fcn_files (), - private_file_map (), method_file_map (), package_dir_map () - { - initialize (); - } + void overloads (const std::string& meth, std::list& l) const; + + string_vector fcn_names (void) const; + + private: + + void add_to_fcn_map (const dir_info& di, bool at_end, bool updating); - dir_info (const dir_info&) = default; + void add_to_private_fcn_map (const dir_info& di); - ~dir_info (void) = default; + void add_to_method_map (const dir_info& di, bool at_end); - dir_info& operator = (const dir_info&) = default; + void move_fcn_map (const std::string& dir, + const string_vector& fcn_files, bool at_end); - bool update (void); + void move_method_map (const std::string& dir, bool at_end); - std::string dir_name; - std::string abs_dir_name; - bool is_relative; - sys::time dir_mtime; - sys::time dir_time_last_checked; - string_vector all_files; - string_vector fcn_files; - fcn_file_map_type private_file_map; - method_file_map_type method_file_map; - package_dir_map_type package_dir_map; + void remove_fcn_map (const std::string& dir, + const string_vector& fcn_files); + + void remove_private_fcn_map (const std::string& dir); + + void remove_method_map (const std::string& dir); + + bool check_file_type (std::string& fname, int type, int possible_types, + const std::string& fcn, const char *who) const; + + void print_types (std::ostream& os, int types) const; + + void print_fcn_list (std::ostream& os, + const dir_info::fcn_file_map_type& lst) const; + + std::string m_package_name; - bool is_package (const std::string& name) const; + std::list m_dir_list; - private: + fcn_map_type m_fcn_map; - void initialize (void); + private_fcn_map_type m_private_fcn_map; - void get_file_list (const std::string& d); + method_map_type m_method_map; + }; - void get_private_file_map (const std::string& d); + // + typedef std::map package_map_type; - void get_method_file_map (const std::string& d, - const std::string& class_name); + typedef package_map_type::const_iterator const_package_map_iterator; + typedef package_map_type::iterator package_map_iterator; + + std::function add_hook; - void get_package_dir (const std::string& d, - const std::string& package_name); + std::function remove_hook; - friend fcn_file_map_type get_fcn_files (const std::string& d); - }; + void execute_pkg_add_or_del (const std::string& dir, + const std::string& script_file); + + const_dir_info_list_iterator find_dir_info (const std::string& dir) const; + dir_info_list_iterator find_dir_info (const std::string& dir); - class file_info - { - public: + bool contains (const std::string& dir) const; + + void move (dir_info_list_iterator i, bool at_end); - file_info (const std::string& d, int t) : dir_name (d), types (t) { } + void move (const dir_info& di, bool at_end, const std::string& pname = ""); + + void remove (const dir_info& di, const std::string& pname = ""); - file_info (const file_info& fi) - : dir_name (fi.dir_name), types (fi.types) { } + void add (const std::string& dir, bool at_end, bool warn); + + void add (const dir_info& di, bool at_end, const std::string& pname = "", + bool updating = false); - ~file_info (void) = default; + bool is_package (const std::string& name) const; - file_info& operator = (const file_info& fi) + package_info& get_package (const std::string& name) + { + if (! name.empty () && is_package (name)) { - if (&fi != this) - { - dir_name = fi.dir_name; - types = fi.types; - } + package_map_iterator l = m_package_map.find (name); - return *this; + if (l == m_package_map.end ()) + l = m_package_map.insert (m_package_map.end (), + package_map_type::value_type (name, package_info (name))); + + return l->second; } - std::string dir_name; - int types; - }; - - // We maintain two ways of looking at the same information. - // - // First, a list of directories and the set of "public" files and - // private files (those found in the special "private" subdirectory) - // in each directory. - // - // Second, a map from filenames (the union of all "public" files for all - // directories, but without filename extensions) to a list of - // corresponding information (directory name and file types). This - // way, we can quickly find shadowed filenames and look up all - // overloaded functions (in the "@" directories used to implement - // classes). - - typedef std::list dir_info_list_type; - - typedef dir_info_list_type::const_iterator const_dir_info_list_iterator; - typedef dir_info_list_type::iterator dir_info_list_iterator; - - typedef std::map abs_dir_cache_type; - - typedef abs_dir_cache_type::const_iterator const_abs_dir_cache_iterator; - typedef abs_dir_cache_type::iterator abs_dir_cache_iterator; + return m_top_level_package; + } - typedef std::list file_info_list_type; - - typedef file_info_list_type::const_iterator const_file_info_list_iterator; - typedef file_info_list_type::iterator file_info_list_iterator; - - // - typedef std::map fcn_map_type; - - typedef fcn_map_type::const_iterator const_fcn_map_iterator; - typedef fcn_map_type::iterator fcn_map_iterator; + string_vector get_file_list (const dir_info::fcn_file_map_type& lst) const; - // > - typedef std::map - private_fcn_map_type; - - typedef private_fcn_map_type::const_iterator const_private_fcn_map_iterator; - typedef private_fcn_map_type::iterator private_fcn_map_iterator; - - // > - typedef std::map method_map_type; - - typedef method_map_type::const_iterator const_method_map_iterator; - typedef method_map_type::iterator method_map_iterator; - - class package_info - { - public: + friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d); - package_info (const std::string& package_name = "") - : m_package_name (package_name), m_dir_list (), m_fcn_map (), - m_private_fcn_map (), - m_method_map () - { } - - package_info (const package_info& l) - : m_package_name (l.m_package_name), m_dir_list (l.m_dir_list), - m_private_fcn_map (l.m_private_fcn_map), m_method_map (l.m_method_map) - { } - - ~package_info (void) = default; + //-------- - package_info& operator = (const package_info& l) - { - if (&l != this) - { - m_package_name = l.m_package_name; - m_dir_list = l.m_dir_list; - m_fcn_map = l.m_fcn_map; - m_private_fcn_map = l.m_private_fcn_map; - m_method_map = l.m_method_map; - } - - return *this; - } + static std::string s_sys_path; - void add (const dir_info& di, bool at_end, bool updating) - { - if (at_end) - m_dir_list.push_back (di.dir_name); - else - m_dir_list.push_front (di.dir_name); - - add_to_fcn_map (di, at_end, updating); - - add_to_private_fcn_map (di); - - add_to_method_map (di, at_end); - } - - void move (const dir_info& di, bool at_end); - - void remove (const dir_info& di); + static abs_dir_cache_type s_abs_dir_cache; - void clear (void) - { - m_dir_list.clear (); - - m_fcn_map.clear (); - - m_private_fcn_map.clear (); - - m_method_map.clear (); - } - - void display (std::ostream& out) const; - - std::string - find_fcn (const std::string& fcn, std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; - - std::string - find_private_fcn (const std::string& dir, const std::string& fcn, - int type = M_FILE | OCT_FILE | MEX_FILE) const; + interpreter& m_interpreter; - std::string - find_method (const std::string& class_name, const std::string& meth, - std::string& dir_name, - int type = M_FILE | OCT_FILE | MEX_FILE) const; - - std::list methods (const std::string& class_name) const; - - void overloads (const std::string& meth, std::list& l) const; - - string_vector fcn_names (void) const; - - private: - - void add_to_fcn_map (const dir_info& di, bool at_end, bool updating); - - void add_to_private_fcn_map (const dir_info& di); - - void add_to_method_map (const dir_info& di, bool at_end); - - void move_fcn_map (const std::string& dir, - const string_vector& fcn_files, bool at_end); - - void move_method_map (const std::string& dir, bool at_end); - - void remove_fcn_map (const std::string& dir, - const string_vector& fcn_files); - - void remove_private_fcn_map (const std::string& dir); + package_map_type m_package_map; - void remove_method_map (const std::string& dir); - - bool check_file_type (std::string& fname, int type, int possible_types, - const std::string& fcn, const char *who) const; - - void print_types (std::ostream& os, int types) const; - - void print_fcn_list (std::ostream& os, - const dir_info::fcn_file_map_type& lst) const; - - std::string m_package_name; - - std::list m_dir_list; + package_info m_top_level_package; - fcn_map_type m_fcn_map; - - private_fcn_map_type m_private_fcn_map; - - method_map_type m_method_map; - }; - - // - typedef std::map package_map_type; - - typedef package_map_type::const_iterator const_package_map_iterator; - typedef package_map_type::iterator package_map_iterator; - - std::function add_hook; - - std::function remove_hook; + dir_info_list_type m_dir_info_list; - void execute_pkg_add_or_del (const std::string& dir, - const std::string& script_file); - - const_dir_info_list_iterator find_dir_info (const std::string& dir) const; - dir_info_list_iterator find_dir_info (const std::string& dir); - - bool contains (const std::string& dir) const; - - void move (dir_info_list_iterator i, bool at_end); - - void move (const dir_info& di, bool at_end, const std::string& pname = ""); - - void remove (const dir_info& di, const std::string& pname = ""); + std::set m_init_dirs; - void add (const std::string& dir, bool at_end, bool warn); - - void add (const dir_info& di, bool at_end, const std::string& pname = "", - bool updating = false); - - bool is_package (const std::string& name) const; - - package_info& get_package (const std::string& name) - { - if (! name.empty () && is_package (name)) - { - package_map_iterator l = m_package_map.find (name); - - if (l == m_package_map.end ()) - l = m_package_map.insert (m_package_map.end (), - package_map_type::value_type (name, package_info (name))); + std::string m_command_line_path; - return l->second; - } - - return m_top_level_package; - } - - string_vector get_file_list (const dir_info::fcn_file_map_type& lst) const; - - friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d); - - //-------- - - static std::string s_sys_path; - - static abs_dir_cache_type s_abs_dir_cache; +}; - interpreter& m_interpreter; - - package_map_type m_package_map; - - package_info m_top_level_package; - - dir_info_list_type m_dir_info_list; - - std::set m_init_dirs; - - std::string m_command_line_path; - - }; - - extern std::string - genpath (const std::string& dir, const string_vector& skip = "private"); +extern std::string +genpath (const std::string& dir, const string_vector& skip = "private"); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/load-save.cc Thu Dec 01 20:05:44 2022 -0800 @@ -92,1460 +92,1460 @@ OCTAVE_BEGIN_NAMESPACE(octave) - OCTAVE_NORETURN static - void - err_file_open (const std::string& fcn, const std::string& file) - { - if (fcn == "load") - error ("%s: unable to open input file '%s'", fcn.c_str (), file.c_str ()); - else if (fcn == "save") - error ("%s: unable to open output file '%s'", fcn.c_str (), file.c_str ()); - else - error ("%s: unable to open file '%s'", fcn.c_str (), file.c_str ()); - } +OCTAVE_NORETURN static +void +err_file_open (const std::string& fcn, const std::string& file) +{ + if (fcn == "load") + error ("%s: unable to open input file '%s'", fcn.c_str (), file.c_str ()); + else if (fcn == "save") + error ("%s: unable to open output file '%s'", fcn.c_str (), file.c_str ()); + else + error ("%s: unable to open file '%s'", fcn.c_str (), file.c_str ()); +} - // Return TRUE if NAME matches one of the given globbing PATTERNS. +// Return TRUE if NAME matches one of the given globbing PATTERNS. - static bool - matches_patterns (const string_vector& patterns, int pat_idx, - int num_pat, const std::string& name) - { - for (int i = pat_idx; i < num_pat; i++) - { - glob_match pattern (patterns[i]); +static bool +matches_patterns (const string_vector& patterns, int pat_idx, + int num_pat, const std::string& name) +{ + for (int i = pat_idx; i < num_pat; i++) + { + glob_match pattern (patterns[i]); - if (pattern.match (name)) - return true; - } + if (pattern.match (name)) + return true; + } - return false; - } + return false; +} - static int - read_binary_file_header (std::istream& is, bool& swap, - mach_info::float_format& flt_fmt, - bool quiet = false) - { - const int magic_len = 10; - char magic[magic_len+1]; - is.read (magic, magic_len); - magic[magic_len] = '\0'; +static int +read_binary_file_header (std::istream& is, bool& swap, + mach_info::float_format& flt_fmt, + bool quiet = false) +{ + const int magic_len = 10; + char magic[magic_len+1]; + is.read (magic, magic_len); + magic[magic_len] = '\0'; - if (strncmp (magic, "Octave-1-L", magic_len) == 0) - swap = mach_info::words_big_endian (); - else if (strncmp (magic, "Octave-1-B", magic_len) == 0) - swap = ! mach_info::words_big_endian (); - else - { - if (! quiet) - error ("load: unable to read binary file"); + if (strncmp (magic, "Octave-1-L", magic_len) == 0) + swap = mach_info::words_big_endian (); + else if (strncmp (magic, "Octave-1-B", magic_len) == 0) + swap = ! mach_info::words_big_endian (); + else + { + if (! quiet) + error ("load: unable to read binary file"); - return -1; - } + return -1; + } - char tmp = 0; - is.read (&tmp, 1); + char tmp = 0; + is.read (&tmp, 1); - flt_fmt = mopt_digit_to_float_format (tmp); + flt_fmt = mopt_digit_to_float_format (tmp); - if (flt_fmt == mach_info::flt_fmt_unknown) - { - if (! quiet) - error ("load: unrecognized binary format!"); + if (flt_fmt == mach_info::flt_fmt_unknown) + { + if (! quiet) + error ("load: unrecognized binary format!"); - return -1; - } + return -1; + } - return 0; - } + return 0; +} #if defined (HAVE_ZLIB) - static bool - check_gzip_magic (const std::string& fname) - { - bool retval = false; +static bool +check_gzip_magic (const std::string& fname) +{ + bool retval = false; - std::ifstream file = sys::ifstream (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 (&magic[0]), 2) - && magic[0] == 0x1f && magic[1] == 0x8b) - retval = true; + unsigned char magic[2]; + if (file.read (reinterpret_cast (&magic[0]), 2) + && magic[0] == 0x1f && magic[1] == 0x8b) + retval = true; - file.close (); + file.close (); - return retval; - } + return retval; +} #endif - static std::string - find_file_to_load (const std::string& name, const std::string& orig_name) - { - std::string fname = find_data_file_in_load_path ("load", name, true); +static std::string +find_file_to_load (const std::string& name, const std::string& orig_name) +{ + std::string fname = find_data_file_in_load_path ("load", name, true); - std::size_t dot_pos = fname.rfind ('.'); - std::size_t sep_pos = fname.find_last_of (sys::file_ops::dir_sep_chars ()); + std::size_t dot_pos = fname.rfind ('.'); + std::size_t sep_pos = fname.find_last_of (sys::file_ops::dir_sep_chars ()); - if (dot_pos == std::string::npos - || (sep_pos != std::string::npos && dot_pos < sep_pos)) - { - // Either no '.' in name or no '.' appears after last directory - // separator. + if (dot_pos == std::string::npos + || (sep_pos != std::string::npos && dot_pos < sep_pos)) + { + // Either no '.' in name or no '.' appears after last directory + // separator. - sys::file_stat fs (fname); + sys::file_stat fs (fname); - if (! (fs.exists () && fs.is_reg ())) - fname = find_file_to_load (fname + ".mat", orig_name); - } - else - { - sys::file_stat fs (fname); + if (! (fs.exists () && fs.is_reg ())) + fname = find_file_to_load (fname + ".mat", orig_name); + } + else + { + sys::file_stat fs (fname); - if (! (fs.exists () && fs.is_reg ())) - { - fname = ""; + if (! (fs.exists () && fs.is_reg ())) + { + fname = ""; - error ("load: unable to find file %s", orig_name.c_str ()); - } - } + error ("load: unable to find file %s", orig_name.c_str ()); + } + } - return fname; - } + return fname; +} - // Return TRUE if PATTERN has any special globbing chars in it. +// Return TRUE if PATTERN has any special globbing chars in it. - static bool - glob_pattern_p (const std::string& pattern) - { - int open = 0; +static bool +glob_pattern_p (const std::string& pattern) +{ + int open = 0; - int len = pattern.length (); + int len = pattern.length (); - for (int i = 0; i < len; i++) - { - char c = pattern[i]; + for (int i = 0; i < len; i++) + { + char c = pattern[i]; - switch (c) - { - case '?': - case '*': - return true; + switch (c) + { + case '?': + case '*': + return true; - case '[': // Only accept an open brace if there is a close - open++; // brace to match it. Bracket expressions must be - continue; // complete, according to Posix.2 + case '[': // Only accept an open brace if there is a close + open++; // brace to match it. Bracket expressions must be + continue; // complete, according to Posix.2 - case ']': - if (open) - return true; - continue; + case ']': + if (open) + return true; + continue; - case '\\': - if (i == len - 1) - return false; - continue; + case '\\': + if (i == len - 1) + return false; + continue; - default: - continue; - } - } + default: + continue; + } + } - return false; - } + return false; +} - load_save_system::load_save_system (interpreter& interp) - : m_interpreter (interp), - m_crash_dumps_octave_core (true), - m_octave_core_file_limit (-1.0), - m_octave_core_file_name ("octave-workspace"), - m_save_default_options ("-text"), - m_octave_core_file_options ("-binary"), - m_save_header_format_string (init_save_header_format ()) - { +load_save_system::load_save_system (interpreter& interp) + : m_interpreter (interp), + m_crash_dumps_octave_core (true), + m_octave_core_file_limit (-1.0), + m_octave_core_file_name ("octave-workspace"), + m_save_default_options ("-text"), + m_octave_core_file_options ("-binary"), + m_save_header_format_string (init_save_header_format ()) +{ #if defined (HAVE_HDF5) - H5dont_atexit (); + H5dont_atexit (); #endif - } +} - load_save_system::~load_save_system (void) - { +load_save_system::~load_save_system (void) +{ #if defined (HAVE_HDF5) - H5close (); + H5close (); #endif - } +} - octave_value - load_save_system::crash_dumps_octave_core (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_crash_dumps_octave_core, args, nargout, - "crash_dumps_octave_core"); - } +octave_value +load_save_system::crash_dumps_octave_core (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_crash_dumps_octave_core, args, nargout, + "crash_dumps_octave_core"); +} - octave_value - load_save_system::octave_core_file_limit (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_octave_core_file_limit, args, nargout, - "octave_core_file_limit"); - } +octave_value +load_save_system::octave_core_file_limit (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_octave_core_file_limit, args, nargout, + "octave_core_file_limit"); +} - octave_value - load_save_system::octave_core_file_name (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_octave_core_file_name, args, nargout, - "octave_core_file_name", false); - } +octave_value +load_save_system::octave_core_file_name (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_octave_core_file_name, args, nargout, + "octave_core_file_name", false); +} - octave_value - load_save_system::save_default_options (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_save_default_options, args, nargout, - "save_default_options", false); - } +octave_value +load_save_system::save_default_options (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_save_default_options, args, nargout, + "save_default_options", false); +} - octave_value - load_save_system::octave_core_file_options (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_octave_core_file_options, args, nargout, - "octave_core_file_options", false); - } +octave_value +load_save_system::octave_core_file_options (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_octave_core_file_options, args, nargout, + "octave_core_file_options", false); +} - octave_value - load_save_system::save_header_format_string (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_save_header_format_string, args, nargout, - "save_header_format_string"); - } +octave_value +load_save_system::save_header_format_string (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_save_header_format_string, args, nargout, + "save_header_format_string"); +} - load_save_format - load_save_system::get_file_format (const std::string& fname, - const std::string& orig_fname, - bool& use_zlib, bool quiet) - { - load_save_format retval = UNKNOWN; +load_save_format +load_save_system::get_file_format (const std::string& fname, + const std::string& orig_fname, + bool& use_zlib, bool quiet) +{ + load_save_format retval = UNKNOWN; #if defined (HAVE_HDF5_UTF8) - std::string ascii_fname = fname; + std::string ascii_fname = fname; #else - std::string ascii_fname = sys::get_ASCII_filename (fname); + std::string ascii_fname = sys::get_ASCII_filename (fname); #endif #if defined (HAVE_HDF5) - // check this before we open the file - if (H5Fis_hdf5 (ascii_fname.c_str ()) > 0) - return HDF5; + // check this before we open the file + if (H5Fis_hdf5 (ascii_fname.c_str ()) > 0) + return HDF5; #endif #if defined (HAVE_ZLIB) - use_zlib = check_gzip_magic (fname); + use_zlib = check_gzip_magic (fname); #else - use_zlib = false; + use_zlib = false; #endif - if (! use_zlib) - { - std::ifstream file = sys::ifstream (fname.c_str (), - std::ios::in | std::ios::binary); - if (file) - { - retval = get_file_format (file, orig_fname); - file.close (); - } - else if (! quiet) - err_file_open ("load", orig_fname); - } + if (! use_zlib) + { + std::ifstream file = sys::ifstream (fname.c_str (), + std::ios::in | std::ios::binary); + if (file) + { + retval = get_file_format (file, orig_fname); + file.close (); + } + else if (! quiet) + err_file_open ("load", orig_fname); + } #if defined (HAVE_ZLIB) - else - { - gzifstream gzfile (fname.c_str (), std::ios::in | std::ios::binary); - if (gzfile) - { - retval = get_file_format (gzfile, orig_fname); - gzfile.close (); - } - else if (! quiet) - err_file_open ("load", orig_fname); - } + else + { + gzifstream gzfile (fname.c_str (), std::ios::in | std::ios::binary); + if (gzfile) + { + retval = get_file_format (gzfile, orig_fname); + gzfile.close (); + } + else if (! quiet) + err_file_open ("load", orig_fname); + } #endif - return retval; - } + return retval; +} - octave_value - load_save_system::load_vars (std::istream& stream, - const std::string& orig_fname, - const load_save_format& fmt, - mach_info::float_format flt_fmt, - bool list_only, bool swap, bool verbose, - const string_vector& argv, int argv_idx, - int argc, int nargout) - { - octave_value retval; +octave_value +load_save_system::load_vars (std::istream& stream, + const std::string& orig_fname, + const load_save_format& fmt, + mach_info::float_format flt_fmt, + bool list_only, bool swap, bool verbose, + const string_vector& argv, int argv_idx, + int argc, int nargout) +{ + octave_value retval; - octave_scalar_map retstruct; + octave_scalar_map retstruct; - std::ostringstream output_buf; - std::list symbol_names; + std::ostringstream output_buf; + std::list symbol_names; - octave_idx_type count = 0; + octave_idx_type count = 0; - for (;;) - { - bool global = false; - octave_value tc; + for (;;) + { + bool global = false; + octave_value tc; - std::string name; - std::string doc; + std::string name; + std::string doc; - switch (fmt.type ()) - { - case TEXT: - name = read_text_data (stream, orig_fname, global, tc, count); - break; + switch (fmt.type ()) + { + case TEXT: + name = read_text_data (stream, orig_fname, global, tc, count); + break; - case BINARY: - name = read_binary_data (stream, swap, flt_fmt, orig_fname, - global, tc, doc); - break; + case BINARY: + name = read_binary_data (stream, swap, flt_fmt, orig_fname, + global, tc, doc); + break; - case MAT_ASCII: - name = read_mat_ascii_data (stream, orig_fname, tc); - break; + case MAT_ASCII: + name = read_mat_ascii_data (stream, orig_fname, tc); + break; - case MAT_BINARY: - name = read_mat_binary_data (stream, orig_fname, tc); - break; + case MAT_BINARY: + name = read_mat_binary_data (stream, orig_fname, tc); + break; #if defined (HAVE_HDF5) - case HDF5: - name = read_hdf5_data (stream, orig_fname, global, tc, doc, - argv, argv_idx, argc); - break; + case HDF5: + name = read_hdf5_data (stream, orig_fname, global, tc, doc, + argv, argv_idx, argc); + break; #endif - case MAT5_BINARY: - case MAT7_BINARY: - name = read_mat5_binary_element (stream, orig_fname, swap, - global, tc); - break; + case MAT5_BINARY: + case MAT7_BINARY: + name = read_mat5_binary_element (stream, orig_fname, swap, + global, tc); + break; - default: - err_unrecognized_data_fmt ("load"); - break; - } - - if (stream.eof () || name.empty ()) + default: + err_unrecognized_data_fmt ("load"); break; - else - { - if (! tc.is_defined ()) - error ("load: unable to load variable '%s'", name.c_str ()); + } - if (fmt.type () == MAT_ASCII && argv_idx < argc) - warning ("load: loaded ASCII file '%s' -- ignoring extra args", - orig_fname.c_str ()); + if (stream.eof () || name.empty ()) + break; + else + { + if (! tc.is_defined ()) + error ("load: unable to load variable '%s'", name.c_str ()); - if (fmt.type () == MAT_ASCII - || argv_idx == argc - || matches_patterns (argv, argv_idx, argc, name)) - { - count++; - if (list_only) - { - if (verbose) - { - if (count == 1) - output_buf + if (fmt.type () == MAT_ASCII && argv_idx < argc) + warning ("load: loaded ASCII file '%s' -- ignoring extra args", + orig_fname.c_str ()); + + if (fmt.type () == MAT_ASCII + || argv_idx == argc + || matches_patterns (argv, argv_idx, argc, name)) + { + count++; + if (list_only) + { + if (verbose) + { + if (count == 1) + output_buf << "type rows cols name\n" << "==== ==== ==== ====\n"; - output_buf + output_buf << std::setiosflags (std::ios::left) << std::setw (16) << tc.type_name ().c_str () << std::setiosflags (std::ios::right) << std::setw (7) << tc.rows () << std::setw (7) << tc.columns () << " " << name << "\n"; - } - else - symbol_names.push_back (name); - } - else - { - if (nargout == 1) - { - if (fmt.type () == MAT_ASCII) - retval = tc; - else - retstruct.assign (name, tc); - } - else - install_loaded_variable (name, tc, global, doc); - } - } - - // Only attempt to read one item from a headless text file. - - if (fmt.type () == MAT_ASCII) - break; - } - } - - if (list_only && count) - { - if (verbose) - { - std::string msg = output_buf.str (); - - if (nargout > 0) - retval = msg; - else - octave_stdout << msg; - } - else - { - if (nargout > 0) - retval = Cell (string_vector (symbol_names)); - else - { - string_vector names (symbol_names); - - names.list_in_columns (octave_stdout); - - octave_stdout << "\n"; - } - } - } - else if (retstruct.nfields () != 0) - retval = retstruct; - - return retval; - } - - string_vector - load_save_system::parse_save_options (const string_vector& argv, - load_save_format& fmt, bool& append, - bool& save_as_floats, bool& use_zlib) - { -#if ! defined (HAVE_ZLIB) - octave_unused_parameter (use_zlib); -#endif - - string_vector retval; - int argc = argv.numel (); - - bool do_double = false; - bool do_tabs = false; - - for (int i = 0; i < argc; i++) - { - if (argv[i] == "-append") - { - append = true; - } - else if (argv[i] == "-ascii" || argv[i] == "-a") - { - fmt.set_type (MAT_ASCII); - } - else if (argv[i] == "-double") - { - do_double = true; - } - else if (argv[i] == "-tabs") - { - do_tabs = true; - } - else if (argv[i] == "-text" || argv[i] == "-t") - { - fmt.set_type (TEXT); - } - else if (argv[i] == "-binary" || argv[i] == "-b") - { - fmt.set_type (BINARY); - } - else if (argv[i] == "-hdf5" || argv[i] == "-h") - { -#if defined (HAVE_HDF5) - fmt.set_type (HDF5); -#else - err_disabled_feature ("save", "HDF5"); -#endif - } - else if (argv[i] == "-v7.3" || argv[i] == "-V7.3" || argv[i] == "-7.3") - { - error ("save: Matlab file format -v7.3 is not yet implemented"); - } -#if defined (HAVE_ZLIB) - else if (argv[i] == "-v7" || argv[i] == "-V7" || argv[i] == "-7" - || argv[i] == "-mat7-binary") - { - fmt.set_type (MAT7_BINARY); - } -#endif - else if (argv[i] == "-mat" || argv[i] == "-m" - || argv[i] == "-v6" || argv[i] == "-V6" || argv[i] == "-6" - || argv[i] == "-mat-binary") - { - fmt.set_type (MAT5_BINARY); - } - else if (argv[i] == "-v4" || argv[i] == "-V4" || argv[i] == "-4" - || argv[i] == "-mat4-binary") - { - fmt.set_type (MAT_BINARY); - } - else if (argv[i] == "-float-binary" || argv[i] == "-f") - { - fmt.set_type (BINARY); - save_as_floats = true; - } - else if (argv[i] == "-float-hdf5") - { -#if defined (HAVE_HDF5) - fmt.set_type (HDF5); - save_as_floats = true; -#else - err_disabled_feature ("save", "HDF5"); -#endif - } -#if defined (HAVE_ZLIB) - else if (argv[i] == "-zip" || argv[i] == "-z") - { - use_zlib = true; - } -#endif - else if (argv[i] == "-struct") - { - retval.append (argv[i]); - } - else if (argv[i][0] == '-' && argv[i] != "-") - { - error ("save: Unrecognized option '%s'", argv[i].c_str ()); - } - else - retval.append (argv[i]); - } - - if (do_double) - { - if (fmt.type () == MAT_ASCII) - fmt.set_option (MAT_ASCII_LONG); - else - warning (R"(save: "-double" option only has an effect with "-ascii")"); - } - - if (do_tabs) - { - if (fmt.type () == MAT_ASCII) - fmt.set_option (MAT_ASCII_TABS); - else - warning (R"(save: "-tabs" option only has an effect with "-ascii")"); - } - - if (append && use_zlib - && (fmt.type () != TEXT && fmt.type () != MAT_ASCII)) - error ("save: -append and -zip options can only be used together with a text format (-text or -ascii)"); - - return retval; - } - - string_vector - load_save_system::parse_save_options (const std::string& arg, - load_save_format& fmt, - bool& append, bool& save_as_floats, - bool& use_zlib) - { - std::istringstream is (arg); - std::string str; - string_vector argv; - - while (! is.eof ()) - { - is >> str; - argv.append (str); - } - - return parse_save_options (argv, fmt, append, save_as_floats, use_zlib); - } - - void load_save_system::save_vars (const string_vector& argv, int argv_idx, - int argc, std::ostream& os, - const load_save_format& fmt, - bool save_as_floats, - bool write_header_info) - { - if (write_header_info) - write_header (os, fmt); - - if (argv_idx == argc) - { - save_vars (os, "*", fmt, save_as_floats); - } - else if (argv[argv_idx] == "-struct") - { - if (++argv_idx >= argc) - error ("save: missing struct name"); - - std::string struct_name = argv[argv_idx]; - - if (! m_interpreter.is_variable (struct_name)) - error ("save: no such variable: '%s'", struct_name.c_str ()); - - octave_value struct_var = m_interpreter.varval (struct_name); - - if (! struct_var.isstruct () || struct_var.numel () != 1) - error ("save: '%s' is not a scalar structure", struct_name.c_str ()); - - octave_scalar_map struct_var_map = struct_var.scalar_map_value (); - - ++argv_idx; - - if (argv_idx < argc) - { - for (int i = argv_idx; i < argc; i++) - { - if (! save_fields (os, struct_var_map, argv[i], fmt, - save_as_floats)) - { - warning ("save: no such field '%s.%s'", - struct_name.c_str (), argv[i].c_str ()); - } - } - } - else - save_fields (os, struct_var_map, "*", fmt, save_as_floats); - } - else - { - for (int i = argv_idx; i < argc; i++) - { - if (argv[i] == "") - continue; // Skip empty vars for Matlab compatibility - if (! save_vars (os, argv[i], fmt, save_as_floats)) - warning ("save: no such variable '%s'", argv[i].c_str ()); - } - } - } - - void load_save_system::dump_octave_core (void) - { - if (m_crash_dumps_octave_core) - { - // FIXME: should choose better filename? - - const char *fname = m_octave_core_file_name.c_str (); - - message (nullptr, "attempting to save variables to '%s'...", fname); - - load_save_format fmt (BINARY); - - bool save_as_floats = false; - - bool append = false; - - bool use_zlib = false; - - load_save_system::parse_save_options (m_octave_core_file_options, - fmt, append, save_as_floats, - use_zlib); - - std::ios::openmode mode = std::ios::out; - - // Matlab v7 files are always compressed - if (fmt.type () == MAT7_BINARY) - use_zlib = false; - - if (fmt.type () == BINARY -#if defined (HAVE_HDF5) - || fmt.type () == HDF5 -#endif - || fmt.type () == MAT_BINARY - || fmt.type () == MAT5_BINARY - || fmt.type () == MAT7_BINARY) - mode |= std::ios::binary; - - mode |= append ? std::ios::ate : std::ios::trunc; - -#if defined (HAVE_HDF5) - if (fmt.type () == HDF5) - { - hdf5_ofstream file (fname, mode); - - if (file.file_id >= 0) - { - dump_octave_core (file, fname, fmt, save_as_floats); - - file.close (); - } - else - warning ("dump_octave_core: unable to open '%s' for writing...", - fname); - } - else -#endif - // don't insert any commands here! The open brace below must - // go with the else above! - { -#if defined (HAVE_ZLIB) - if (use_zlib) - { - gzofstream file (fname, mode); - - if (file) - { - dump_octave_core (file, fname, fmt, save_as_floats); - - file.close (); - } - else - warning ("dump_octave_core: unable to open '%s' for writing...", - fname); - } - else -#endif - { - std::ofstream file = sys::ofstream (fname, mode); - - if (file) - { - dump_octave_core (file, fname, fmt, save_as_floats); - - file.close (); - } - else - warning ("dump_octave_core: unable to open '%s' for writing...", - fname); - } - } - } - } - - void load_save_system::write_header (std::ostream& os, - const load_save_format& fmt) - { - switch (fmt.type ()) - { - case BINARY: - { - os << (mach_info::words_big_endian () - ? "Octave-1-B" : "Octave-1-L"); - - mach_info::float_format flt_fmt = mach_info::native_float_format (); - - char tmp = static_cast (float_format_to_mopt_digit (flt_fmt)); - - os.write (&tmp, 1); - } - break; - - case MAT5_BINARY: - case MAT7_BINARY: - { - char const *versionmagic; - char headertext[128]; - sys::gmtime now; - - // ISO 8601 format date - const char *matlab_format = "MATLAB 5.0 MAT-file, written by Octave " - OCTAVE_VERSION ", %Y-%m-%d %T UTC"; - std::string comment_string = now.strftime (matlab_format); - - std::size_t len = std::min (comment_string.length (), - static_cast (124)); - memset (headertext, ' ', 124); - memcpy (headertext, comment_string.data (), len); - - // The first pair of bytes give the version of the MAT file - // format. The second pair of bytes form a magic number which - // signals a MAT file. MAT file data are always written in - // native byte order. The order of the bytes in the second - // pair indicates whether the file was written by a big- or - // little-endian machine. However, the version number is - // written in the *opposite* byte order from everything else! - if (mach_info::words_big_endian ()) - versionmagic = "\x01\x00\x4d\x49"; // this machine is big endian - else - versionmagic = "\x00\x01\x49\x4d"; // this machine is little endian - - memcpy (headertext+124, versionmagic, 4); - os.write (headertext, 128); - } - - break; - -#if defined (HAVE_HDF5) - case HDF5: -#endif - case TEXT: - { - sys::localtime now; - - std::string comment_string = now.strftime (m_save_header_format_string); - - if (! comment_string.empty ()) - { -#if defined (HAVE_HDF5) - if (fmt.type () == HDF5) - { - hdf5_ofstream& hs = dynamic_cast (os); - H5Gset_comment (hs.file_id, "/", comment_string.c_str ()); + } + else + symbol_names.push_back (name); } else -#endif - os << comment_string << "\n"; + { + if (nargout == 1) + { + if (fmt.type () == MAT_ASCII) + retval = tc; + else + retstruct.assign (name, tc); + } + else + install_loaded_variable (name, tc, global, doc); + } + } + + // Only attempt to read one item from a headless text file. + + if (fmt.type () == MAT_ASCII) + break; + } + } + + if (list_only && count) + { + if (verbose) + { + std::string msg = output_buf.str (); + + if (nargout > 0) + retval = msg; + else + octave_stdout << msg; + } + else + { + if (nargout > 0) + retval = Cell (string_vector (symbol_names)); + else + { + string_vector names (symbol_names); + + names.list_in_columns (octave_stdout); + + octave_stdout << "\n"; } } - break; - - default: - break; - } - } - - // Save variables with names matching PATTERN on stream OS in the - // format specified by FMT. + } + else if (retstruct.nfields () != 0) + retval = retstruct; - std::size_t load_save_system::save_vars (std::ostream& os, - const std::string& pattern, - const load_save_format& fmt, - bool save_as_floats) - { - tree_evaluator& tw = m_interpreter.get_evaluator (); - - symbol_info_list syminfo_list = tw.glob_symbol_info (pattern); - - std::size_t saved = 0; - - for (const auto& syminfo : syminfo_list) - { - do_save (os, syminfo, fmt, save_as_floats); - - saved++; - } - - return saved; - } + return retval; +} - void load_save_system::do_save (std::ostream& os, const octave_value& tc, - const std::string& name, - const std::string& help, - bool global, const load_save_format& fmt, - bool save_as_floats) - { - switch (fmt.type ()) - { - case TEXT: - save_text_data (os, tc, name, global, 0); - break; - - case BINARY: - save_binary_data (os, tc, name, help, global, save_as_floats); - break; - - case MAT_ASCII: - if (! save_mat_ascii_data (os, tc, - fmt.options () & MAT_ASCII_LONG ? 16 : 8, - fmt.options () & MAT_ASCII_TABS)) - warning ("save: unable to save %s in ASCII format", name.c_str ()); - break; - - case MAT_BINARY: - save_mat_binary_data (os, tc, name); - break; - -#if defined (HAVE_HDF5) - case HDF5: - save_hdf5_data (os, tc, name, help, global, save_as_floats); - break; +string_vector +load_save_system::parse_save_options (const string_vector& argv, + load_save_format& fmt, bool& append, + bool& save_as_floats, bool& use_zlib) +{ +#if ! defined (HAVE_ZLIB) + octave_unused_parameter (use_zlib); #endif - case MAT5_BINARY: - save_mat5_binary_element (os, tc, name, global, false, save_as_floats); - break; - - case MAT7_BINARY: - save_mat5_binary_element (os, tc, name, global, true, save_as_floats); - break; - - default: - err_unrecognized_data_fmt ("save"); - break; - } - } - - // Save the info from SR on stream OS in the format specified by FMT. + string_vector retval; + int argc = argv.numel (); - void load_save_system::do_save (std::ostream& os, - const symbol_info& syminfo, - const load_save_format& fmt, - bool save_as_floats) - { - octave_value val = syminfo.value (); - - if (val.is_defined ()) - { - std::string name = syminfo.name (); - std::string help; - bool global = syminfo.is_global (); - - do_save (os, val, name, help, global, fmt, save_as_floats); - } - } + bool do_double = false; + bool do_tabs = false; - // save fields of a scalar structure STR matching PATTERN on stream OS - // in the format specified by FMT. - - std::size_t load_save_system::save_fields (std::ostream& os, - const octave_scalar_map& m, - const std::string& pattern, - const load_save_format& fmt, - bool save_as_floats) - { - glob_match pat (pattern); - - std::size_t saved = 0; - - for (auto it = m.begin (); it != m.end (); it++) - { - std::string empty_str; + for (int i = 0; i < argc; i++) + { + if (argv[i] == "-append") + { + append = true; + } + else if (argv[i] == "-ascii" || argv[i] == "-a") + { + fmt.set_type (MAT_ASCII); + } + else if (argv[i] == "-double") + { + do_double = true; + } + else if (argv[i] == "-tabs") + { + do_tabs = true; + } + else if (argv[i] == "-text" || argv[i] == "-t") + { + fmt.set_type (TEXT); + } + else if (argv[i] == "-binary" || argv[i] == "-b") + { + fmt.set_type (BINARY); + } + else if (argv[i] == "-hdf5" || argv[i] == "-h") + { +#if defined (HAVE_HDF5) + fmt.set_type (HDF5); +#else + err_disabled_feature ("save", "HDF5"); +#endif + } + else if (argv[i] == "-v7.3" || argv[i] == "-V7.3" || argv[i] == "-7.3") + { + error ("save: Matlab file format -v7.3 is not yet implemented"); + } +#if defined (HAVE_ZLIB) + else if (argv[i] == "-v7" || argv[i] == "-V7" || argv[i] == "-7" + || argv[i] == "-mat7-binary") + { + fmt.set_type (MAT7_BINARY); + } +#endif + else if (argv[i] == "-mat" || argv[i] == "-m" + || argv[i] == "-v6" || argv[i] == "-V6" || argv[i] == "-6" + || argv[i] == "-mat-binary") + { + fmt.set_type (MAT5_BINARY); + } + else if (argv[i] == "-v4" || argv[i] == "-V4" || argv[i] == "-4" + || argv[i] == "-mat4-binary") + { + fmt.set_type (MAT_BINARY); + } + else if (argv[i] == "-float-binary" || argv[i] == "-f") + { + fmt.set_type (BINARY); + save_as_floats = true; + } + else if (argv[i] == "-float-hdf5") + { +#if defined (HAVE_HDF5) + fmt.set_type (HDF5); + save_as_floats = true; +#else + err_disabled_feature ("save", "HDF5"); +#endif + } +#if defined (HAVE_ZLIB) + else if (argv[i] == "-zip" || argv[i] == "-z") + { + use_zlib = true; + } +#endif + else if (argv[i] == "-struct") + { + retval.append (argv[i]); + } + else if (argv[i][0] == '-' && argv[i] != "-") + { + error ("save: Unrecognized option '%s'", argv[i].c_str ()); + } + else + retval.append (argv[i]); + } - if (pat.match (m.key (it))) - { - do_save (os, m.contents (it), m.key (it), empty_str, - 0, fmt, save_as_floats); + if (do_double) + { + if (fmt.type () == MAT_ASCII) + fmt.set_option (MAT_ASCII_LONG); + else + warning (R"(save: "-double" option only has an effect with "-ascii")"); + } - saved++; - } - } + if (do_tabs) + { + if (fmt.type () == MAT_ASCII) + fmt.set_option (MAT_ASCII_TABS); + else + warning (R"(save: "-tabs" option only has an effect with "-ascii")"); + } + + if (append && use_zlib + && (fmt.type () != TEXT && fmt.type () != MAT_ASCII)) + error ("save: -append and -zip options can only be used together with a text format (-text or -ascii)"); + + return retval; +} - return saved; - } +string_vector +load_save_system::parse_save_options (const std::string& arg, + load_save_format& fmt, + bool& append, bool& save_as_floats, + bool& use_zlib) +{ + std::istringstream is (arg); + std::string str; + string_vector argv; - void load_save_system::dump_octave_core (std::ostream& os, - const char *fname, - const load_save_format& fmt, - bool save_as_floats) - { + while (! is.eof ()) + { + is >> str; + argv.append (str); + } + + return parse_save_options (argv, fmt, append, save_as_floats, use_zlib); +} + +void load_save_system::save_vars (const string_vector& argv, int argv_idx, + int argc, std::ostream& os, + const load_save_format& fmt, + bool save_as_floats, + bool write_header_info) +{ + if (write_header_info) write_header (os, fmt); - tree_evaluator& tw = m_interpreter.get_evaluator (); - - symbol_info_list syminfo_list = tw.top_scope_symbol_info (); - - double save_mem_size = 0; - - for (const auto& syminfo : syminfo_list) - { - octave_value val = syminfo.value (); - - std::string name = syminfo.name (); - std::string help; - bool global = syminfo.is_global (); - - double val_size = val.byte_size () / 1024; - - // FIXME: maybe we should try to throw out the largest first... - - if (m_octave_core_file_limit < 0 - || save_mem_size + val_size < m_octave_core_file_limit) - { - save_mem_size += val_size; + if (argv_idx == argc) + { + save_vars (os, "*", fmt, save_as_floats); + } + else if (argv[argv_idx] == "-struct") + { + if (++argv_idx >= argc) + error ("save: missing struct name"); - do_save (os, val, name, help, global, fmt, save_as_floats); - } - } - - message (nullptr, "save to '%s' complete", fname); - } - - // Install a variable with name NAME and the value VAL in the - // symbol table. If GLOBAL is TRUE, make the variable global. - - void load_save_system::install_loaded_variable (const std::string& name, - const octave_value& val, - bool global, - const std::string& /*doc*/) - { - m_interpreter.install_variable (name, val, global); - } - - std::string load_save_system::init_save_header_format (void) - { - return - (std::string ("# Created by Octave " OCTAVE_VERSION - ", %a %b %d %H:%M:%S %Y %Z <") - + sys::env::get_user_name () - + '@' - + sys::env::get_host_name () - + '>'); - } + std::string struct_name = argv[argv_idx]; - load_save_format - load_save_system::get_file_format (std::istream& file, - const std::string& filename) - { - load_save_format retval = load_save_system::UNKNOWN; - - mach_info::float_format flt_fmt - = mach_info::flt_fmt_unknown; - - bool swap = false; + if (! m_interpreter.is_variable (struct_name)) + error ("save: no such variable: '%s'", struct_name.c_str ()); - if (read_binary_file_header (file, swap, flt_fmt, true) == 0) - retval = BINARY; - else - { - file.clear (); - file.seekg (0, std::ios::beg); - - int32_t mopt, nr, nc, imag, len; - - int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, - true); - - if (! err) - retval = MAT_BINARY; - else - { - file.clear (); - file.seekg (0, std::ios::beg); + octave_value struct_var = m_interpreter.varval (struct_name); - err = read_mat5_binary_file_header (file, swap, true, filename); - - if (! err) - { - file.clear (); - file.seekg (0, std::ios::beg); - retval = MAT5_BINARY; - } - else - { - file.clear (); - file.seekg (0, std::ios::beg); + if (! struct_var.isstruct () || struct_var.numel () != 1) + error ("save: '%s' is not a scalar structure", struct_name.c_str ()); - std::string name_val = extract_keyword (file, "name"); - std::string type_val = extract_keyword (file, "type"); + octave_scalar_map struct_var_map = struct_var.scalar_map_value (); - if (name_val.empty () != true && type_val.empty () != true) - retval = TEXT; - else - { - file.clear (); - file.seekg (0, std::ios::beg); - - // FIXME: looks_like_mat_ascii_file does not check - // to see whether the file contains numbers. It - // just skips comments and checks for the same - // number of words on each line. We may need a - // better check here. The best way to do that might - // be just to try to read the file and see if it - // works. + ++argv_idx; - if (looks_like_mat_ascii_file (file, filename)) - retval = MAT_ASCII; - } - } - } - } - - return retval; - } - - octave_value_list - load_save_system::load (const octave_value_list& args, int nargout) - { - octave_value_list retval; - - int argc = args.length () + 1; - - string_vector argv = args.make_argv ("load"); - - int i = 1; - std::string orig_fname = ""; + if (argv_idx < argc) + { + for (int i = argv_idx; i < argc; i++) + { + if (! save_fields (os, struct_var_map, argv[i], fmt, + save_as_floats)) + { + warning ("save: no such field '%s.%s'", + struct_name.c_str (), argv[i].c_str ()); + } + } + } + else + save_fields (os, struct_var_map, "*", fmt, save_as_floats); + } + else + { + for (int i = argv_idx; i < argc; i++) + { + if (argv[i] == "") + continue; // Skip empty vars for Matlab compatibility + if (! save_vars (os, argv[i], fmt, save_as_floats)) + warning ("save: no such variable '%s'", argv[i].c_str ()); + } + } +} - // Function called with Matlab-style ["filename", options] syntax - if (argc > 1 && ! argv[1].empty () && argv[1].at (0) != '-') - { - orig_fname = argv[1]; - i++; - } +void load_save_system::dump_octave_core (void) +{ + if (m_crash_dumps_octave_core) + { + // FIXME: should choose better filename? + + const char *fname = m_octave_core_file_name.c_str (); - // It isn't necessary to have the default load format stored in a - // user preference variable since we can determine the type of file - // as we are reading. + message (nullptr, "attempting to save variables to '%s'...", fname); + + load_save_format fmt (BINARY); - load_save_format format = UNKNOWN; + bool save_as_floats = false; - bool list_only = false; - bool verbose = false; + bool append = false; - for (; i < argc; i++) - { - if (argv[i] == "-text" || argv[i] == "-t") - { - format = TEXT; - } - else if (argv[i] == "-binary" || argv[i] == "-b") - { - format = BINARY; - } - else if (argv[i] == "-hdf5" || argv[i] == "-h") - { + bool use_zlib = false; + + load_save_system::parse_save_options (m_octave_core_file_options, + fmt, append, save_as_floats, + use_zlib); + + std::ios::openmode mode = std::ios::out; + + // Matlab v7 files are always compressed + if (fmt.type () == MAT7_BINARY) + use_zlib = false; + + if (fmt.type () == BINARY #if defined (HAVE_HDF5) - format = HDF5; -#else - err_disabled_feature ("load", "HDF5"); + || fmt.type () == HDF5 #endif - } - else if (argv[i] == "-ascii" || argv[i] == "-a") - { - format = MAT_ASCII; - } - else if (argv[i] == "-v7.3" || argv[i] == "-V7.3" || argv[i] == "-7.3") - { - error ("load: Matlab file format -v7.3 is not yet implemented"); - } - else if (argv[i] == "-v7" || argv[i] == "-V7" || argv[i] == "-7" - || argv[i] == "-mat7-binary") - { - format = MAT7_BINARY; - } - else if (argv[i] == "-mat" || argv[i] == "-m" - || argv[i] == "-v6" || argv[i] == "-V6" || argv[i] == "-6" - || argv[i] == "-mat-binary") - { - format = MAT5_BINARY; - } - else if (argv[i] == "-v4" || argv[i] == "-V4" || argv[i] == "-4" - || argv[i] == "-mat4-binary") - { - format = MAT_BINARY; - } - else if (argv[i] == "-force" || argv[i] == "-f") - { - // Silently ignore this - // warning ("load: -force ignored"); - } - else if (argv[i] == "-import" || argv[i] == "-i") - { - warning ("load: -import ignored"); - } - else if (argv[i] == "-list" || argv[i] == "-l") - { - list_only = true; - } - else if (argv[i] == "-verbose" || argv[i] == "-v") - { - verbose = true; - } - else - break; - } + || fmt.type () == MAT_BINARY + || fmt.type () == MAT5_BINARY + || fmt.type () == MAT7_BINARY) + mode |= std::ios::binary; - if (orig_fname == "") - { - if (i == argc) - print_usage (); - - orig_fname = argv[i]; - } - else - i--; - - mach_info::float_format flt_fmt = mach_info::flt_fmt_unknown; - - bool swap = false; - - if (orig_fname == "-") - { - i++; + mode |= append ? std::ios::ate : std::ios::trunc; #if defined (HAVE_HDF5) - if (format.type () == HDF5) - error ("load: cannot read HDF5 format from stdin"); - else -#endif - if (format.type () != UNKNOWN) + if (fmt.type () == HDF5) + { + hdf5_ofstream file (fname, mode); + + if (file.file_id >= 0) { - // FIXME: if we have already seen EOF on a previous call, - // how do we fix up the state of std::cin so that we can get - // additional input? I'm afraid that we can't fix this - // using std::cin only. + dump_octave_core (file, fname, fmt, save_as_floats); - retval = load_vars (std::cin, orig_fname, format, flt_fmt, - list_only, swap, verbose, argv, i, - argc, nargout); + file.close (); } else - error ("load: must specify file format if reading from stdin"); - } - else - { - std::string fname = sys::file_ops::tilde_expand (orig_fname); - - fname = find_file_to_load (fname, orig_fname); - - bool use_zlib = false; - - if (format.type () == UNKNOWN) - format = get_file_format (fname, orig_fname, use_zlib); - -#if defined (HAVE_HDF5) - if (format.type () == HDF5) - { - i++; - - hdf5_ifstream hdf5_file (fname.c_str ()); - - if (hdf5_file.file_id < 0) - err_file_open ("load", orig_fname); - - retval = load_vars (hdf5_file, orig_fname, format, flt_fmt, - list_only, swap, verbose, argv, i, - argc, nargout); - - hdf5_file.close (); - } - else + warning ("dump_octave_core: unable to open '%s' for writing...", + fname); + } + else #endif - // don't insert any statements here; the "else" above has to - // go with the "if" below!!!!! - if (format.type () != UNKNOWN) + // don't insert any commands here! The open brace below must + // go with the else above! + { +#if defined (HAVE_ZLIB) + if (use_zlib) { - i++; - - // Always open in binary mode and handle various - // line-endings explicitly. - std::ios::openmode mode = std::ios::in | std::ios::binary; + gzofstream file (fname, mode); -#if defined (HAVE_ZLIB) - if (use_zlib) + if (file) { - gzifstream file (fname.c_str (), mode); - - if (! file) - err_file_open ("load", orig_fname); + dump_octave_core (file, fname, fmt, save_as_floats); - if (format.type () == BINARY) - { - if (read_binary_file_header (file, swap, flt_fmt) < 0) - { - if (file) file.close (); - return retval; - } - } - else if (format.type () == MAT5_BINARY - || format.type () == MAT7_BINARY) - { - if (read_mat5_binary_file_header (file, swap, false, - orig_fname) < 0) - { - if (file) file.close (); - return retval; - } - } + file.close (); + } + else + warning ("dump_octave_core: unable to open '%s' for writing...", + fname); + } + else +#endif + { + std::ofstream file = sys::ofstream (fname, mode); - retval = load_vars (file, orig_fname, format, flt_fmt, - list_only, swap, verbose, argv, i, - argc, nargout); + if (file) + { + dump_octave_core (file, fname, fmt, save_as_floats); file.close (); } else -#endif - { - std::ifstream file = sys::ifstream (fname.c_str (), mode); + warning ("dump_octave_core: unable to open '%s' for writing...", + fname); + } + } + } +} - if (! file) - error ("load: unable to open input file '%s'", - orig_fname.c_str ()); +void load_save_system::write_header (std::ostream& os, + const load_save_format& fmt) +{ + switch (fmt.type ()) + { + case BINARY: + { + os << (mach_info::words_big_endian () + ? "Octave-1-B" : "Octave-1-L"); + + mach_info::float_format flt_fmt = mach_info::native_float_format (); + + char tmp = static_cast (float_format_to_mopt_digit (flt_fmt)); + + os.write (&tmp, 1); + } + break; - if (format.type () == BINARY) - { - if (read_binary_file_header (file, swap, flt_fmt) < 0) - { - if (file) file.close (); - return retval; - } - } - else if (format.type () == MAT5_BINARY - || format.type () == MAT7_BINARY) - { - if (read_mat5_binary_file_header (file, swap, false, - orig_fname) < 0) - { - if (file) file.close (); - return retval; - } - } + case MAT5_BINARY: + case MAT7_BINARY: + { + char const *versionmagic; + char headertext[128]; + sys::gmtime now; + + // ISO 8601 format date + const char *matlab_format = "MATLAB 5.0 MAT-file, written by Octave " + OCTAVE_VERSION ", %Y-%m-%d %T UTC"; + std::string comment_string = now.strftime (matlab_format); - retval = load_vars (file, orig_fname, format, flt_fmt, - list_only, swap, verbose, argv, i, - argc, nargout); + std::size_t len = std::min (comment_string.length (), + static_cast (124)); + memset (headertext, ' ', 124); + memcpy (headertext, comment_string.data (), len); - file.close (); - } - } - else - error ("load: unable to determine file format of '%s'", - orig_fname.c_str ()); + // The first pair of bytes give the version of the MAT file + // format. The second pair of bytes form a magic number which + // signals a MAT file. MAT file data are always written in + // native byte order. The order of the bytes in the second + // pair indicates whether the file was written by a big- or + // little-endian machine. However, the version number is + // written in the *opposite* byte order from everything else! + if (mach_info::words_big_endian ()) + versionmagic = "\x01\x00\x4d\x49"; // this machine is big endian + else + versionmagic = "\x00\x01\x49\x4d"; // this machine is little endian + memcpy (headertext+124, versionmagic, 4); + os.write (headertext, 128); } - return retval; - } + break; + +#if defined (HAVE_HDF5) + case HDF5: +#endif + case TEXT: + { + sys::localtime now; + + std::string comment_string = now.strftime (m_save_header_format_string); - octave_value_list - load_save_system::save (const octave_value_list& args, int nargout) - { - // Here is where we would get the default save format if it were - // stored in a user preference variable. - load_save_format format = TEXT; - bool save_as_floats = false; - bool append = false; - bool use_zlib = false; + if (! comment_string.empty ()) + { +#if defined (HAVE_HDF5) + if (fmt.type () == HDF5) + { + hdf5_ofstream& hs = dynamic_cast (os); + H5Gset_comment (hs.file_id, "/", comment_string.c_str ()); + } + else +#endif + os << comment_string << "\n"; + } + } + break; + default: + break; + } +} - // get default options - parse_save_options (save_default_options (), format, append, - save_as_floats, use_zlib); +// Save variables with names matching PATTERN on stream OS in the +// format specified by FMT. + +std::size_t load_save_system::save_vars (std::ostream& os, + const std::string& pattern, + const load_save_format& fmt, + bool save_as_floats) +{ + tree_evaluator& tw = m_interpreter.get_evaluator (); - // override from command line - string_vector argv = args.make_argv (); + symbol_info_list syminfo_list = tw.glob_symbol_info (pattern); + + std::size_t saved = 0; - argv = parse_save_options (argv, format, append, save_as_floats, use_zlib); + for (const auto& syminfo : syminfo_list) + { + do_save (os, syminfo, fmt, save_as_floats); - int argc = argv.numel (); - int i = 0; + saved++; + } + + return saved; +} - if (i == argc) - print_usage (); - - if (save_as_floats && format.type () == TEXT) - error ("save: cannot specify both -text and -float-binary"); +void load_save_system::do_save (std::ostream& os, const octave_value& tc, + const std::string& name, + const std::string& help, + bool global, const load_save_format& fmt, + bool save_as_floats) +{ + switch (fmt.type ()) + { + case TEXT: + save_text_data (os, tc, name, global, 0); + break; - octave_value_list retval; + case BINARY: + save_binary_data (os, tc, name, help, global, save_as_floats); + break; - if (argv[i] == "-") - { - i++; + case MAT_ASCII: + if (! save_mat_ascii_data (os, tc, + fmt.options () & MAT_ASCII_LONG ? 16 : 8, + fmt.options () & MAT_ASCII_TABS)) + warning ("save: unable to save %s in ASCII format", name.c_str ()); + break; + + case MAT_BINARY: + save_mat_binary_data (os, tc, name); + break; #if defined (HAVE_HDF5) - if (format.type () == HDF5) - error ("save: cannot write HDF5 format to stdout"); - else + case HDF5: + save_hdf5_data (os, tc, name, help, global, save_as_floats); + break; #endif - // don't insert any commands here! the brace below must go - // with the "else" above! - { - if (append) - warning ("save: ignoring -append option for output to stdout"); + + case MAT5_BINARY: + save_mat5_binary_element (os, tc, name, global, false, save_as_floats); + break; + + case MAT7_BINARY: + save_mat5_binary_element (os, tc, name, global, true, save_as_floats); + break; + + default: + err_unrecognized_data_fmt ("save"); + break; + } +} + +// Save the info from SR on stream OS in the format specified by FMT. + +void load_save_system::do_save (std::ostream& os, + const symbol_info& syminfo, + const load_save_format& fmt, + bool save_as_floats) +{ + octave_value val = syminfo.value (); + + if (val.is_defined ()) + { + std::string name = syminfo.name (); + std::string help; + bool global = syminfo.is_global (); + + do_save (os, val, name, help, global, fmt, save_as_floats); + } +} + +// save fields of a scalar structure STR matching PATTERN on stream OS +// in the format specified by FMT. + +std::size_t load_save_system::save_fields (std::ostream& os, + const octave_scalar_map& m, + const std::string& pattern, + const load_save_format& fmt, + bool save_as_floats) +{ + glob_match pat (pattern); + + std::size_t saved = 0; + + for (auto it = m.begin (); it != m.end (); it++) + { + std::string empty_str; + + if (pat.match (m.key (it))) + { + do_save (os, m.contents (it), m.key (it), empty_str, + 0, fmt, save_as_floats); + + saved++; + } + } + + return saved; +} + +void load_save_system::dump_octave_core (std::ostream& os, + const char *fname, + const load_save_format& fmt, + bool save_as_floats) +{ + write_header (os, fmt); + + tree_evaluator& tw = m_interpreter.get_evaluator (); + + symbol_info_list syminfo_list = tw.top_scope_symbol_info (); + + double save_mem_size = 0; + + for (const auto& syminfo : syminfo_list) + { + octave_value val = syminfo.value (); + + std::string name = syminfo.name (); + std::string help; + bool global = syminfo.is_global (); + + double val_size = val.byte_size () / 1024; + + // FIXME: maybe we should try to throw out the largest first... + + if (m_octave_core_file_limit < 0 + || save_mem_size + val_size < m_octave_core_file_limit) + { + save_mem_size += val_size; + + do_save (os, val, name, help, global, fmt, save_as_floats); + } + } + + message (nullptr, "save to '%s' complete", fname); +} + +// Install a variable with name NAME and the value VAL in the +// symbol table. If GLOBAL is TRUE, make the variable global. + +void load_save_system::install_loaded_variable (const std::string& name, + const octave_value& val, + bool global, + const std::string& /*doc*/) +{ + m_interpreter.install_variable (name, val, global); +} + +std::string load_save_system::init_save_header_format (void) +{ + return + (std::string ("# Created by Octave " OCTAVE_VERSION + ", %a %b %d %H:%M:%S %Y %Z <") + + sys::env::get_user_name () + + '@' + + sys::env::get_host_name () + + '>'); +} + +load_save_format +load_save_system::get_file_format (std::istream& file, + const std::string& filename) +{ + load_save_format retval = load_save_system::UNKNOWN; + + mach_info::float_format flt_fmt + = mach_info::flt_fmt_unknown; + + bool swap = false; + + if (read_binary_file_header (file, swap, flt_fmt, true) == 0) + retval = BINARY; + else + { + file.clear (); + file.seekg (0, std::ios::beg); + + int32_t mopt, nr, nc, imag, len; + + int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, + true); - if (nargout == 0) - save_vars (argv, i, argc, octave_stdout, format, - save_as_floats, true); - else - { - std::ostringstream output_buf; - save_vars (argv, i, argc, output_buf, format, - save_as_floats, true); - retval = octave_value (output_buf.str()); - } - } - } + if (! err) + retval = MAT_BINARY; + else + { + file.clear (); + file.seekg (0, std::ios::beg); + + err = read_mat5_binary_file_header (file, swap, true, filename); + + if (! err) + { + file.clear (); + file.seekg (0, std::ios::beg); + retval = MAT5_BINARY; + } + else + { + file.clear (); + file.seekg (0, std::ios::beg); + + std::string name_val = extract_keyword (file, "name"); + std::string type_val = extract_keyword (file, "type"); + + if (name_val.empty () != true && type_val.empty () != true) + retval = TEXT; + else + { + file.clear (); + file.seekg (0, std::ios::beg); + + // FIXME: looks_like_mat_ascii_file does not check + // to see whether the file contains numbers. It + // just skips comments and checks for the same + // number of words on each line. We may need a + // better check here. The best way to do that might + // be just to try to read the file and see if it + // works. - // Guard against things like 'save a*', which are probably mistakes... + if (looks_like_mat_ascii_file (file, filename)) + retval = MAT_ASCII; + } + } + } + } + + return retval; +} + +octave_value_list +load_save_system::load (const octave_value_list& args, int nargout) +{ + octave_value_list retval; + + int argc = args.length () + 1; + + string_vector argv = args.make_argv ("load"); + + int i = 1; + std::string orig_fname = ""; + + // Function called with Matlab-style ["filename", options] syntax + if (argc > 1 && ! argv[1].empty () && argv[1].at (0) != '-') + { + orig_fname = argv[1]; + i++; + } + + // It isn't necessary to have the default load format stored in a + // user preference variable since we can determine the type of file + // as we are reading. + + load_save_format format = UNKNOWN; + + bool list_only = false; + bool verbose = false; - else if (i == argc - 1 && glob_pattern_p (argv[i])) - print_usage (); - else - { - std::string fname = sys::file_ops::tilde_expand (argv[i]); - - i++; + for (; i < argc; i++) + { + if (argv[i] == "-text" || argv[i] == "-t") + { + format = TEXT; + } + else if (argv[i] == "-binary" || argv[i] == "-b") + { + format = BINARY; + } + else if (argv[i] == "-hdf5" || argv[i] == "-h") + { +#if defined (HAVE_HDF5) + format = HDF5; +#else + err_disabled_feature ("load", "HDF5"); +#endif + } + else if (argv[i] == "-ascii" || argv[i] == "-a") + { + format = MAT_ASCII; + } + else if (argv[i] == "-v7.3" || argv[i] == "-V7.3" || argv[i] == "-7.3") + { + error ("load: Matlab file format -v7.3 is not yet implemented"); + } + else if (argv[i] == "-v7" || argv[i] == "-V7" || argv[i] == "-7" + || argv[i] == "-mat7-binary") + { + format = MAT7_BINARY; + } + else if (argv[i] == "-mat" || argv[i] == "-m" + || argv[i] == "-v6" || argv[i] == "-V6" || argv[i] == "-6" + || argv[i] == "-mat-binary") + { + format = MAT5_BINARY; + } + else if (argv[i] == "-v4" || argv[i] == "-V4" || argv[i] == "-4" + || argv[i] == "-mat4-binary") + { + format = MAT_BINARY; + } + else if (argv[i] == "-force" || argv[i] == "-f") + { + // Silently ignore this + // warning ("load: -force ignored"); + } + else if (argv[i] == "-import" || argv[i] == "-i") + { + warning ("load: -import ignored"); + } + else if (argv[i] == "-list" || argv[i] == "-l") + { + list_only = true; + } + else if (argv[i] == "-verbose" || argv[i] == "-v") + { + verbose = true; + } + else + break; + } - // Matlab v7 files are always compressed - if (format.type () == MAT7_BINARY) - use_zlib = false; + if (orig_fname == "") + { + if (i == argc) + print_usage (); - std::ios::openmode mode - = (append ? (std::ios::app | std::ios::ate) : std::ios::out); + orig_fname = argv[i]; + } + else + i--; - // Always open in binary mode to save line endings as is. - mode |= std::ios::binary; + mach_info::float_format flt_fmt = mach_info::flt_fmt_unknown; + + bool swap = false; + + if (orig_fname == "-") + { + i++; #if defined (HAVE_HDF5) - if (format.type () == HDF5) + if (format.type () == HDF5) + error ("load: cannot read HDF5 format from stdin"); + else +#endif + if (format.type () != UNKNOWN) { - // FIXME: It should be possible to append to HDF5 files. - if (append) - error ("save: appending to HDF5 files is not implemented"); - -# if defined (HAVE_HDF5_UTF8) - bool write_header_info - = ! (append && H5Fis_hdf5 (fname.c_str ()) > 0); -# else - std::string ascii_fname = sys::get_ASCII_filename (fname); + // FIXME: if we have already seen EOF on a previous call, + // how do we fix up the state of std::cin so that we can get + // additional input? I'm afraid that we can't fix this + // using std::cin only. - bool write_header_info - = ! (append && H5Fis_hdf5 (ascii_fname.c_str ()) > 0); -# endif - - hdf5_ofstream hdf5_file (fname.c_str (), mode); - - if (hdf5_file.file_id == -1) - err_file_open ("save", fname); - - save_vars (argv, i, argc, hdf5_file, format, save_as_floats, - write_header_info); - - hdf5_file.close (); + retval = load_vars (std::cin, orig_fname, format, flt_fmt, + list_only, swap, verbose, argv, i, + argc, nargout); } else + error ("load: must specify file format if reading from stdin"); + } + else + { + std::string fname = sys::file_ops::tilde_expand (orig_fname); + + fname = find_file_to_load (fname, orig_fname); + + bool use_zlib = false; + + if (format.type () == UNKNOWN) + format = get_file_format (fname, orig_fname, use_zlib); + +#if defined (HAVE_HDF5) + if (format.type () == HDF5) + { + i++; + + hdf5_ifstream hdf5_file (fname.c_str ()); + + if (hdf5_file.file_id < 0) + err_file_open ("load", orig_fname); + + retval = load_vars (hdf5_file, orig_fname, format, flt_fmt, + list_only, swap, verbose, argv, i, + argc, nargout); + + hdf5_file.close (); + } + else #endif - // don't insert any statements here! The brace below must go - // with the "else" above! + // don't insert any statements here; the "else" above has to + // go with the "if" below!!!!! + if (format.type () != UNKNOWN) { + i++; + + // Always open in binary mode and handle various + // line-endings explicitly. + std::ios::openmode mode = std::ios::in | std::ios::binary; + #if defined (HAVE_ZLIB) if (use_zlib) { - gzofstream file (fname.c_str (), mode); + gzifstream file (fname.c_str (), mode); if (! file) - err_file_open ("save", fname); + err_file_open ("load", orig_fname); - bool write_header_info = ! file.tellp (); + if (format.type () == BINARY) + { + if (read_binary_file_header (file, swap, flt_fmt) < 0) + { + if (file) file.close (); + return retval; + } + } + else if (format.type () == MAT5_BINARY + || format.type () == MAT7_BINARY) + { + if (read_mat5_binary_file_header (file, swap, false, + orig_fname) < 0) + { + if (file) file.close (); + return retval; + } + } - save_vars (argv, i, argc, file, format, save_as_floats, - write_header_info); + retval = load_vars (file, orig_fname, format, flt_fmt, + list_only, swap, verbose, argv, i, + argc, nargout); file.close (); } else #endif { - std::ofstream file = sys::ofstream (fname.c_str (), mode); + std::ifstream file = sys::ifstream (fname.c_str (), mode); if (! file) - err_file_open ("save", fname); + error ("load: unable to open input file '%s'", + orig_fname.c_str ()); - bool write_header_info = ! file.tellp (); + if (format.type () == BINARY) + { + if (read_binary_file_header (file, swap, flt_fmt) < 0) + { + if (file) file.close (); + return retval; + } + } + else if (format.type () == MAT5_BINARY + || format.type () == MAT7_BINARY) + { + if (read_mat5_binary_file_header (file, swap, false, + orig_fname) < 0) + { + if (file) file.close (); + return retval; + } + } - save_vars (argv, i, argc, file, format, save_as_floats, - write_header_info); + retval = load_vars (file, orig_fname, format, flt_fmt, + list_only, swap, verbose, argv, i, + argc, nargout); file.close (); } } - } + else + error ("load: unable to determine file format of '%s'", + orig_fname.c_str ()); + + } + + return retval; +} + +octave_value_list +load_save_system::save (const octave_value_list& args, int nargout) +{ + // Here is where we would get the default save format if it were + // stored in a user preference variable. + load_save_format format = TEXT; + bool save_as_floats = false; + bool append = false; + bool use_zlib = false; + + + // get default options + parse_save_options (save_default_options (), format, append, + save_as_floats, use_zlib); + + // override from command line + string_vector argv = args.make_argv (); + + argv = parse_save_options (argv, format, append, save_as_floats, use_zlib); + + int argc = argv.numel (); + int i = 0; + + if (i == argc) + print_usage (); + + if (save_as_floats && format.type () == TEXT) + error ("save: cannot specify both -text and -float-binary"); + + octave_value_list retval; + + if (argv[i] == "-") + { + i++; + +#if defined (HAVE_HDF5) + if (format.type () == HDF5) + error ("save: cannot write HDF5 format to stdout"); + else +#endif + // don't insert any commands here! the brace below must go + // with the "else" above! + { + if (append) + warning ("save: ignoring -append option for output to stdout"); + + if (nargout == 0) + save_vars (argv, i, argc, octave_stdout, format, + save_as_floats, true); + else + { + std::ostringstream output_buf; + save_vars (argv, i, argc, output_buf, format, + save_as_floats, true); + retval = octave_value (output_buf.str()); + } + } + } + + // Guard against things like 'save a*', which are probably mistakes... + + else if (i == argc - 1 && glob_pattern_p (argv[i])) + print_usage (); + else + { + std::string fname = sys::file_ops::tilde_expand (argv[i]); + + i++; - return retval; - } + // Matlab v7 files are always compressed + if (format.type () == MAT7_BINARY) + use_zlib = false; + + std::ios::openmode mode + = (append ? (std::ios::app | std::ios::ate) : std::ios::out); + + // Always open in binary mode to save line endings as is. + mode |= std::ios::binary; + +#if defined (HAVE_HDF5) + if (format.type () == HDF5) + { + // FIXME: It should be possible to append to HDF5 files. + if (append) + error ("save: appending to HDF5 files is not implemented"); + +# if defined (HAVE_HDF5_UTF8) + bool write_header_info + = ! (append && H5Fis_hdf5 (fname.c_str ()) > 0); +# else + std::string ascii_fname = sys::get_ASCII_filename (fname); + + bool write_header_info + = ! (append && H5Fis_hdf5 (ascii_fname.c_str ()) > 0); +# endif + + hdf5_ofstream hdf5_file (fname.c_str (), mode); + + if (hdf5_file.file_id == -1) + err_file_open ("save", fname); + + save_vars (argv, i, argc, hdf5_file, format, save_as_floats, + write_header_info); + + hdf5_file.close (); + } + else +#endif + // don't insert any statements here! The brace below must go + // with the "else" above! + { +#if defined (HAVE_ZLIB) + if (use_zlib) + { + gzofstream file (fname.c_str (), mode); + + if (! file) + err_file_open ("save", fname); + + bool write_header_info = ! file.tellp (); + + save_vars (argv, i, argc, file, format, save_as_floats, + write_header_info); + + file.close (); + } + else +#endif + { + std::ofstream file = sys::ofstream (fname.c_str (), mode); + + if (! file) + err_file_open ("save", fname); + + bool write_header_info = ! file.tellp (); + + save_vars (argv, i, argc, file, format, save_as_floats, + write_header_info); + + file.close (); + } + } + } + + return retval; +} DEFMETHOD (load, interp, args, nargout, doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/load-save.h --- a/libinterp/corefcn/load-save.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/load-save.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,260 +37,260 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; - class load_save_format; - class symbol_info; +class interpreter; +class load_save_format; +class symbol_info; - class load_save_system - { - public: +class load_save_system +{ +public: - // FIXME: maybe MAT5 and MAT7 should be options to MAT_BINARY. - // Similarly, save_as_floats may be an option for LS_BINARY, - // LS_HDF5 etc. + // FIXME: maybe MAT5 and MAT7 should be options to MAT_BINARY. + // Similarly, save_as_floats may be an option for LS_BINARY, + // LS_HDF5 etc. - enum format_type - { - TEXT, - BINARY, - MAT_ASCII, - MAT_BINARY, - MAT5_BINARY, - MAT7_BINARY, - HDF5, - UNKNOWN - }; + enum format_type + { + TEXT, + BINARY, + MAT_ASCII, + MAT_BINARY, + MAT5_BINARY, + MAT7_BINARY, + HDF5, + UNKNOWN + }; - enum format_options - { - // MAT_ASCII options (not exclusive) - MAT_ASCII_LONG = 1, - MAT_ASCII_TABS = 2, - // MAT_BINARY options - MAT_BINARY_V5 = 1, - MAT_BINARY_V7, - // zero means no option. - NO_OPTION = 0 - }; + enum format_options + { + // MAT_ASCII options (not exclusive) + MAT_ASCII_LONG = 1, + MAT_ASCII_TABS = 2, + // MAT_BINARY options + MAT_BINARY_V5 = 1, + MAT_BINARY_V7, + // zero means no option. + NO_OPTION = 0 + }; - OCTINTERP_API load_save_system (interpreter& interp); + OCTINTERP_API load_save_system (interpreter& interp); - OCTINTERP_API ~load_save_system (void); + OCTINTERP_API ~load_save_system (void); - load_save_system (const load_save_system&) = delete; + load_save_system (const load_save_system&) = delete; - load_save_system& operator = (const load_save_system&) = delete; + load_save_system& operator = (const load_save_system&) = delete; - OCTINTERP_API octave_value - crash_dumps_octave_core (const octave_value_list& args, int nargout); + OCTINTERP_API octave_value + crash_dumps_octave_core (const octave_value_list& args, int nargout); - bool crash_dumps_octave_core (void) const - { - return m_crash_dumps_octave_core; - } + bool crash_dumps_octave_core (void) const + { + return m_crash_dumps_octave_core; + } - bool crash_dumps_octave_core (bool flag) - { - return set (m_crash_dumps_octave_core, flag); - } - - octave_value octave_core_file_limit (const octave_value_list& args, - int nargout); + bool crash_dumps_octave_core (bool flag) + { + return set (m_crash_dumps_octave_core, flag); + } - double octave_core_file_limit (void) const - { - return m_octave_core_file_limit; - } + octave_value octave_core_file_limit (const octave_value_list& args, + int nargout); - double octave_core_file_limit (double limit) - { - return set (m_octave_core_file_limit, limit); - } + double octave_core_file_limit (void) const + { + return m_octave_core_file_limit; + } - OCTINTERP_API octave_value - octave_core_file_name (const octave_value_list& args, int nargout); + double octave_core_file_limit (double limit) + { + return set (m_octave_core_file_limit, limit); + } - std::string octave_core_file_name (void) const - { - return m_octave_core_file_name; - } + OCTINTERP_API octave_value + octave_core_file_name (const octave_value_list& args, int nargout); - std::string octave_core_file_name (const std::string& file) - { - return set (m_octave_core_file_name, file); - } + std::string octave_core_file_name (void) const + { + return m_octave_core_file_name; + } - OCTINTERP_API octave_value - save_default_options (const octave_value_list& args, int nargout); + std::string octave_core_file_name (const std::string& file) + { + return set (m_octave_core_file_name, file); + } - std::string save_default_options (void) const - { - return m_save_default_options; - } + OCTINTERP_API octave_value + save_default_options (const octave_value_list& args, int nargout); - std::string save_default_options (const std::string& options) - { - return set (m_save_default_options, options); - } + std::string save_default_options (void) const + { + return m_save_default_options; + } - OCTINTERP_API octave_value - octave_core_file_options (const octave_value_list& args, int nargout); + std::string save_default_options (const std::string& options) + { + return set (m_save_default_options, options); + } - std::string octave_core_file_options (void) const - { - return m_octave_core_file_options; - } + OCTINTERP_API octave_value + octave_core_file_options (const octave_value_list& args, int nargout); - std::string octave_core_file_options (const std::string& options) - { - return set (m_octave_core_file_options, options); - } + std::string octave_core_file_options (void) const + { + return m_octave_core_file_options; + } - OCTINTERP_API octave_value - save_header_format_string (const octave_value_list& args, int nargout); + std::string octave_core_file_options (const std::string& options) + { + return set (m_octave_core_file_options, options); + } - std::string save_header_format_string (void) const - { - return m_save_header_format_string; - } + OCTINTERP_API octave_value + save_header_format_string (const octave_value_list& args, int nargout); - std::string save_header_format_string (const std::string& format) - { - return set (m_save_header_format_string, format); - } + std::string save_header_format_string (void) const + { + return m_save_header_format_string; + } - static OCTINTERP_API load_save_format - get_file_format (const std::string& fname, const std::string& orig_fname, - bool& use_zlib, bool quiet = false); + std::string save_header_format_string (const std::string& format) + { + return set (m_save_header_format_string, format); + } - // FIXME: this is probably not the best public interface for - // loading and saving variables, but it is what is currently - // needed for the Fload and Fsave functions. + static OCTINTERP_API load_save_format + get_file_format (const std::string& fname, const std::string& orig_fname, + bool& use_zlib, bool quiet = false); + + // FIXME: this is probably not the best public interface for + // loading and saving variables, but it is what is currently + // needed for the Fload and Fsave functions. - OCTINTERP_API octave_value - load_vars (std::istream& stream, const std::string& orig_fname, - const load_save_format& fmt, mach_info::float_format flt_fmt, - bool list_only, bool swap, bool verbose, - const string_vector& argv, int argv_idx, int argc, int nargout); + OCTINTERP_API octave_value + load_vars (std::istream& stream, const std::string& orig_fname, + const load_save_format& fmt, mach_info::float_format flt_fmt, + bool list_only, bool swap, bool verbose, + const string_vector& argv, int argv_idx, int argc, int nargout); - static OCTINTERP_API string_vector - parse_save_options (const string_vector& argv, load_save_format& fmt, - bool& append, bool& save_as_floats, bool& use_zlib); + static OCTINTERP_API string_vector + parse_save_options (const string_vector& argv, load_save_format& fmt, + bool& append, bool& save_as_floats, bool& use_zlib); - static OCTINTERP_API string_vector - parse_save_options (const std::string& arg, load_save_format& fmt, - bool& append, bool& save_as_floats, bool& use_zlib); - - OCTINTERP_API void - save_vars (const string_vector& argv, int argv_idx, int argc, - std::ostream& os, const load_save_format& fmt, - bool save_as_floats, bool write_header_info); + static OCTINTERP_API string_vector + parse_save_options (const std::string& arg, load_save_format& fmt, + bool& append, bool& save_as_floats, bool& use_zlib); - OCTINTERP_API void dump_octave_core (void); - - OCTINTERP_API octave_value_list - load (const octave_value_list& args = octave_value_list (), - int nargout = 0); + OCTINTERP_API void + save_vars (const string_vector& argv, int argv_idx, int argc, + std::ostream& os, const load_save_format& fmt, + bool save_as_floats, bool write_header_info); - OCTINTERP_API octave_value_list - save (const octave_value_list& args = octave_value_list (), - int nargout = 0); + OCTINTERP_API void dump_octave_core (void); - private: + OCTINTERP_API octave_value_list + load (const octave_value_list& args = octave_value_list (), + int nargout = 0); - interpreter& m_interpreter; + OCTINTERP_API octave_value_list + save (const octave_value_list& args = octave_value_list (), + int nargout = 0); - // Write octave-workspace file if Octave crashes or is killed by a - // signal. - bool m_crash_dumps_octave_core; +private: - // The maximum amount of memory (in kilobytes) that we will - // attempt to write to the Octave core file. - double m_octave_core_file_limit; + interpreter& m_interpreter; - // The name of the Octave core file. - std::string m_octave_core_file_name; + // Write octave-workspace file if Octave crashes or is killed by a + // signal. + bool m_crash_dumps_octave_core; - // The default output format. May be one of "binary", "text", - // "mat-binary", or "hdf5". - std::string m_save_default_options; + // The maximum amount of memory (in kilobytes) that we will + // attempt to write to the Octave core file. + double m_octave_core_file_limit; - // The output format for Octave core files. - std::string m_octave_core_file_options; + // The name of the Octave core file. + std::string m_octave_core_file_name; - // The format string for the comment line at the top of - // text-format save files. Passed to strftime. Should begin with - // '#' and contain no newline characters. - std::string m_save_header_format_string; + // The default output format. May be one of "binary", "text", + // "mat-binary", or "hdf5". + std::string m_save_default_options; - OCTINTERP_API void - write_header (std::ostream& os, const load_save_format& fmt); - - OCTINTERP_API std::size_t - save_vars (std::ostream& os, const std::string& pattern, - const load_save_format& fmt, bool save_as_floats); + // The output format for Octave core files. + std::string m_octave_core_file_options; - OCTINTERP_API void - do_save (std::ostream& os, const octave_value& tc, const std::string& name, - const std::string& help, bool global, const load_save_format& fmt, - bool save_as_floats); + // The format string for the comment line at the top of + // text-format save files. Passed to strftime. Should begin with + // '#' and contain no newline characters. + std::string m_save_header_format_string; - OCTINTERP_API void - do_save (std::ostream& os, const symbol_info& syminfo, + OCTINTERP_API void + write_header (std::ostream& os, const load_save_format& fmt); + + OCTINTERP_API std::size_t + save_vars (std::ostream& os, const std::string& pattern, const load_save_format& fmt, bool save_as_floats); - OCTINTERP_API std::size_t - save_fields (std::ostream& os, const octave_scalar_map& m, - const std::string& pattern, const load_save_format& fmt, - bool save_as_floats); + OCTINTERP_API void + do_save (std::ostream& os, const octave_value& tc, const std::string& name, + const std::string& help, bool global, const load_save_format& fmt, + bool save_as_floats); - OCTINTERP_API void - dump_octave_core (std::ostream& os, const char *fname, - const load_save_format& fmt, bool save_as_floats); + OCTINTERP_API void + do_save (std::ostream& os, const symbol_info& syminfo, + const load_save_format& fmt, bool save_as_floats); - OCTINTERP_API void - install_loaded_variable (const std::string& name, const octave_value& val, - bool global, const std::string& /*doc*/); + OCTINTERP_API std::size_t + save_fields (std::ostream& os, const octave_scalar_map& m, + const std::string& pattern, const load_save_format& fmt, + bool save_as_floats); + + OCTINTERP_API void + dump_octave_core (std::ostream& os, const char *fname, + const load_save_format& fmt, bool save_as_floats); - static OCTINTERP_API std::string init_save_header_format (void); + OCTINTERP_API void + install_loaded_variable (const std::string& name, const octave_value& val, + bool global, const std::string& /*doc*/); - static OCTINTERP_API load_save_format - get_file_format (std::istream& file, const std::string& filename); + static OCTINTERP_API std::string init_save_header_format (void); + + static OCTINTERP_API load_save_format + get_file_format (std::istream& file, const std::string& filename); - template - T set (T& var, const T& new_val) - { - T old_val = var; - var = new_val; - return old_val; - } - }; + template + T set (T& var, const T& new_val) + { + T old_val = var; + var = new_val; + return old_val; + } +}; - class load_save_format - { - public: +class load_save_format +{ +public: - load_save_format (load_save_system::format_type type, - load_save_system::format_options options = load_save_system::NO_OPTION) - : m_type (type), m_options (options) - { } + load_save_format (load_save_system::format_type type, + load_save_system::format_options options = load_save_system::NO_OPTION) + : m_type (type), m_options (options) + { } - void set_type (load_save_system::format_type type) { m_type = type; } + void set_type (load_save_system::format_type type) { m_type = type; } - load_save_system::format_type type (void) const { return m_type; } + load_save_system::format_type type (void) const { return m_type; } - void set_option (load_save_system::format_options option) - { - m_options |= option; - } + void set_option (load_save_system::format_options option) + { + m_options |= option; + } - int options (void) const { return m_options; } + int options (void) const { return m_options; } - private: +private: - load_save_system::format_type m_type; - int m_options; - }; + load_save_system::format_type m_type; + int m_options; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/lookup.cc --- a/libinterp/corefcn/lookup.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/lookup.cc Thu Dec 01 20:05:44 2022 -0800 @@ -258,28 +258,28 @@ // PS: I learned this from data.cc if INT_ARRAY_LOOKUP (int8) - else if INT_ARRAY_LOOKUP (int16) - else if INT_ARRAY_LOOKUP (int32) - else if INT_ARRAY_LOOKUP (int64) - else if INT_ARRAY_LOOKUP (uint8) - else if INT_ARRAY_LOOKUP (uint16) - else if INT_ARRAY_LOOKUP (uint32) - else if INT_ARRAY_LOOKUP (uint64) - else if (table.is_char_matrix () && y.is_char_matrix ()) - retval = do_numeric_lookup (table.char_array_value (), - y.char_array_value (), - left_inf, right_inf, - match_idx, match_bool); - else if (table.is_single_type () || y.is_single_type ()) - retval = do_numeric_lookup (table.float_array_value (), - y.float_array_value (), - left_inf, right_inf, - match_idx, match_bool); - else - retval = do_numeric_lookup (table.array_value (), - y.array_value (), - left_inf, right_inf, - match_idx, match_bool); + else if INT_ARRAY_LOOKUP (int16) + else if INT_ARRAY_LOOKUP (int32) + else if INT_ARRAY_LOOKUP (int64) + else if INT_ARRAY_LOOKUP (uint8) + else if INT_ARRAY_LOOKUP (uint16) + else if INT_ARRAY_LOOKUP (uint32) + else if INT_ARRAY_LOOKUP (uint64) + else if (table.is_char_matrix () && y.is_char_matrix ()) + retval = do_numeric_lookup (table.char_array_value (), + y.char_array_value (), + left_inf, right_inf, + match_idx, match_bool); + else if (table.is_single_type () || y.is_single_type ()) + retval = do_numeric_lookup (table.float_array_value (), + y.float_array_value (), + left_inf, right_inf, + match_idx, match_bool); + else + retval = do_numeric_lookup (table.array_value (), + y.array_value (), + left_inf, right_inf, + match_idx, match_bool); } else if (str_case) { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ls-hdf5.cc --- a/libinterp/corefcn/ls-hdf5.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ls-hdf5.cc Thu Dec 01 20:05:44 2022 -0800 @@ -181,7 +181,7 @@ // Check whether filename contains non-ASCII (UTF-8) characters. std::string::const_iterator first_non_ASCII = std::find_if (fname_str.begin (), fname_str.end (), - [](char c) { return (c < 0 || c >= 128); }); + [](char c) { return (c < 0 || c >= 128); }); if (first_non_ASCII == fname_str.end ()) { // No non-ASCII characters diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ls-mat4.cc --- a/libinterp/corefcn/ls-mat4.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ls-mat4.cc Thu Dec 01 20:05:44 2022 -0800 @@ -320,7 +320,7 @@ read_mat_binary_data (is, ctmp, prec, 1, swap, flt_fmt); SparseComplexMatrix smc = SparseComplexMatrix (data, r, c, - nr_new, nc_new); + nr_new, nc_new); tc = (order ? smc.transpose () : smc); } @@ -372,7 +372,7 @@ for (octave_idx_type j = 0; j < nc; j++) for (octave_idx_type i = 0; i < nr; i++) - ctmp (i,j) = Complex (re(i,j), im(i,j)); + ctmp (i, j) = Complex (re(i, j), im(i, j)); tc = (order ? ctmp.transpose () : ctmp); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ls-mat5.cc --- a/libinterp/corefcn/ls-mat5.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ls-mat5.cc Thu Dec 01 20:05:44 2022 -0800 @@ -913,7 +913,7 @@ if (ov_fcn.is_defined ()) // XXX FCN_HANDLE: SIMPLE/SCOPED tc = octave_value (new octave_fcn_handle (ov_fcn, - fname)); + fname)); } else { @@ -941,7 +941,7 @@ if (ov_fcn.is_defined ()) // XXX FCN_HANDLE: SIMPLE/SCOPED tc = octave_value (new octave_fcn_handle (ov_fcn, - fname)); + fname)); else { warning_with_id ("Octave:load:file-not-found", @@ -1043,7 +1043,7 @@ // XXX FCN_HANDLE: ANONYMOUS tc = octave_value (new octave_fcn_handle (fh->fcn_val (), - local_vars)); + local_vars)); } else error ("load: invalid function handle type"); @@ -1366,7 +1366,7 @@ break; case MAT_FILE_CHAR_CLASS: - // handle as a numerical array to start with + // handle as a numerical array to start with case MAT_FILE_DOUBLE_CLASS: default: @@ -1442,8 +1442,8 @@ // Convert to UTF-8. std::size_t n8; uint8_t *u8_str = octave_u16_to_u8_wrapper (u16_str, - u16.numel (), - nullptr, &n8); + u16.numel (), + nullptr, &n8); if (u8_str) { // FIXME: Is there a better way to construct a charMatrix @@ -1462,8 +1462,8 @@ // Convert to UTF-8. std::size_t n8; uint8_t *u8_str = octave_u32_to_u8_wrapper (u32_str, - u32.numel (), - nullptr, &n8); + u32.numel (), + nullptr, &n8); if (u8_str) { // FIXME: Is there a better way to construct a charMatrix @@ -1498,8 +1498,8 @@ 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 '?'"); + "load: failed to convert from input to UTF-8; " + "replacing non-ASCII characters with '?'"); tc = re; tc = tc.convert_to_str (false, true, '\''); @@ -2203,90 +2203,90 @@ else if (cname == "int8") INT_LEN (tc.int8_array_value ().numel (), 1) - else if (cname == "int16") - INT_LEN (tc.int16_array_value ().numel (), 2) - else if (cname == "int32") - INT_LEN (tc.int32_array_value ().numel (), 4) - else if (cname == "int64") - INT_LEN (tc.int64_array_value ().numel (), 8) - else if (cname == "uint8") - INT_LEN (tc.uint8_array_value ().numel (), 1) - else if (cname == "uint16") - INT_LEN (tc.uint16_array_value ().numel (), 2) - else if (cname == "uint32") - INT_LEN (tc.uint32_array_value ().numel (), 4) - else if (cname == "uint64") - INT_LEN (tc.uint64_array_value ().numel (), 8) - else if (tc.islogical ()) - INT_LEN (tc.bool_array_value ().numel (), 1) - else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()) - { - if (tc.is_single_type ()) - { - const FloatNDArray m = tc.float_array_value (); - ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); - } - else - { - const NDArray m = tc.array_value (); - ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); - } - } - else if (tc.iscell ()) - { - Cell cell = tc.cell_value (); - octave_idx_type nel = cell.numel (); - - for (int i = 0; i < nel; i++) - ret += 8 + - save_mat5_element_length (cell (i), "", save_as_floats, mat7_format); - } - else if (tc.is_complex_scalar () || tc.is_complex_matrix ()) - { - if (tc.is_single_type ()) - { - const FloatComplexNDArray m = tc.float_complex_array_value (); - ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); - } - else - { - const ComplexNDArray m = tc.complex_array_value (); - ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); - } - } - else if (tc.isstruct () || tc.is_inline_function () || tc.isobject ()) - { - int fieldcnt = 0; - const octave_map m = tc.map_value (); - octave_idx_type nel = m.numel (); - - if (tc.is_inline_function ()) - ret += 8 + PAD (6); // length of "inline" is 6 - else if (tc.isobject ()) - { - std::size_t classlen = tc.class_name ().length (); - - ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen); - } - - for (auto i = m.begin (); i != m.end (); i++) - fieldcnt++; - - ret += 16 + fieldcnt * (max_namelen + 1); - - for (octave_idx_type j = 0; j < nel; j++) - { - for (auto i = m.begin (); i != m.end (); i++) - { - const Cell elts = m.contents (i); - - ret += 8 + save_mat5_element_length (elts(j), "", save_as_floats, - mat7_format); - } - } - } - else - ret = -1; + else if (cname == "int16") + INT_LEN (tc.int16_array_value ().numel (), 2) + else if (cname == "int32") + INT_LEN (tc.int32_array_value ().numel (), 4) + else if (cname == "int64") + INT_LEN (tc.int64_array_value ().numel (), 8) + else if (cname == "uint8") + INT_LEN (tc.uint8_array_value ().numel (), 1) + else if (cname == "uint16") + INT_LEN (tc.uint16_array_value ().numel (), 2) + else if (cname == "uint32") + INT_LEN (tc.uint32_array_value ().numel (), 4) + else if (cname == "uint64") + INT_LEN (tc.uint64_array_value ().numel (), 8) + else if (tc.islogical ()) + INT_LEN (tc.bool_array_value ().numel (), 1) + else if (tc.is_real_scalar () || tc.is_real_matrix () || tc.is_range ()) + { + if (tc.is_single_type ()) + { + const FloatNDArray m = tc.float_array_value (); + ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); + } + else + { + const NDArray m = tc.array_value (); + ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); + } + } + else if (tc.iscell ()) + { + Cell cell = tc.cell_value (); + octave_idx_type nel = cell.numel (); + + for (int i = 0; i < nel; i++) + ret += 8 + + save_mat5_element_length (cell (i), "", save_as_floats, mat7_format); + } + else if (tc.is_complex_scalar () || tc.is_complex_matrix ()) + { + if (tc.is_single_type ()) + { + const FloatComplexNDArray m = tc.float_complex_array_value (); + ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); + } + else + { + const ComplexNDArray m = tc.complex_array_value (); + ret += save_mat5_array_length (m.data (), m.numel (), save_as_floats); + } + } + else if (tc.isstruct () || tc.is_inline_function () || tc.isobject ()) + { + int fieldcnt = 0; + const octave_map m = tc.map_value (); + octave_idx_type nel = m.numel (); + + if (tc.is_inline_function ()) + ret += 8 + PAD (6); // length of "inline" is 6 + else if (tc.isobject ()) + { + std::size_t classlen = tc.class_name ().length (); + + ret += 8 + PAD (classlen > max_namelen ? max_namelen : classlen); + } + + for (auto i = m.begin (); i != m.end (); i++) + fieldcnt++; + + ret += 16 + fieldcnt * (max_namelen + 1); + + for (octave_idx_type j = 0; j < nel; j++) + { + for (auto i = m.begin (); i != m.end (); i++) + { + const Cell elts = m.contents (i); + + ret += 8 + save_mat5_element_length (elts(j), "", save_as_floats, + mat7_format); + } + } + } + else + ret = -1; return ret; } @@ -2399,7 +2399,7 @@ if (compress (reinterpret_cast (out_buf), &destLen, reinterpret_cast (buf_str.c_str ()), - srcLen) + srcLen) != Z_OK) error ("save: error compressing data element"); @@ -2707,7 +2707,7 @@ if (tc.is_inline_function () || tc.isobject ()) { std::string classname = (tc.isobject () ? tc.class_name () - : "inline"); + : "inline"); std::size_t namelen = classname.length (); if (namelen > max_namelen) @@ -2788,9 +2788,9 @@ for (octave_idx_type i = 0; i < nf; i++) { bool retval2 = save_mat5_binary_element (os, elts[i][j], "", - mark_global, - false, - save_as_floats); + mark_global, + false, + save_as_floats); if (! retval2) error ("save: error while writing '%s' to MAT file", name.c_str ()); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/lsode.cc --- a/libinterp/corefcn/lsode.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/lsode.cc Thu Dec 01 20:05:44 2022 -0800 @@ -135,7 +135,8 @@ warned_jac_imaginary = true; } - retval = tmp(0).xmatrix_value ("lsode: expecting user supplied jacobian function to return numeric array"); + retval = tmp( + 0).xmatrix_value ("lsode: expecting user supplied jacobian function to return numeric array"); if (retval.isempty ()) err_user_supplied_eval ("lsode"); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/lu.cc --- a/libinterp/corefcn/lu.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/lu.cc Thu Dec 01 20:05:44 2022 -0800 @@ -276,7 +276,7 @@ for (octave_idx_type i = 0; i < nc; i++) Qinit(i) = i; math::sparse_lu fact (m, Qinit, thresh, - false, true); + false, true); if (nargout < 2) retval(0) = fact.Y (); @@ -778,19 +778,19 @@ %!testif HAVE_QRUPDATE_LUU %! [L,U,P] = lu (single (A)); -%! [L,U] = luupdate (L,U,P*single (u), single (v)); +%! [L,U] = luupdate (L,U,P* single (u), single (v)); %! assert (norm (vec (tril (L)-L), Inf) == 0); %! assert (norm (vec (triu (U)-U), Inf) == 0); -%! assert (norm (vec (P'*L*U - single (A) - single (u)*single (v).'), Inf) -%! < norm (single (A))*1e1*eps ("single")); +%! assert (norm (vec (P'*L*U - single (A) - single (u)* single (v).'), Inf) +%! < norm (single (A))*1e1* eps ("single")); %! %!testif HAVE_QRUPDATE_LUU %! [L,U,P] = lu (single (Ac)); -%! [L,U] = luupdate (L,U,P*single (uc),single (vc)); +%! [L,U] = luupdate (L,U,P* single (uc),single (vc)); %! assert (norm (vec (tril (L)-L), Inf) == 0); %! assert (norm (vec (triu (U)-U), Inf) == 0); -%! assert (norm (vec (P'*L*U - single (Ac) - single (uc)*single (vc).'), Inf) -%! < norm (single (Ac))*1e1*eps ("single")); +%! assert (norm (vec (P'*L*U - single (Ac) - single (uc)* single (vc).'), Inf) +%! < norm (single (Ac))*1e1* eps ("single")); %!testif HAVE_QRUPDATE_LUU %! [L,U,P] = lu (A); @@ -825,16 +825,16 @@ %! [L,U,P] = luupdate (L,U,P,single (u),single (v)); %! assert (norm (vec (tril (L)-L), Inf) == 0); %! assert (norm (vec (triu (U)-U), Inf) == 0); -%! assert (norm (vec (P'*L*U - single (A) - single (u)*single (v).'), Inf) -%! < norm (single (A))*1e1*eps ("single")); +%! assert (norm (vec (P'*L*U - single (A) - single (u)* single (v).'), Inf) +%! < norm (single (A))*1e1* eps ("single")); %! %!testif HAVE_QRUPDATE_LUU %! [L,U,P] = lu (single (Ac)); %! [L,U,P] = luupdate (L,U,P,single (uc),single (vc)); %! assert (norm (vec (tril (L)-L), Inf) == 0); %! assert (norm (vec (triu (U)-U), Inf) == 0); -%! assert (norm (vec (P'*L*U - single (Ac) - single (uc)*single (vc).'), Inf) -%! < norm (single (Ac))*1e1*eps ("single")); +%! assert (norm (vec (P'*L*U - single (Ac) - single (uc)* single (vc).'), Inf) +%! < norm (single (Ac))*1e1* eps ("single")); */ OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/mappers.cc --- a/libinterp/corefcn/mappers.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/mappers.cc Thu Dec 01 20:05:44 2022 -0800 @@ -197,8 +197,8 @@ %!test <49091> %! re = single (2.99822295029797); %! im = single (pi/2); -%! assert (acosh (single (10i)), re + i*im, 5*eps ("single")); -%! assert (acosh (single (-10i)), re - i*im, 5*eps ("single")); +%! assert (acosh (single (10i)), re + i*im, 5* eps ("single")); +%! assert (acosh (single (-10i)), re - i*im, 5* eps ("single")); ## Test large magnitude arguments (bug #45507) ## Test fails with older versions of libm, solution is to upgrade. @@ -275,13 +275,13 @@ %!test %! if (ismac ()) %! ## Avoid failing for a MacOS feature -%! assert (arg (single (-1)), single (pi), 2*eps (single (1))); +%! assert (arg (single (-1)), single (pi), 2* eps (single (1))); %! else %! assert (arg (single (-1)), single (pi)); %! endif %!assert (arg (single (-i)), single (-pi/2)) %!assert (arg (single ([1, i; -1, -i])), -%! single ([0, pi/2; pi, -pi/2]), 2e1*eps ("single")) +%! single ([0, pi/2; pi, -pi/2]), 2e1* eps ("single")) %!error arg () %!error arg (1, 2) @@ -678,7 +678,7 @@ /* %!test -%! a = -1i*sqrt (-1/(6.4187*6.4187)); +%! a = -1i* sqrt (-1/(6.4187*6.4187)); %! assert (erf (a), erf (real (a))); %!test @@ -690,7 +690,7 @@ %! assert (erfinv (v), x, 1.e-10); %!test -%! a = -1i*sqrt (single (-1/(6.4187*6.4187))); +%! a = -1i* sqrt (single (-1/(6.4187*6.4187))); %! assert (erf (a), erf (real (a))); %!test @@ -819,7 +819,7 @@ /* %!test -%! a = -1i*sqrt (-1/(6.4187*6.4187)); +%! a = -1i* sqrt (-1/(6.4187*6.4187)); %! assert (erfc (a), erfc (real (a))); %!error erfc () @@ -1157,7 +1157,7 @@ /* %!test -%! a = -1i*sqrt (-1/(6.4187*6.4187)); +%! a = -1i* sqrt (-1/(6.4187*6.4187)); %! assert (gamma (a), gamma (real (a))); %!test @@ -1166,7 +1166,7 @@ %! assert (gamma (x), v, sqrt (eps)); %!test -%! a = single (-1i*sqrt (-1/(6.4187*6.4187))); +%! a = single (-1i* sqrt (-1/(6.4187*6.4187))); %! assert (gamma (a), gamma (real (a))); %!test @@ -1685,7 +1685,7 @@ /* %!test -%! a = -1i*sqrt (-1/(6.4187*6.4187)); +%! a = -1i* sqrt (-1/(6.4187*6.4187)); %! assert (gammaln (a), gammaln (real (a))); %!test @@ -1694,7 +1694,7 @@ %! assert (gammaln (x), log (v), sqrt (eps)); %!test -%! a = single (-1i*sqrt (-1/(6.4187*6.4187))); +%! a = single (-1i* sqrt (-1/(6.4187*6.4187))); %! assert (gammaln (a), gammaln (real (a))); %!test @@ -1740,7 +1740,7 @@ %!assert (log (single ([1, e, e^2])), single ([0, 1, 2]), sqrt (eps ("single"))) %!assert (log (single ([-0.5, -1.5, -2.5])), -%! single (log ([0.5, 1.5, 2.5]) + pi*1i), 4*eps ("single")) +%! single (log ([0.5, 1.5, 2.5]) + pi*1i), 4* eps ("single")) %!error log () %!error log (1, 2) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/matrix_type.cc --- a/libinterp/corefcn/matrix_type.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/matrix_type.cc Thu Dec 01 20:05:44 2022 -0800 @@ -471,7 +471,7 @@ %! spparms ("bandden", 0.5); %! a = spdiags (rand (10,3)-0.5,[-1,0,1],10,10); %! assert (matrix_type (a), "Tridiagonal"); -%! assert (matrix_type (a'+a+2*speye (10)), "Tridiagonal Positive Definite"); +%! assert (matrix_type (a'+a+2* speye (10)), "Tridiagonal Positive Definite"); %! spparms ("bandden", bnd); %!test %! bnd=spparms ("bandden"); @@ -504,8 +504,8 @@ %! "Permuted Lower") %!assert (matrix_type (spdiags (randn (10,4),[-2:1],10,9)), "Rectangular") -%!assert (matrix_type (1i*speye (10,10)), "Diagonal") -%!assert (matrix_type (1i*speye (10,10)([2:10,1],:)), "Permuted Diagonal") +%!assert (matrix_type (1i* speye (10,10)), "Diagonal") +%!assert (matrix_type (1i* speye (10,10)([2:10,1],:)), "Permuted Diagonal") %!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1i;sparse(9,1);1]]), %! "Upper") %!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1i;sparse(9,1);1]](:,[2,1,3:11])), @@ -517,7 +517,7 @@ %!test %! bnd = spparms ("bandden"); %! spparms ("bandden", 0.5); -%! assert (matrix_type (spdiags (1i*randn (10,3),[-1,0,1],10,10)), +%! assert (matrix_type (spdiags (1i* randn (10,3),[-1,0,1],10,10)), %! "Tridiagonal"); %! a = 1i*(rand (9,1)-0.5); %! a = [[a;0],ones(10,1),[0;-a]]; @@ -527,7 +527,7 @@ %!test %! bnd = spparms ("bandden"); %! spparms ("bandden", 0.5); -%! assert (matrix_type (spdiags (1i*randn (10,4),[-2:1],10,10)), "Banded"); +%! assert (matrix_type (spdiags (1i* randn (10,4),[-2:1],10,10)), "Banded"); %! a = 1i*(rand (9,2)-0.5); %! a = [[a;[0,0]],ones(10,1),[[0;-a(:,2)],[0;0;-a(1:8,1)]]]; %! assert (matrix_type (spdiags (a,[-2:2],10,10)), "Banded Positive Definite"); @@ -537,10 +537,10 @@ %! assert (matrix_type (a), "Full"); %! assert (matrix_type (a'*a), "Positive Definite"); -%!assert (matrix_type (1i*speye (10,11)), "Diagonal") -%!assert (matrix_type (1i*speye (10,11)([2:10,1],:)), "Permuted Diagonal") -%!assert (matrix_type (1i*speye (11,10)), "Diagonal") -%!assert (matrix_type (1i*speye (11,10)([2:11,1],:)), "Permuted Diagonal") +%!assert (matrix_type (1i* speye (10,11)), "Diagonal") +%!assert (matrix_type (1i* speye (10,11)([2:10,1],:)), "Permuted Diagonal") +%!assert (matrix_type (1i* speye (11,10)), "Diagonal") +%!assert (matrix_type (1i* speye (11,10)([2:11,1],:)), "Permuted Diagonal") %!#assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]]), "Upper") %!#assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]](:,[2,1,3:12])), "Permuted Upper") %!assert (matrix_type ([speye(11,9),[1i;sparse(8,1);1i;0]]), "Upper") @@ -561,17 +561,17 @@ %!assert (matrix_type (triu (ones (10,10),-1)), "Full") %!assert (matrix_type (tril (ones (10,10))), "Lower") %!assert (matrix_type (tril (ones (10,10),1)), "Full") -%!assert (matrix_type (10*eye (10,10) + ones (10,10)), "Positive Definite") +%!assert (matrix_type (10* eye (10,10) + ones (10,10)), "Positive Definite") %!assert (matrix_type (ones (11,10)), "Rectangular") %!test %! a = matrix_type (ones (10,10), "Singular"); %! assert (matrix_type (a), "Singular"); -%!assert (matrix_type (triu (1i*ones (10,10))), "Upper") -%!assert (matrix_type (triu (1i*ones (10,10),-1)), "Full") -%!assert (matrix_type (tril (1i*ones (10,10))), "Lower") -%!assert (matrix_type (tril (1i*ones (10,10),1)), "Full") -%!assert (matrix_type (10*eye (10,10) + 1i*triu (ones (10,10),1) -1i*tril (ones (10,10),-1)), "Positive Definite") +%!assert (matrix_type (triu (1i* ones (10,10))), "Upper") +%!assert (matrix_type (triu (1i* ones (10,10),-1)), "Full") +%!assert (matrix_type (tril (1i* ones (10,10))), "Lower") +%!assert (matrix_type (tril (1i* ones (10,10),1)), "Full") +%!assert (matrix_type (10* eye (10,10) + 1i*triu (ones (10,10),1) -1i*tril (ones (10,10),-1)), "Positive Definite") %!assert (matrix_type (ones (11,10)), "Rectangular") %!test %! a = matrix_type (ones (10,10), "Singular"); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/max.cc --- a/libinterp/corefcn/max.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/max.cc Thu Dec 01 20:05:44 2022 -0800 @@ -291,12 +291,12 @@ if (nargout > 1) retval(1) = static_cast (range.increment () >= 0 ? range.numel () - : 1); + : 1); } } else if (arg.issparse ()) retval = do_minmax_red_op (arg, nargout, dim, - ismin); + ismin); else retval = do_minmax_red_op (arg, nargout, dim, ismin); @@ -307,10 +307,10 @@ { if (arg.issparse ()) retval = do_minmax_red_op (arg, nargout, dim, - ismin); + ismin); else retval = do_minmax_red_op (arg, nargout, dim, - ismin); + ismin); } break; @@ -320,7 +320,7 @@ case btyp_float_complex: retval = do_minmax_red_op (arg, nargout, dim, - ismin); + ismin); break; case btyp_char: @@ -332,14 +332,14 @@ retval = do_minmax_red_op (arg, nargout, dim, ismin); \ break; - MAKE_INT_BRANCH (int8); - MAKE_INT_BRANCH (int16); - MAKE_INT_BRANCH (int32); - MAKE_INT_BRANCH (int64); - MAKE_INT_BRANCH (uint8); - MAKE_INT_BRANCH (uint16); - MAKE_INT_BRANCH (uint32); - MAKE_INT_BRANCH (uint64); + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); #undef MAKE_INT_BRANCH @@ -385,7 +385,7 @@ && (argy.issparse () || argy.is_scalar_type ())) || (argy.issparse () && argx.is_scalar_type ())) retval = do_minmax_bin_op (argx, argy, - ismin); + ismin); else retval = do_minmax_bin_op (argx, argy, ismin); } @@ -408,14 +408,14 @@ retval = do_minmax_bin_op (argx, argy, ismin); \ break; - MAKE_INT_BRANCH (int8); - MAKE_INT_BRANCH (int16); - MAKE_INT_BRANCH (int32); - MAKE_INT_BRANCH (int64); - MAKE_INT_BRANCH (uint8); - MAKE_INT_BRANCH (uint16); - MAKE_INT_BRANCH (uint32); - MAKE_INT_BRANCH (uint64); + MAKE_INT_BRANCH (int8); + MAKE_INT_BRANCH (int16); + MAKE_INT_BRANCH (int32); + MAKE_INT_BRANCH (int64); + MAKE_INT_BRANCH (uint8); + MAKE_INT_BRANCH (uint16); + MAKE_INT_BRANCH (uint32); + MAKE_INT_BRANCH (uint64); #undef MAKE_INT_BRANCH @@ -947,7 +947,7 @@ case btyp_complex: retval = do_cumminmax_red_op (arg, nargout, dim, - ismin); + ismin); break; case btyp_float: @@ -956,7 +956,7 @@ case btyp_float_complex: retval = do_cumminmax_red_op (arg, nargout, dim, - ismin); + ismin); break; #define MAKE_INT_BRANCH(X) \ @@ -978,7 +978,7 @@ case btyp_bool: { retval = do_cumminmax_red_op (arg, nargout, dim, - ismin); + ismin); if (retval.length () > 0) retval(0) = retval(0).bool_array_value (); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/mex.cc --- a/libinterp/corefcn/mex.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/mex.cc Thu Dec 01 20:05:44 2022 -0800 @@ -181,8 +181,8 @@ extern OCTINTERP_API mxArray * mxCreateUninitNumericMatrix_interleaved (mwSize m, mwSize n, - mxClassID class_id, - mxComplexity flag); + mxClassID class_id, + mxComplexity flag); extern OCTINTERP_API mxArray * mxCreateSparse_interleaved (mwSize m, mwSize n, mwSize nzmax, @@ -352,7 +352,7 @@ return ptr; } - void do_deallocate (void* ptr, std::size_t /*bytes*/, + void do_deallocate (void *ptr, std::size_t /*bytes*/, std::size_t /*alignment*/) { xfree (ptr); @@ -378,7 +378,7 @@ return ptr; } - void do_deallocate (void* /*ptr*/, std::size_t /*bytes*/, + void do_deallocate (void * /*ptr*/, std::size_t /*bytes*/, std::size_t /*alignment*/) { } @@ -596,7 +596,7 @@ m_ndims = m_val.ndims (); m_dims = static_cast (mxArray::malloc (m_ndims - * sizeof (mwSize))); + * sizeof (mwSize))); dim_vector dv = m_val.dims (); @@ -2639,20 +2639,21 @@ if (current_mx_memory_resource == &the_mx_deleting_memory_resource) { - octave::unwind_action act ([=] () { + octave::unwind_action act ([=] () + { maybe_disown_ptr (m_pr); maybe_disown_ptr (m_ir); maybe_disown_ptr (m_jc); }); return octave_value - (Sparse (dv, static_cast (m_nzmax), - ppr, m_ir, m_jc, current_mx_memory_resource)); + (Sparse (dv, static_cast (m_nzmax), + ppr, m_ir, m_jc, current_mx_memory_resource)); } else return octave_value - (Sparse (dv, static_cast (m_nzmax), - ppr, m_ir, m_jc, current_mx_memory_resource)); + (Sparse (dv, static_cast (m_nzmax), + ppr, m_ir, m_jc, current_mx_memory_resource)); #else // Copy data instead of allowing the octave_value object to borrow @@ -2848,10 +2849,10 @@ : mxArray_matlab (interleaved, mxSTRUCT_CLASS, ndims, dims), m_nfields (num_keys), m_fields (static_cast (mxArray::calloc (m_nfields, - sizeof (char *)))), - m_data (static_cast (mxArray::calloc (m_nfields * - get_number_of_elements (), - sizeof (mxArray *)))) + sizeof (char *)))), + m_data (static_cast (mxArray::calloc (m_nfields * + get_number_of_elements (), + sizeof (mxArray *)))) { init (keys); } @@ -2861,10 +2862,10 @@ : mxArray_matlab (interleaved, mxSTRUCT_CLASS, dv), m_nfields (num_keys), m_fields (static_cast (mxArray::calloc (m_nfields, - sizeof (char *)))), - m_data (static_cast (mxArray::calloc (m_nfields * - get_number_of_elements (), - sizeof (mxArray *)))) + sizeof (char *)))), + m_data (static_cast (mxArray::calloc (m_nfields * + get_number_of_elements (), + sizeof (mxArray *)))) { init (keys); } @@ -2874,10 +2875,10 @@ : mxArray_matlab (interleaved, mxSTRUCT_CLASS, m, n), m_nfields (num_keys), m_fields (static_cast (mxArray::calloc (m_nfields, - sizeof (char *)))), - m_data (static_cast (mxArray::calloc (m_nfields * - get_number_of_elements (), - sizeof (mxArray *)))) + sizeof (char *)))), + m_data (static_cast (mxArray::calloc (m_nfields * + get_number_of_elements (), + sizeof (mxArray *)))) { init (keys); } @@ -2887,10 +2888,10 @@ mxArray_struct (const mxArray_struct& val) : mxArray_matlab (val), m_nfields (val.m_nfields), m_fields (static_cast (mxArray::malloc (m_nfields - * sizeof (char *)))), - m_data (static_cast (mxArray::malloc (m_nfields * - get_number_of_elements () - * sizeof (mxArray *)))) + * sizeof (char *)))), + m_data (static_cast (mxArray::malloc (m_nfields * + get_number_of_elements () + * sizeof (mxArray *)))) { for (int i = 0; i < m_nfields; i++) m_fields[i] = mxArray::strsave (val.m_fields[i]); @@ -2941,7 +2942,7 @@ m_nfields++; m_fields = static_cast - (mxRealloc (m_fields, m_nfields * sizeof (char *))); + (mxRealloc (m_fields, m_nfields * sizeof (char *))); if (m_fields) { @@ -2953,7 +2954,7 @@ mxArray **new_data; new_data = static_cast - (mxArray::malloc (ntot * sizeof (mxArray *))); + (mxArray::malloc (ntot * sizeof (mxArray *))); if (new_data) { @@ -2994,11 +2995,11 @@ int new_nfields = m_nfields - 1; char **new_fields = static_cast - (mxArray::malloc (new_nfields * sizeof (char *))); + (mxArray::malloc (new_nfields * sizeof (char *))); mxArray **new_data = static_cast - (mxArray::malloc (new_nfields * nel - * sizeof (mxArray *))); + (mxArray::malloc (new_nfields * nel + * sizeof (mxArray *))); for (int i = 0; i < key_num; i++) new_fields[i] = m_fields[i]; @@ -3112,28 +3113,28 @@ mxArray_cell (bool interleaved, mwSize ndims, const mwSize *dims) : mxArray_matlab (interleaved, mxCELL_CLASS, ndims, dims), - m_data (static_cast ( - mxArray::calloc (get_number_of_elements (), sizeof (mxArray *)))) + m_data (static_cast ( + mxArray::calloc (get_number_of_elements (), sizeof (mxArray *)))) { } mxArray_cell (bool interleaved, const dim_vector& dv) : mxArray_matlab (interleaved, mxCELL_CLASS, dv), - m_data (static_cast ( - mxArray::calloc (get_number_of_elements (), sizeof (mxArray *)))) + m_data (static_cast ( + mxArray::calloc (get_number_of_elements (), sizeof (mxArray *)))) { } mxArray_cell (bool interleaved, mwSize m, mwSize n) : mxArray_matlab (interleaved, mxCELL_CLASS, m, n), - m_data (static_cast ( - mxArray::calloc (get_number_of_elements (), sizeof (mxArray *)))) + m_data (static_cast ( + mxArray::calloc (get_number_of_elements (), sizeof (mxArray *)))) { } private: mxArray_cell (const mxArray_cell& val) : mxArray_matlab (val), - m_data (static_cast ( - mxArray::malloc (get_number_of_elements () * sizeof (mxArray *)))) + m_data (static_cast ( + mxArray::malloc (get_number_of_elements () * sizeof (mxArray *)))) { mwSize nel = get_number_of_elements (); @@ -4037,7 +4038,7 @@ mxArray * mxCreateUninitNumericMatrix_interleaved (mwSize m, mwSize n, - mxClassID class_id, mxComplexity flag) + mxClassID class_id, mxComplexity flag) { return maybe_mark_array (new mxArray (true, class_id, m, n, flag, false)); } @@ -4882,7 +4883,7 @@ // mexCallMATLAB returns. octave::unwind_protect_var - upv (current_mx_memory_resource, &the_mx_preserving_memory_resource); + upv (current_mx_memory_resource, &the_mx_preserving_memory_resource); #endif @@ -4909,10 +4910,10 @@ octave::tree_evaluator& tw = interp.get_evaluator (); octave::unwind_action act - ([&tw] (const std::list *lvl) - { - tw.set_lvalue_list (lvl); - }, tw.lvalue_list ()); + ([&tw] (const std::list *lvl) + { + tw.set_lvalue_list (lvl); + }, tw.lvalue_list ()); tw.set_lvalue_list (nullptr); @@ -5233,13 +5234,13 @@ { #if defined (OCTAVE_HAVE_STD_PMR_POLYMORPHIC_ALLOCATOR) - // Use allocator that doesn't free memory because Octave may mutate - // the value (single element mxArray -> scalar octave_value object, - // for example) and we need these objects to continue to exist after - // mexCallMATLAB returns. + // Use allocator that doesn't free memory because Octave may mutate + // the value (single element mxArray -> scalar octave_value object, + // for example) and we need these objects to continue to exist after + // mexCallMATLAB returns. octave::unwind_protect_var - upv (current_mx_memory_resource, &the_mx_preserving_memory_resource); + upv (current_mx_memory_resource, &the_mx_preserving_memory_resource); #endif interp.global_assign (name, mxArray::as_octave_value (ptr)); @@ -5276,8 +5277,8 @@ // to continue to exist after mexCallMATLAB returns. octave::unwind_protect_var - upv (current_mx_memory_resource, - &the_mx_preserving_memory_resource); + upv (current_mx_memory_resource, + &the_mx_preserving_memory_resource); #endif interp.assign (name, mxArray::as_octave_value (ptr)); @@ -5396,13 +5397,13 @@ // mexCallMATLAB returns. octave::unwind_protect_var - upv (current_mx_memory_resource, &the_mx_preserving_memory_resource); + upv (current_mx_memory_resource, &the_mx_preserving_memory_resource); #endif bool ret = octave::set_property_in_handle (handle, property, - mxArray::as_octave_value (val), - "mexSet"); + mxArray::as_octave_value (val), + "mexSet"); return (ret ? 0 : 1); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/mexproto.h --- a/libinterp/corefcn/mexproto.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/mexproto.h Thu Dec 01 20:05:44 2022 -0800 @@ -81,11 +81,11 @@ extern OCTINTERP_API int mexCallMATLAB (int nargout, mxArray *argout[], int nargin, mxArray *argin[], const char *fname); -extern OCTINTERP_API mxArray * mexCallMATLABWithTrap (int nargout, - mxArray *argout[], - int nargin, - mxArray *argin[], - const char *fname); +extern OCTINTERP_API mxArray *mexCallMATLABWithTrap (int nargout, + mxArray *argout[], + int nargin, + mxArray *argin[], + const char *fname); extern OCTINTERP_API int mexEvalString (const char *s); extern OCTINTERP_API mxArray * mexEvalStringWithTrap (const char *s); @@ -100,10 +100,10 @@ ...); extern OCTINTERP_API int mexPrintf (const char *fmt, ...); -extern OCTINTERP_API mxArray * mexGetVariable (const char *space, - const char *name); -extern OCTINTERP_API const mxArray * mexGetVariablePtr (const char *space, - const char *name); +extern OCTINTERP_API mxArray *mexGetVariable (const char *space, + const char *name); +extern OCTINTERP_API const mxArray *mexGetVariablePtr (const char *space, + const char *name); extern OCTINTERP_API int mexPutVariable (const char *space, const char *name, const mxArray *ptr); @@ -111,8 +111,8 @@ #if MX_HAS_INTERLEAVED_COMPLEX # define mexGet mexGet_interleaved #endif -extern OCTINTERP_API const mxArray * mexGet (double handle, - const char *property); +extern OCTINTERP_API const mxArray *mexGet (double handle, + const char *property); extern OCTINTERP_API int mexSet (double handle, const char *property, mxArray *val); @@ -166,47 +166,47 @@ # define mxCreateStructMatrix mxCreateStructMatrix_interleaved #endif -extern OCTINTERP_API mxArray * mxCreateCellArray (mwSize ndims, - const mwSize *dims); +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 *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 *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, +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 * mxCreateNumericMatrix (mwSize m, mwSize n, - mxClassID class_id, - mxComplexity flag); -extern OCTINTERP_API mxArray * mxCreateUninitNumericArray (mwSize ndims, - const mwSize *dims, +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 * 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 *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, +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 * mxCreateStructMatrix (mwSize rows, mwSize cols, - int num_keys, - const char **keys); /* Copy constructor. */ extern OCTINTERP_API mxArray * mxDuplicateArray (const mxArray *v); @@ -340,8 +340,8 @@ extern OCTINTERP_API mxClassID mxGetClassID (const mxArray *ptr); extern OCTINTERP_API const char * mxGetClassName (const mxArray *ptr); extern OCTINTERP_API void mxSetClassName (mxArray *ptr, const char *name); -extern OCTINTERP_API mxArray * mxGetProperty (const mxArray *ptr, mwIndex idx, - const char *property_name); +extern OCTINTERP_API mxArray *mxGetProperty (const mxArray *ptr, mwIndex idx, + const char *property_name); extern OCTINTERP_API void mxSetProperty (mxArray *ptr, mwIndex idx, const char *property_name, const mxArray *property_value); @@ -365,10 +365,10 @@ extern OCTINTERP_API void mxRemoveField (mxArray *ptr, int key_num); -extern OCTINTERP_API mxArray * mxGetField (const mxArray *ptr, mwIndex index, - const char *key); -extern OCTINTERP_API mxArray * mxGetFieldByNumber (const mxArray *ptr, - mwIndex index, int key_num); +extern OCTINTERP_API mxArray *mxGetField (const mxArray *ptr, mwIndex index, + const char *key); +extern OCTINTERP_API mxArray *mxGetFieldByNumber (const mxArray *ptr, + mwIndex index, int key_num); extern OCTINTERP_API void mxSetField (mxArray *ptr, mwIndex index, const char *key, mxArray *val); @@ -377,8 +377,8 @@ extern OCTINTERP_API int mxGetNumberOfFields (const mxArray *ptr); -extern OCTINTERP_API const char * mxGetFieldNameByNumber (const mxArray *ptr, - int key_num); +extern OCTINTERP_API const char *mxGetFieldNameByNumber (const mxArray *ptr, + int key_num); extern OCTINTERP_API int mxGetFieldNumber (const mxArray *ptr, const char *key); extern OCTINTERP_API int mxGetString (const mxArray *ptr, char *buf, diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/mxarray.h --- a/libinterp/corefcn/mxarray.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/mxarray.h Thu Dec 01 20:05:44 2022 -0800 @@ -656,7 +656,7 @@ { return m_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)); } + { 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)); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/mxtypes.in.h --- a/libinterp/corefcn/mxtypes.in.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/mxtypes.in.h Thu Dec 01 20:05:44 2022 -0800 @@ -54,7 +54,7 @@ #include "octave-config.h" typedef enum -{ + { mxUNKNOWN_CLASS = 0, mxCELL_CLASS, mxSTRUCT_CLASS, @@ -76,7 +76,7 @@ mxClassID; typedef enum -{ + { mxREAL = 0, mxCOMPLEX = 1 } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-errno.in.cc --- a/libinterp/corefcn/oct-errno.in.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-errno.in.cc Thu Dec 01 20:05:44 2022 -0800 @@ -276,7 +276,7 @@ // Others (duplicates are OK). -@SYSDEP_ERRNO_LIST@ + @SYSDEP_ERRNO_LIST@ { nullptr, 0 }, }; @@ -322,7 +322,7 @@ octave_errno::do_lookup (const std::string& name) { return (m_errno_tbl.find (name) != m_errno_tbl.end ()) ? m_errno_tbl[name] - : -1; + : -1; } octave_scalar_map diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-hdf5-types.cc --- a/libinterp/corefcn/oct-hdf5-types.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-hdf5-types.cc Thu Dec 01 20:05:44 2022 -0800 @@ -47,15 +47,15 @@ if (warn && ! ok) warning_with_id - ("Octave:internal", - "the size of octave_hdf5_id is smaller than the size of HDF5 hid_t"); + ("Octave:internal", + "the size of octave_hdf5_id is smaller than the size of HDF5 hid_t"); ok = sizeof (octave_hdf5_err) >= sizeof (herr_t); if (warn && ! ok) warning_with_id - ("Octave:internal", - "the size of octave_hdf5_err is smaller than the size of HDF5 herr_t"); + ("Octave:internal", + "the size of octave_hdf5_err is smaller than the size of HDF5 herr_t"); #else octave_unused_parameter (warn); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-hist.cc --- a/libinterp/corefcn/oct-hist.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-hist.cc Thu Dec 01 20:05:44 2022 -0800 @@ -72,510 +72,510 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Read the edited history lines from STREAM and return them - // one at a time. This can read unlimited length lines. The - // caller should free the storage. +// Read the edited history lines from STREAM and return them +// one at a time. This can read unlimited length lines. The +// caller should free the storage. - static char * - edit_history_readline (std::fstream& stream) - { - char c; - int line_len = 128; - int lindex = 0; - char *line = new char [line_len]; - line[0] = '\0'; +static char * +edit_history_readline (std::fstream& stream) +{ + char c; + int line_len = 128; + int lindex = 0; + char *line = new char [line_len]; + line[0] = '\0'; - while (stream.get (c)) - { - if (lindex + 2 >= line_len) - { - char *tmp_line = new char [line_len += 128]; - strcpy (tmp_line, line); - delete [] line; - line = tmp_line; - } + while (stream.get (c)) + { + if (lindex + 2 >= line_len) + { + char *tmp_line = new char [line_len += 128]; + strcpy (tmp_line, line); + delete [] line; + line = tmp_line; + } - if (c == '\n') - { - line[lindex++] = '\n'; - line[lindex++] = '\0'; - return line; - } - else - line[lindex++] = c; - } + if (c == '\n') + { + line[lindex++] = '\n'; + line[lindex++] = '\0'; + return line; + } + else + line[lindex++] = c; + } - if (! lindex) - { - delete [] line; - return nullptr; - } + if (! lindex) + { + delete [] line; + return nullptr; + } - if (lindex + 2 >= line_len) - { - char *tmp_line = new char [lindex+3]; - strcpy (tmp_line, line); - delete [] line; - line = tmp_line; - } + if (lindex + 2 >= line_len) + { + char *tmp_line = new char [lindex+3]; + strcpy (tmp_line, line); + delete [] line; + line = tmp_line; + } - // Finish with newline if none in file. + // Finish with newline if none in file. - line[lindex++] = '\n'; - line[lindex++] = '\0'; - return line; - } + line[lindex++] = '\n'; + line[lindex++] = '\0'; + return line; +} - static void - edit_history_add_hist (const std::string& line) - { - if (! line.empty ()) - { - std::string tmp = line; +static void +edit_history_add_hist (const std::string& line) +{ + if (! line.empty ()) + { + std::string tmp = line; - int len = tmp.length (); + int len = tmp.length (); - if (len > 0 && tmp[len-1] == '\n') - tmp.resize (len - 1); + if (len > 0 && tmp[len-1] == '\n') + tmp.resize (len - 1); - if (! tmp.empty ()) - { - if (command_history::add (tmp)) - { - event_manager& evmgr = __get_event_manager__ (); + if (! tmp.empty ()) + { + if (command_history::add (tmp)) + { + event_manager& evmgr = __get_event_manager__ (); - evmgr.append_history (tmp); - } - } - } - } + evmgr.append_history (tmp); + } + } + } +} - static bool - get_int_arg (const octave_value& arg, int& val) - { - bool ok = true; +static bool +get_int_arg (const octave_value& arg, int& val) +{ + bool ok = true; - if (arg.is_string ()) - { - std::string tmp = arg.string_value (); + if (arg.is_string ()) + { + std::string tmp = arg.string_value (); - ok = sscanf (tmp.c_str (), "%d", &val) == 1; - } - else if (arg.isnumeric ()) - val = arg.int_value (); - else - ok = false; + ok = sscanf (tmp.c_str (), "%d", &val) == 1; + } + else if (arg.isnumeric ()) + val = arg.int_value (); + else + ok = false; - return ok; - } + return ok; +} - static std::string - mk_tmp_hist_file (const octave_value_list& args, - bool insert_curr, const char *warn_for) - { - string_vector hlist = command_history::list (); +static std::string +mk_tmp_hist_file (const octave_value_list& args, + bool insert_curr, const char *warn_for) +{ + string_vector hlist = command_history::list (); - int hist_count = hlist.numel () - 1; // switch to zero-based indexing + int hist_count = hlist.numel () - 1; // switch to zero-based indexing - // The current command line is already part of the history list by - // the time we get to this point. Delete the cmd from the list when - // executing 'edit_history' so that it doesn't show up in the history - // but the actual commands performed will. + // The current command line is already part of the history list by + // the time we get to this point. Delete the cmd from the list when + // executing 'edit_history' so that it doesn't show up in the history + // but the actual commands performed will. - if (! insert_curr) - command_history::remove (hist_count); + if (! insert_curr) + command_history::remove (hist_count); - hist_count--; // skip last entry in history list + hist_count--; // skip last entry in history list - // If no numbers have been specified, the default is to edit the - // last command in the history list. + // If no numbers have been specified, the default is to edit the + // last command in the history list. - int hist_beg = hist_count; - int hist_end = hist_count; + int hist_beg = hist_count; + int hist_end = hist_count; - bool reverse = false; + bool reverse = false; - // Process options. + // Process options. - int nargin = args.length (); + int nargin = args.length (); - if (nargin == 2) - { - if (! get_int_arg (args(0), hist_beg) - || ! get_int_arg (args(1), hist_end)) - error ("%s: arguments must be integers", warn_for); + if (nargin == 2) + { + if (! get_int_arg (args(0), hist_beg) + || ! get_int_arg (args(1), hist_end)) + error ("%s: arguments must be integers", warn_for); - if (hist_beg < 0) - hist_beg += (hist_count + 1); - else - hist_beg--; - if (hist_end < 0) - hist_end += (hist_count + 1); - else - hist_end--; - } - else if (nargin == 1) - { - if (! get_int_arg (args(0), hist_beg)) - error ("%s: argument must be an integer", warn_for); + if (hist_beg < 0) + hist_beg += (hist_count + 1); + else + hist_beg--; + if (hist_end < 0) + hist_end += (hist_count + 1); + else + hist_end--; + } + else if (nargin == 1) + { + if (! get_int_arg (args(0), hist_beg)) + error ("%s: argument must be an integer", warn_for); - if (hist_beg < 0) - hist_beg += (hist_count + 1); - else - hist_beg--; + if (hist_beg < 0) + hist_beg += (hist_count + 1); + else + hist_beg--; - hist_end = hist_beg; - } + hist_end = hist_beg; + } - if (hist_beg > hist_count || hist_end > hist_count) - error ("%s: history specification out of range", warn_for); + if (hist_beg > hist_count || hist_end > hist_count) + error ("%s: history specification out of range", warn_for); - if (hist_end < hist_beg) - { - std::swap (hist_end, hist_beg); - reverse = true; - } + if (hist_end < hist_beg) + { + std::swap (hist_end, hist_beg); + reverse = true; + } - std::string name = sys::tempnam ("", "oct-"); + std::string name = sys::tempnam ("", "oct-"); - std::ofstream file = sys::ofstream (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, - name.c_str ()); + if (! file) + error ("%s: couldn't open temporary file '%s'", warn_for, + name.c_str ()); - if (reverse) - { - for (int i = hist_end; i >= hist_beg; i--) - file << hlist[i] << "\n"; - } - else - { - for (int i = hist_beg; i <= hist_end; i++) - file << hlist[i] << "\n"; - } + if (reverse) + { + for (int i = hist_end; i >= hist_beg; i--) + file << hlist[i] << "\n"; + } + else + { + for (int i = hist_beg; i <= hist_end; i++) + file << hlist[i] << "\n"; + } - file.close (); + file.close (); - return name; - } + return name; +} - history_system::history_system (interpreter& interp) - : m_interpreter (interp), m_input_from_tmp_file (false), - m_timestamp_format_string (default_timestamp_format ()) - { } +history_system::history_system (interpreter& interp) + : m_interpreter (interp), m_input_from_tmp_file (false), + m_timestamp_format_string (default_timestamp_format ()) +{ } - void history_system::initialize (bool read_history_file) - { - command_history::initialize (read_history_file, default_file (), - default_size (), - sys::env::getenv ("OCTAVE_HISTCONTROL")); +void history_system::initialize (bool read_history_file) +{ + command_history::initialize (read_history_file, default_file (), + default_size (), + sys::env::getenv ("OCTAVE_HISTCONTROL")); - event_manager& evmgr = m_interpreter.get_event_manager (); + event_manager& evmgr = m_interpreter.get_event_manager (); - evmgr.set_history (command_history::list ()); - } + evmgr.set_history (command_history::list ()); +} - void history_system::write_timestamp (void) - { - sys::localtime now; +void history_system::write_timestamp (void) +{ + sys::localtime now; - std::string timestamp = now.strftime (m_timestamp_format_string); + std::string timestamp = now.strftime (m_timestamp_format_string); - if (! timestamp.empty ()) - { - if (command_history::add (timestamp)) - { - event_manager& evmgr = m_interpreter.get_event_manager (); + if (! timestamp.empty ()) + { + if (command_history::add (timestamp)) + { + event_manager& evmgr = m_interpreter.get_event_manager (); - evmgr.append_history (timestamp); - } - } - } + evmgr.append_history (timestamp); + } + } +} - octave_value - history_system::input_from_tmp_file (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_input_from_tmp_file, args, nargout, - "input_from_tmp_file"); - } +octave_value +history_system::input_from_tmp_file (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_input_from_tmp_file, args, nargout, + "input_from_tmp_file"); +} - octave_value - history_system::timestamp_format_string (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_timestamp_format_string, args, nargout, - "timestamp_format_string"); - } +octave_value +history_system::timestamp_format_string (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_timestamp_format_string, args, nargout, + "timestamp_format_string"); +} - // Display, save, or load history. Stolen and modified from bash. - // - // Arg of -w FILENAME means write file, arg of -r FILENAME - // means read file, arg of -q means don't number lines. Arg of N - // means only display that many items. +// Display, save, or load history. Stolen and modified from bash. +// +// Arg of -w FILENAME means write file, arg of -r FILENAME +// means read file, arg of -q means don't number lines. Arg of N +// means only display that many items. - string_vector history_system::do_history (const octave_value_list& args, - int nargout) - { - bool numbered_output = nargout == 0; +string_vector history_system::do_history (const octave_value_list& args, + int nargout) +{ + bool numbered_output = nargout == 0; - unwind_action restore_history_filename - ([] (const std::string& old_filename) - { - command_history::set_file (old_filename); - }, command_history::file ()); + unwind_action restore_history_filename + ([] (const std::string& old_filename) + { + command_history::set_file (old_filename); + }, command_history::file ()); - string_vector hlist; + string_vector hlist; - int nargin = args.length (); + int nargin = args.length (); - // Number of history lines to show (-1 = all) - int limit = -1; + // Number of history lines to show (-1 = all) + int limit = -1; - for (octave_idx_type i = 0; i < nargin; i++) - { - octave_value arg = args(i); + for (octave_idx_type i = 0; i < nargin; i++) + { + octave_value arg = args(i); - std::string option; + std::string option; - if (arg.is_string ()) - option = arg.string_value (); - else if (arg.isnumeric ()) - { - limit = arg.int_value (); - if (limit < 0) - limit = -limit; - continue; - } - else - err_wrong_type_arg ("history", arg); + if (arg.is_string ()) + option = arg.string_value (); + else if (arg.isnumeric ()) + { + limit = arg.int_value (); + if (limit < 0) + limit = -limit; + continue; + } + else + err_wrong_type_arg ("history", arg); - event_manager& evmgr = m_interpreter.get_event_manager (); + event_manager& evmgr = m_interpreter.get_event_manager (); - if (option == "-r" || option == "-w" || option == "-a" - || option == "-n") - { - if (i < nargin - 1) - { - std::string fname - = args(++i).xstring_value ("history: filename must be a string for %s option", - option.c_str ()); + if (option == "-r" || option == "-w" || option == "-a" + || option == "-n") + { + if (i < nargin - 1) + { + std::string fname + = args(++i).xstring_value ("history: filename must be a string for %s option", + option.c_str ()); - command_history::set_file (fname); - } - else - command_history::set_file (default_file ()); + command_history::set_file (fname); + } + else + command_history::set_file (default_file ()); - if (option == "-a") - // Append 'new' lines to file. - command_history::append (); + if (option == "-a") + // Append 'new' lines to file. + command_history::append (); - else if (option == "-w") - // Write entire history. - command_history::write (); + else if (option == "-w") + // Write entire history. + command_history::write (); - else if (option == "-r") - { - // Read entire file. - command_history::read (); - evmgr.set_history (command_history::list ()); - } + else if (option == "-r") + { + // Read entire file. + command_history::read (); + evmgr.set_history (command_history::list ()); + } - else if (option == "-n") - { - // Read 'new' history from file. - command_history::read_range (); - evmgr.set_history (command_history::list ()); - } + else if (option == "-n") + { + // Read 'new' history from file. + command_history::read_range (); + evmgr.set_history (command_history::list ()); + } - else - panic_impossible (); + else + panic_impossible (); - return hlist; - } - else if (option == "-c") - { - command_history::clear (); - evmgr.clear_history (); - } - else if (option == "-q") - numbered_output = false; - else if (option == "--") - { - i++; - break; - } - else - { - // The last argument found in the command list that looks like - // an integer will be used - int tmp; + return hlist; + } + else if (option == "-c") + { + command_history::clear (); + evmgr.clear_history (); + } + else if (option == "-q") + numbered_output = false; + else if (option == "--") + { + i++; + break; + } + else + { + // The last argument found in the command list that looks like + // an integer will be used + int tmp; - if (sscanf (option.c_str (), "%d", &tmp) == 1) - { - if (tmp > 0) - limit = tmp; - else - limit = -tmp; - } + if (sscanf (option.c_str (), "%d", &tmp) == 1) + { + if (tmp > 0) + limit = tmp; + else + limit = -tmp; + } - else - { - if (option.length () > 0 && option[0] == '-') - error ("history: unrecognized option '%s'", option.c_str ()); - else - error ("history: bad non-numeric arg '%s'", option.c_str ()); - } - } - } + else + { + if (option.length () > 0 && option[0] == '-') + error ("history: unrecognized option '%s'", option.c_str ()); + else + error ("history: bad non-numeric arg '%s'", option.c_str ()); + } + } + } - hlist = command_history::list (limit, numbered_output); + hlist = command_history::list (limit, numbered_output); - int len = hlist.numel (); + int len = hlist.numel (); - if (nargout == 0) - { - for (octave_idx_type i = 0; i < len; i++) - octave_stdout << hlist[i] << "\n"; - } + if (nargout == 0) + { + for (octave_idx_type i = 0; i < len; i++) + octave_stdout << hlist[i] << "\n"; + } - return hlist; - } + return hlist; +} - void history_system::do_edit_history (const octave_value_list& args) - { - std::string name = mk_tmp_hist_file (args, false, "edit_history"); +void history_system::do_edit_history (const octave_value_list& args) +{ + std::string name = mk_tmp_hist_file (args, false, "edit_history"); - if (name.empty ()) - return; + if (name.empty ()) + return; - // Call up our favorite editor on the file of commands. + // Call up our favorite editor on the file of commands. - environment& env = m_interpreter.get_environment (); - std::string cmd = env.editor (); - cmd.append (R"( ")" + name + '"'); + environment& env = m_interpreter.get_environment (); + std::string cmd = env.editor (); + cmd.append (R"( ")" + name + '"'); - // Ignore interrupts while we are off editing commands. Should we - // maybe avoid using system()? + // Ignore interrupts while we are off editing commands. Should we + // maybe avoid using system()? - volatile interrupt_handler old_interrupt_handler - = ignore_interrupts (); + volatile interrupt_handler old_interrupt_handler + = ignore_interrupts (); - int status = sys::system (cmd); + int status = sys::system (cmd); - set_interrupt_handler (old_interrupt_handler); + set_interrupt_handler (old_interrupt_handler); - // Check if text edition was successful. Abort the operation - // in case of failure. - if (status != EXIT_SUCCESS) - error ("edit_history: text editor command failed"); + // Check if text edition was successful. Abort the operation + // in case of failure. + if (status != EXIT_SUCCESS) + error ("edit_history: text editor command failed"); - // Write the commands to the history file since source_file - // disables command line history while it executes. + // Write the commands to the history file since source_file + // disables command line history while it executes. - std::fstream file = sys::fstream (name.c_str (), std::ios::in); + std::fstream file = sys::fstream (name.c_str (), std::ios::in); - char *line; - //int first = 1; - while ((line = edit_history_readline (file)) != nullptr) - { - // Skip blank lines. + char *line; + //int first = 1; + while ((line = edit_history_readline (file)) != nullptr) + { + // Skip blank lines. - if (line[0] == '\n') - { - delete [] line; - continue; - } + if (line[0] == '\n') + { + delete [] line; + continue; + } - edit_history_add_hist (line); + edit_history_add_hist (line); - delete [] line; - } + delete [] line; + } - file.close (); + file.close (); - int(*unlink_fptr)(const std::string&) = sys::unlink; - unwind_action unlink_action (unlink_fptr, name); - unwind_protect_var upv (m_input_from_tmp_file, true); + int(*unlink_fptr)(const std::string&) = sys::unlink; + unwind_action unlink_action (unlink_fptr, name); + unwind_protect_var upv (m_input_from_tmp_file, true); - // FIXME: instead of sourcing a file, we should just iterate through - // the list of commands, parsing and executing them one at a time as - // if they were entered interactively. + // FIXME: instead of sourcing a file, we should just iterate through + // the list of commands, parsing and executing them one at a time as + // if they were entered interactively. - source_file (name); - } + source_file (name); +} - void history_system::do_run_history (const octave_value_list& args) - { - std::string name = mk_tmp_hist_file (args, false, "run_history"); +void history_system::do_run_history (const octave_value_list& args) +{ + std::string name = mk_tmp_hist_file (args, false, "run_history"); - if (name.empty ()) - return; + if (name.empty ()) + return; - int(*unlink_fptr)(const std::string&) = sys::unlink; - unwind_action unlink_action (unlink_fptr, name); - unwind_protect_var upv (m_input_from_tmp_file, true); + int(*unlink_fptr)(const std::string&) = sys::unlink; + unwind_action unlink_action (unlink_fptr, name); + unwind_protect_var upv (m_input_from_tmp_file, true); - // FIXME: instead of sourcing a file, we should just iterate through - // the list of commands, parsing and executing them one at a time as - // if they were entered interactively. + // FIXME: instead of sourcing a file, we should just iterate through + // the list of commands, parsing and executing them one at a time as + // if they were entered interactively. - source_file (name); - } + source_file (name); +} - std::string history_system::default_file (void) - { - std::string file; +std::string history_system::default_file (void) +{ + std::string file; - std::string env_file = sys::env::getenv ("OCTAVE_HISTFILE"); + std::string env_file = sys::env::getenv ("OCTAVE_HISTFILE"); - if (! env_file.empty ()) - file = env_file; + if (! env_file.empty ()) + file = env_file; - if (file.empty ()) - { - // Default to $DATA/octave/history, where $DATA is the platform- - // dependent location for (roaming) user data files. + if (file.empty ()) + { + // Default to $DATA/octave/history, where $DATA is the platform- + // dependent location for (roaming) user data files. - std::string user_data_dir = sys::env::get_user_data_directory (); + std::string user_data_dir = sys::env::get_user_data_directory (); - std::string hist_dir = user_data_dir + sys::file_ops::dir_sep_str () - + "octave"; + std::string hist_dir = user_data_dir + sys::file_ops::dir_sep_str () + + "octave"; - file = sys::env::make_absolute ("history", hist_dir); - } + file = sys::env::make_absolute ("history", hist_dir); + } - return file; - } + return file; +} - int history_system::default_size (void) - { - int size = 1000; +int history_system::default_size (void) +{ + int size = 1000; - std::string env_size = sys::env::getenv ("OCTAVE_HISTSIZE"); + std::string env_size = sys::env::getenv ("OCTAVE_HISTSIZE"); - if (! env_size.empty ()) - { - int val; + if (! env_size.empty ()) + { + int val; - if (sscanf (env_size.c_str (), "%d", &val) == 1) - size = (val > 0 ? val : 0); - } + if (sscanf (env_size.c_str (), "%d", &val) == 1) + size = (val > 0 ? val : 0); + } - return size; - } + return size; +} - std::string history_system::default_timestamp_format (void) - { - return - "# Octave " OCTAVE_VERSION ", %a %b %d %H:%M:%S %Y %Z <" - + sys::env::get_user_name () - + '@' - + sys::env::get_host_name () - + '>'; - } +std::string history_system::default_timestamp_format (void) +{ + return + "# Octave " OCTAVE_VERSION ", %a %b %d %H:%M:%S %Y %Z <" + + sys::env::get_user_name () + + '@' + + sys::env::get_host_name () + + '>'; +} DEFMETHOD (edit_history, interp, args, , doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-hist.h --- a/libinterp/corefcn/oct-hist.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-hist.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,83 +36,83 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; - class OCTINTERP_API history_system - { - public: +class OCTINTERP_API history_system +{ +public: - history_system (interpreter& interp); + history_system (interpreter& interp); - history_system (const history_system&) = delete; + history_system (const history_system&) = delete; - history_system& operator = (const history_system&) = delete; + history_system& operator = (const history_system&) = delete; - ~history_system (void) = default; + ~history_system (void) = default; - void initialize (bool read_history_file = false); + void initialize (bool read_history_file = false); - void write_timestamp (void); + void write_timestamp (void); - octave_value input_from_tmp_file (const octave_value_list& args, - int nargout); + octave_value input_from_tmp_file (const octave_value_list& args, + int nargout); - bool input_from_tmp_file (void) const - { - return m_input_from_tmp_file; - } + bool input_from_tmp_file (void) const + { + return m_input_from_tmp_file; + } - bool input_from_tmp_file (bool flag) - { - return set (m_input_from_tmp_file, flag); - } + bool input_from_tmp_file (bool flag) + { + return set (m_input_from_tmp_file, flag); + } - octave_value timestamp_format_string (const octave_value_list& args, - int nargout); + octave_value timestamp_format_string (const octave_value_list& args, + int nargout); - std::string timestamp_format_string (void) const - { - return m_timestamp_format_string; - } + std::string timestamp_format_string (void) const + { + return m_timestamp_format_string; + } - std::string timestamp_format_string (const std::string& file) - { - return set (m_timestamp_format_string, file); - } + std::string timestamp_format_string (const std::string& file) + { + return set (m_timestamp_format_string, file); + } - string_vector - do_history (const octave_value_list& args = octave_value_list (), - int nargout = 0); + string_vector + do_history (const octave_value_list& args = octave_value_list (), + int nargout = 0); - void do_edit_history (const octave_value_list& args = octave_value_list ()); + void do_edit_history (const octave_value_list& args = octave_value_list ()); - void do_run_history (const octave_value_list& args = octave_value_list ()); + void do_run_history (const octave_value_list& args = octave_value_list ()); - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - // TRUE means input is coming from temporary history file. - bool m_input_from_tmp_file; + // TRUE means input is coming from temporary history file. + bool m_input_from_tmp_file; - // The format of the timestamp marker written to the history file when - // Octave exits. - std::string m_timestamp_format_string; + // The format of the timestamp marker written to the history file when + // Octave exits. + std::string m_timestamp_format_string; - static std::string default_file (void); + static std::string default_file (void); - static int default_size (void); + static int default_size (void); - static std::string default_timestamp_format (void); + static std::string default_timestamp_format (void); - template - T set (T& var, const T& new_val) - { - T old_val = var; - var = new_val; - return old_val; - } - }; + template + T set (T& var, const T& new_val) + { + T old_val = var; + var = new_val; + return old_val; + } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-map.cc --- a/libinterp/corefcn/oct-map.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-map.cc Thu Dec 01 20:05:44 2022 -0800 @@ -50,7 +50,7 @@ (*m_rep)[fields(i)] = i; } -octave_fields::octave_fields (const char * const *fields) +octave_fields::octave_fields (const char *const *fields) : m_rep (new fields_rep) { octave_idx_type n = 0; @@ -167,7 +167,7 @@ } octave_scalar_map::octave_scalar_map - (const std::map& m) +(const std::map& m) { std::size_t sz = m.size (); m_vals.resize (sz); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-map.h --- a/libinterp/corefcn/oct-map.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-map.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,7 +40,7 @@ // A class holding a map field->index. Supports reference-counting. class OCTINTERP_API -octave_fields + octave_fields { class fields_rep : public std::map { @@ -57,13 +57,13 @@ fields_rep *m_rep; - static fields_rep *nil_rep (void); + static fields_rep * nil_rep (void); public: octave_fields (void) : m_rep (nil_rep ()) { m_rep->m_count++; } octave_fields (const string_vector&); - octave_fields (const char * const *); + octave_fields (const char *const *); ~octave_fields (void) { @@ -158,7 +158,7 @@ }; class OCTINTERP_API -octave_scalar_map + octave_scalar_map { public: @@ -273,7 +273,7 @@ { return v.scalar_map_value (); } class OCTINTERP_API -octave_map + octave_map { public: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-opengl.h --- a/libinterp/corefcn/oct-opengl.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-opengl.h Thu Dec 01 20:05:44 2022 -0800 @@ -52,412 +52,412 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class opengl_functions - { - public: +class opengl_functions +{ +public: - opengl_functions (void) { } + opengl_functions (void) { } - opengl_functions (const opengl_functions&) = default; + opengl_functions (const opengl_functions&) = default; - opengl_functions& operator = (const opengl_functions&) = default; + opengl_functions& operator = (const opengl_functions&) = default; - virtual ~opengl_functions (void) = default; + virtual ~opengl_functions (void) = default; #if defined (HAVE_OPENGL) - // If OpenGL is not available, opengl_functions will be a dummy - // class that does nothing. This makes the implementation of - // other things that rely on this class slightly simpler. + // If OpenGL is not available, opengl_functions will be a dummy + // class that does nothing. This makes the implementation of + // other things that rely on this class slightly simpler. - virtual void glAlphaFunc (GLenum fcn, GLclampf ref) - { - ::glAlphaFunc (fcn, ref); - } + virtual void glAlphaFunc (GLenum fcn, GLclampf ref) + { + ::glAlphaFunc (fcn, ref); + } - virtual void glBegin (GLenum mode) - { - ::glBegin (mode); - } + virtual void glBegin (GLenum mode) + { + ::glBegin (mode); + } - virtual void glBindTexture (GLenum target, GLuint texture) - { - ::glBindTexture (target, texture); - } + virtual void glBindTexture (GLenum target, GLuint texture) + { + ::glBindTexture (target, texture); + } - virtual void glBitmap (GLsizei width, GLsizei height, GLfloat xorig, - GLfloat yorig, GLfloat xmove, GLfloat ymove, - const GLubyte *bitmap) - { - ::glBitmap (width, height, xorig, yorig, xmove, ymove, bitmap); - } + virtual void glBitmap (GLsizei width, GLsizei height, GLfloat xorig, + GLfloat yorig, GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap) + { + ::glBitmap (width, height, xorig, yorig, xmove, ymove, bitmap); + } - virtual void glBlendFunc (GLenum sfactor, GLenum dfactor) - { - ::glBlendFunc (sfactor, dfactor); - } + virtual void glBlendFunc (GLenum sfactor, GLenum dfactor) + { + ::glBlendFunc (sfactor, dfactor); + } - virtual void glCallList (GLuint list) - { - ::glCallList (list); - } + virtual void glCallList (GLuint list) + { + ::glCallList (list); + } - virtual void glClearColor (GLclampf red, GLclampf green, GLclampf blue, - GLclampf alpha) - { - ::glClearColor (red, green, blue, alpha); - } + virtual void glClearColor (GLclampf red, GLclampf green, GLclampf blue, + GLclampf alpha) + { + ::glClearColor (red, green, blue, alpha); + } - virtual void glClear (GLbitfield mask) - { - ::glClear (mask); - } + virtual void glClear (GLbitfield mask) + { + ::glClear (mask); + } - virtual void glClipPlane (GLenum plane, const GLdouble *equation) - { - ::glClipPlane (plane, equation); - } + virtual void glClipPlane (GLenum plane, const GLdouble *equation) + { + ::glClipPlane (plane, equation); + } - virtual void glColor3dv (const GLdouble *v) - { - ::glColor3dv (v); - } + virtual void glColor3dv (const GLdouble *v) + { + ::glColor3dv (v); + } - virtual void glColor3f (GLfloat red, GLfloat green, GLfloat blue) - { - ::glColor3f (red, green, blue); - } + virtual void glColor3f (GLfloat red, GLfloat green, GLfloat blue) + { + ::glColor3f (red, green, blue); + } - virtual void glColor3fv (const GLfloat *v) - { - ::glColor3fv (v); - } + virtual void glColor3fv (const GLfloat *v) + { + ::glColor3fv (v); + } - virtual void glColor4d (GLdouble red, GLdouble green, GLdouble blue, - GLdouble alpha) - { - ::glColor4d (red, green, blue, alpha); - } + virtual void glColor4d (GLdouble red, GLdouble green, GLdouble blue, + GLdouble alpha) + { + ::glColor4d (red, green, blue, alpha); + } - virtual void glColor4f (GLfloat red, GLfloat green, GLfloat blue, - GLfloat alpha) - { - ::glColor4f (red, green, blue, alpha); - } + virtual void glColor4f (GLfloat red, GLfloat green, GLfloat blue, + GLfloat alpha) + { + ::glColor4f (red, green, blue, alpha); + } - virtual void glColor4fv (const GLfloat *v) - { - ::glColor4fv (v); - } + virtual void glColor4fv (const GLfloat *v) + { + ::glColor4fv (v); + } - virtual void glDeleteLists (GLuint list, GLsizei range) - { - ::glDeleteLists (list, range); - } + virtual void glDeleteLists (GLuint list, GLsizei range) + { + ::glDeleteLists (list, range); + } - virtual void glDeleteTextures (GLsizei n, const GLuint *textures) - { - ::glDeleteTextures (n, textures); - } + virtual void glDeleteTextures (GLsizei n, const GLuint *textures) + { + ::glDeleteTextures (n, textures); + } - virtual void glDepthFunc (GLenum fcn) - { - ::glDepthFunc (fcn); - } + virtual void glDepthFunc (GLenum fcn) + { + ::glDepthFunc (fcn); + } - virtual void glDisable (GLenum cap) - { - ::glDisable (cap); - } + virtual void glDisable (GLenum cap) + { + ::glDisable (cap); + } - virtual void glDrawPixels (GLsizei width, GLsizei height, GLenum format, - GLenum type, const GLvoid *pixels) - { - ::glDrawPixels (width, height, format, type, pixels); - } + virtual void glDrawPixels (GLsizei width, GLsizei height, GLenum format, + GLenum type, const GLvoid *pixels) + { + ::glDrawPixels (width, height, format, type, pixels); + } - virtual void glEdgeFlag (GLboolean flag) - { - ::glEdgeFlag (flag); - } + virtual void glEdgeFlag (GLboolean flag) + { + ::glEdgeFlag (flag); + } - virtual void glEnable (GLenum cap) - { - ::glEnable (cap); - } + virtual void glEnable (GLenum cap) + { + ::glEnable (cap); + } - virtual void glEndList (void) - { - ::glEndList (); - } + virtual void glEndList (void) + { + ::glEndList (); + } - virtual void glEnd (void) - { - ::glEnd (); - } + virtual void glEnd (void) + { + ::glEnd (); + } - virtual void glFinish (void) - { - ::glFinish (); - } + virtual void glFinish (void) + { + ::glFinish (); + } - virtual GLuint glGenLists (GLsizei range) - { - return ::glGenLists (range); - } + virtual GLuint glGenLists (GLsizei range) + { + return ::glGenLists (range); + } - virtual void glGenTextures (GLsizei n, GLuint *textures) - { - ::glGenTextures (n, textures); - } + virtual void glGenTextures (GLsizei n, GLuint *textures) + { + ::glGenTextures (n, textures); + } - virtual void glGetBooleanv (GLenum pname, GLboolean *data) - { - ::glGetBooleanv (pname, data); - } + virtual void glGetBooleanv (GLenum pname, GLboolean *data) + { + ::glGetBooleanv (pname, data); + } - virtual void glGetDoublev (GLenum pname, GLdouble *data) - { - ::glGetDoublev (pname, data); - } + virtual void glGetDoublev (GLenum pname, GLdouble *data) + { + ::glGetDoublev (pname, data); + } - virtual GLenum glGetError (void) - { - return ::glGetError (); - } + virtual GLenum glGetError (void) + { + return ::glGetError (); + } - virtual void glGetFloatv (GLenum pname, GLfloat *data) - { - ::glGetFloatv (pname, data); - } + virtual void glGetFloatv (GLenum pname, GLfloat *data) + { + ::glGetFloatv (pname, data); + } - virtual void glGetIntegerv (GLenum pname, GLint *data) - { - ::glGetIntegerv (pname, data); - } + virtual void glGetIntegerv (GLenum pname, GLint *data) + { + ::glGetIntegerv (pname, data); + } - virtual const GLubyte * glGetString (GLenum name) - { - return ::glGetString (name); - } + virtual const GLubyte * glGetString (GLenum name) + { + return ::glGetString (name); + } - virtual void glHint (GLenum target, GLenum mode) - { - ::glHint (target, mode); - } + virtual void glHint (GLenum target, GLenum mode) + { + ::glHint (target, mode); + } - virtual void glInitNames (void) - { - ::glInitNames (); - } + virtual void glInitNames (void) + { + ::glInitNames (); + } - virtual GLboolean glIsEnabled (GLenum cap) - { - return ::glIsEnabled (cap); - } + virtual GLboolean glIsEnabled (GLenum cap) + { + return ::glIsEnabled (cap); + } - virtual void glLightfv (GLenum light, GLenum pname, const GLfloat *params) - { - ::glLightfv (light, pname, params); - } + virtual void glLightfv (GLenum light, GLenum pname, const GLfloat *params) + { + ::glLightfv (light, pname, params); + } - virtual void glLineStipple (GLint factor, GLushort pattern) - { - ::glLineStipple (factor, pattern); - } + virtual void glLineStipple (GLint factor, GLushort pattern) + { + ::glLineStipple (factor, pattern); + } - virtual void glLineWidth (GLfloat width) - { - ::glLineWidth (width); - } + virtual void glLineWidth (GLfloat width) + { + ::glLineWidth (width); + } - virtual void glLoadIdentity (void) - { - ::glLoadIdentity (); - } + virtual void glLoadIdentity (void) + { + ::glLoadIdentity (); + } - virtual void glMaterialf (GLenum face, GLenum pname, GLfloat param) - { - ::glMaterialf (face, pname, param); - } + virtual void glMaterialf (GLenum face, GLenum pname, GLfloat param) + { + ::glMaterialf (face, pname, param); + } - virtual void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) - { - ::glMaterialfv (face, pname, params); - } + virtual void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) + { + ::glMaterialfv (face, pname, params); + } - virtual void glMatrixMode (GLenum mode) - { - ::glMatrixMode (mode); - } + virtual void glMatrixMode (GLenum mode) + { + ::glMatrixMode (mode); + } - virtual void glMultMatrixd (const GLdouble *m) - { - ::glMultMatrixd (m); - } + virtual void glMultMatrixd (const GLdouble *m) + { + ::glMultMatrixd (m); + } - virtual void glNewList (GLuint list, GLenum mode) - { - ::glNewList (list, mode); - } + virtual void glNewList (GLuint list, GLenum mode) + { + ::glNewList (list, mode); + } - virtual void glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz) - { - ::glNormal3d (nx, ny, nz); - } + virtual void glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz) + { + ::glNormal3d (nx, ny, nz); + } - virtual void glNormal3dv (const GLdouble *v) - { - ::glNormal3dv (v); - } + virtual void glNormal3dv (const GLdouble *v) + { + ::glNormal3dv (v); + } - virtual void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, - GLdouble top, GLdouble near_val, GLdouble far_val) - { - ::glOrtho (left, right, bottom, top, near_val, far_val); - } + virtual void glOrtho (GLdouble left, GLdouble right, GLdouble bottom, + GLdouble top, GLdouble near_val, GLdouble far_val) + { + ::glOrtho (left, right, bottom, top, near_val, far_val); + } - virtual void glPixelStorei (GLenum pname, GLint param) - { - ::glPixelStorei (pname, param); - } + virtual void glPixelStorei (GLenum pname, GLint param) + { + ::glPixelStorei (pname, param); + } - virtual void glPixelZoom (GLfloat xfactor, GLfloat yfactor) - { - ::glPixelZoom (xfactor, yfactor); - } + virtual void glPixelZoom (GLfloat xfactor, GLfloat yfactor) + { + ::glPixelZoom (xfactor, yfactor); + } - virtual void glPolygonMode (GLenum face, GLenum mode) - { - ::glPolygonMode (face, mode); - } + virtual void glPolygonMode (GLenum face, GLenum mode) + { + ::glPolygonMode (face, mode); + } - virtual void glPolygonOffset (GLfloat factor, GLfloat units) - { - ::glPolygonOffset (factor, units); - } + virtual void glPolygonOffset (GLfloat factor, GLfloat units) + { + ::glPolygonOffset (factor, units); + } - virtual void glPopAttrib (void) - { - ::glPopAttrib (); - } + virtual void glPopAttrib (void) + { + ::glPopAttrib (); + } - virtual void glPopMatrix (void) - { - ::glPopMatrix (); - } + virtual void glPopMatrix (void) + { + ::glPopMatrix (); + } - virtual void glPopName (void) - { - ::glPopName (); - } + virtual void glPopName (void) + { + ::glPopName (); + } - virtual void glPushAttrib (GLbitfield mask) - { - ::glPushAttrib (mask); - } + virtual void glPushAttrib (GLbitfield mask) + { + ::glPushAttrib (mask); + } - virtual void glPushMatrix (void) - { - ::glPushMatrix (); - } + virtual void glPushMatrix (void) + { + ::glPushMatrix (); + } - virtual void glPushName (GLuint name) - { - ::glPushName (name); - } + virtual void glPushName (GLuint name) + { + ::glPushName (name); + } - virtual void glRasterPos3d (GLdouble x, GLdouble y, GLdouble z) - { - ::glRasterPos3d (x, y, z); - } + virtual void glRasterPos3d (GLdouble x, GLdouble y, GLdouble z) + { + ::glRasterPos3d (x, y, z); + } - virtual void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLvoid *pixels) - { - ::glReadPixels (x, y, width, height, format, type, pixels); - } + virtual void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLvoid *pixels) + { + ::glReadPixels (x, y, width, height, format, type, pixels); + } - virtual GLint glRenderMode (GLenum mode) - { - return ::glRenderMode (mode); - } + virtual GLint glRenderMode (GLenum mode) + { + return ::glRenderMode (mode); + } - virtual void glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) - { - ::glRotated (angle, x, y, z); - } + virtual void glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) + { + ::glRotated (angle, x, y, z); + } - virtual void glScaled (GLdouble x, GLdouble y, GLdouble z) - { - ::glScaled (x, y, z); - } + virtual void glScaled (GLdouble x, GLdouble y, GLdouble z) + { + ::glScaled (x, y, z); + } - virtual void glScalef (GLfloat x, GLfloat y, GLfloat z) - { - ::glScalef (x, y, z); - } + virtual void glScalef (GLfloat x, GLfloat y, GLfloat z) + { + ::glScalef (x, y, z); + } - virtual void glSelectBuffer (GLsizei size, GLuint *buffer) - { - ::glSelectBuffer (size, buffer); - } + virtual void glSelectBuffer (GLsizei size, GLuint *buffer) + { + ::glSelectBuffer (size, buffer); + } - virtual void glShadeModel (GLenum mode) - { - ::glShadeModel (mode); - } + virtual void glShadeModel (GLenum mode) + { + ::glShadeModel (mode); + } - virtual void glTexCoord2d (GLdouble s, GLdouble t) - { - ::glTexCoord2d (s, t); - } + virtual void glTexCoord2d (GLdouble s, GLdouble t) + { + ::glTexCoord2d (s, t); + } - virtual void glTexImage2D (GLenum target, GLint level, GLint internalFormat, - GLsizei width, GLsizei height, GLint border, - GLenum format, GLenum type, const GLvoid *pixels) - { - ::glTexImage2D (target, level, internalFormat, width, height, border, - format, type, pixels); - } + virtual void glTexImage2D (GLenum target, GLint level, GLint internalFormat, + GLsizei width, GLsizei height, GLint border, + GLenum format, GLenum type, const GLvoid *pixels) + { + ::glTexImage2D (target, level, internalFormat, width, height, border, + format, type, pixels); + } - virtual void glTexParameteri (GLenum target, GLenum pname, GLint param) - { - ::glTexParameteri (target, pname, param); - } + virtual void glTexParameteri (GLenum target, GLenum pname, GLint param) + { + ::glTexParameteri (target, pname, param); + } - virtual void glTranslated (GLdouble x, GLdouble y, GLdouble z) - { - ::glTranslated (x, y, z); - } + virtual void glTranslated (GLdouble x, GLdouble y, GLdouble z) + { + ::glTranslated (x, y, z); + } - virtual void glTranslatef (GLfloat x, GLfloat y, GLfloat z) - { - ::glTranslatef (x, y, z); - } + virtual void glTranslatef (GLfloat x, GLfloat y, GLfloat z) + { + ::glTranslatef (x, y, z); + } - virtual void glVertex2d (GLdouble x, GLdouble y) - { - ::glVertex2d (x, y); - } + virtual void glVertex2d (GLdouble x, GLdouble y) + { + ::glVertex2d (x, y); + } - virtual void glVertex3d (GLdouble x, GLdouble y, GLdouble z) - { - ::glVertex3d (x, y, z); - } + virtual void glVertex3d (GLdouble x, GLdouble y, GLdouble z) + { + ::glVertex3d (x, y, z); + } - virtual void glVertex3dv (const GLdouble *v) - { - ::glVertex3dv (v); - } + virtual void glVertex3dv (const GLdouble *v) + { + ::glVertex3dv (v); + } - virtual void glViewport (GLint x, GLint y, GLsizei width, GLsizei height) - { - ::glViewport (x, y, width, height); - } + virtual void glViewport (GLint x, GLint y, GLsizei width, GLsizei height) + { + ::glViewport (x, y, width, height); + } #endif - }; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-prcstrm.h --- a/libinterp/corefcn/oct-prcstrm.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-prcstrm.h Thu Dec 01 20:05:44 2022 -0800 @@ -48,7 +48,7 @@ octave_iprocstream (const std::string& n, std::ios::openmode arg_md = std::ios::in, octave::mach_info::float_format flt_fmt - = octave::mach_info::native_float_format (), + = octave::mach_info::native_float_format (), const std::string& encoding = "utf-8"); // No copying! @@ -60,7 +60,7 @@ static octave::stream create (const std::string& n, std::ios::openmode arg_md = std::ios::in, octave::mach_info::float_format flt_fmt - = octave::mach_info::native_float_format (), + = octave::mach_info::native_float_format (), const std::string& encoding = "utf-8"); protected: @@ -76,7 +76,7 @@ octave_oprocstream (const std::string& n, std::ios::openmode arg_md = std::ios::out, octave::mach_info::float_format flt_fmt - = octave::mach_info::native_float_format (), + = octave::mach_info::native_float_format (), const std::string& encoding = "utf-8"); // No copying! @@ -88,7 +88,7 @@ static octave::stream create (const std::string& n, std::ios::openmode arg_md = std::ios::out, octave::mach_info::float_format flt_fmt - = octave::mach_info::native_float_format (), + = octave::mach_info::native_float_format (), const std::string& encoding = "utf-8"); protected: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-process.cc --- a/libinterp/corefcn/oct-process.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-process.cc Thu Dec 01 20:05:44 2022 -0800 @@ -33,57 +33,57 @@ OCTAVE_BEGIN_NAMESPACE(octave) - process_execution_result - process_execution_result::of_success (int exit_status, - const std::string& stdout_output) - { - return process_execution_result (0, exit_status, stdout_output, ""); - } +process_execution_result +process_execution_result::of_success (int exit_status, + const std::string& stdout_output) +{ + return process_execution_result (0, exit_status, stdout_output, ""); +} - process_execution_result - process_execution_result::of_error (int status, const std::string& err_msg) - { - return process_execution_result (status, -1, "", err_msg); - } +process_execution_result +process_execution_result::of_error (int status, const std::string& err_msg) +{ + return process_execution_result (status, -1, "", err_msg); +} - // Execute a shell command, returning results as a C++ object - process_execution_result - run_command_and_return_output (const std::string& cmd_str) - { - iprocstream cmd (cmd_str.c_str ()); +// Execute a shell command, returning results as a C++ object +process_execution_result +run_command_and_return_output (const std::string& cmd_str) +{ + iprocstream cmd (cmd_str.c_str ()); - if (! cmd) - { - std::string msg = "unable to start subprocess for '" + cmd_str + "'"; + if (! cmd) + { + std::string msg = "unable to start subprocess for '" + cmd_str + "'"; - return process_execution_result::of_error (-1, msg); - } + return process_execution_result::of_error (-1, msg); + } - std::ostringstream output_buf; + std::ostringstream output_buf; - char ch; + char ch; - for (;;) - { - if (cmd.get (ch)) - output_buf.put (ch); - else - { - if (! cmd.eof () && errno == EAGAIN) - cmd.clear (); - else - break; - } - } + for (;;) + { + if (cmd.get (ch)) + output_buf.put (ch); + else + { + if (! cmd.eof () && errno == EAGAIN) + cmd.clear (); + else + break; + } + } - int cmd_status = cmd.close (); + int cmd_status = cmd.close (); - if (sys::wifexited (cmd_status)) - cmd_status = sys::wexitstatus (cmd_status); - else - cmd_status = 127; + if (sys::wifexited (cmd_status)) + cmd_status = sys::wexitstatus (cmd_status); + else + cmd_status = 127; - return process_execution_result::of_success (cmd_status, output_buf.str ()); - } + return process_execution_result::of_success (cmd_status, output_buf.str ()); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-process.h --- a/libinterp/corefcn/oct-process.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-process.h Thu Dec 01 20:05:44 2022 -0800 @@ -32,53 +32,53 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - process_execution_result - { - public: +class +process_execution_result +{ +public: - process_execution_result (void) - : m_status (-1), m_err_msg (), m_exit_status (-1), m_stdout_output () - { } + process_execution_result (void) + : m_status (-1), m_err_msg (), m_exit_status (-1), m_stdout_output () + { } - process_execution_result (int status, int exit_status, - const std::string& stdout_output, - const std::string& err_msg) - : m_status (status), m_err_msg (err_msg), m_exit_status (exit_status), - m_stdout_output (stdout_output) - { } + process_execution_result (int status, int exit_status, + const std::string& stdout_output, + const std::string& err_msg) + : m_status (status), m_err_msg (err_msg), m_exit_status (exit_status), + m_stdout_output (stdout_output) + { } - static OCTINTERP_API process_execution_result - of_success (int exit_status, const std::string& stdout_output); + static OCTINTERP_API process_execution_result + of_success (int exit_status, const std::string& stdout_output); - static OCTINTERP_API process_execution_result - of_error (int status, const std::string& err_msg); + static OCTINTERP_API process_execution_result + of_error (int status, const std::string& err_msg); - int status (void) const { return m_status; } + int status (void) const { return m_status; } - int exit_status (void) const { return m_exit_status; } + int exit_status (void) const { return m_exit_status; } - std::string err_msg (void) const { return m_err_msg; } + std::string err_msg (void) const { return m_err_msg; } - std::string stdout_output (void) const { return m_stdout_output; } + std::string stdout_output (void) const { return m_stdout_output; } - private: +private: - // Launch status of the process, 0 for success, nonzero for error. - int m_status; + // Launch status of the process, 0 for success, nonzero for error. + int m_status; - // Error message if executing command failed. - std::string m_err_msg; + // Error message if executing command failed. + std::string m_err_msg; - // Exit status of the process. - int m_exit_status; + // Exit status of the process. + int m_exit_status; - // Collected stdout output of the process. - std::string m_stdout_output; - }; + // Collected stdout output of the process. + std::string m_stdout_output; +}; - extern OCTINTERP_API process_execution_result - run_command_and_return_output (const std::string& cmd_str); +extern OCTINTERP_API process_execution_result +run_command_and_return_output (const std::string& cmd_str); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-stdstrm.h --- a/libinterp/corefcn/oct-stdstrm.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-stdstrm.h Thu Dec 01 20:05:44 2022 -0800 @@ -135,7 +135,7 @@ const std::string& encoding = "utf-8", c_file_ptr_buf::close_fcn cf = c_file_ptr_buf::file_close) : tstdiostream - (n, f, f ? fileno (f) : -1, m, ff, encoding, cf) { } + (n, f, f ? fileno (f) : -1, m, ff, encoding, cf) { } static stream create (const std::string& n, FILE *f = nullptr, @@ -172,7 +172,7 @@ const std::string& encoding = "utf-8", c_zfile_ptr_buf::close_fcn cf = c_zfile_ptr_buf::file_close) : tstdiostream - (n, f, fid, m, ff, encoding, cf) { } + (n, f, fid, m, ff, encoding, cf) { } static stream create (const std::string& n, gzFile f = nullptr, int fid = 0, diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-stream.cc Thu Dec 01 20:05:44 2022 -0800 @@ -69,1106 +69,1106 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Programming Note: There are two very different error functions used - // in the stream code. When invoked with "error (...)" the member - // function from stream or base_stream is called. This - // function sets the error state on the stream AND returns control to - // the caller. The caller must then return a value at the end of the - // function. When invoked with "::error (...)" the exception-based - // error function from error.h is used. This function will throw an - // exception and not return control to the caller. BE CAREFUL and - // invoke the correct error function! - - // Possible values for conv_err: - // - // 1 : not a real scalar - // 2 : value is NaN - // 3 : value is not an integer - - static int - convert_to_valid_int (const octave_value& tc, int& conv_err) - { - conv_err = 0; - - int retval = 0; - - double dval = 0.0; - - try - { - dval = tc.double_value (); - } - catch (const execution_exception&) - { - interpreter& interp = __get_interpreter__ (); - - interp.recover_from_exception (); - - conv_err = 1; - } - - if (! conv_err) - { - if (! lo_ieee_isnan (dval)) - { - int ival = math::nint (dval); - - if (ival == dval) - retval = ival; - else - conv_err = 3; - } - else - conv_err = 2; - } - - return retval; - } - - static octave_idx_type - get_size (double d, const std::string& who) - { - octave_idx_type retval = -1; - - if (lo_ieee_isnan (d)) - ::error ("%s: NaN invalid as size specification", who.c_str ()); - - if (math::isinf (d)) - retval = -1; - else - { - if (d < 0.0) - ::error ("%s: negative value invalid as size specification", - who.c_str ()); - - static const double out_of_range_top - = static_cast (std::numeric_limits::max ()) - + 1.; - if (d >= out_of_range_top) - ::error ("%s: dimension too large for Octave's index type", - who.c_str ()); - - retval = math::nint_big (d); - } - - return retval; - } - - static void - get_size (const Array& size, - octave_idx_type& nr, octave_idx_type& nc, - bool& one_elt_size_spec, const std::string& who) - { - nr = -1; - nc = -1; - - one_elt_size_spec = false; - - double dnr = -1.0; - double dnc = -1.0; - - octave_idx_type sz_len = size.numel (); - - if (sz_len == 1) - { - one_elt_size_spec = true; - - dnr = size(0); - - dnc = (dnr == 0.0) ? 0.0 : 1.0; - } - else if (sz_len == 2) - { - dnr = size(0); - - if (math::isinf (dnr)) - ::error ("%s: infinite value invalid as size specification", - who.c_str ()); - - dnc = size(1); - } - else - ::error ("%s: invalid size specification (must be 2-D)", who.c_str ()); - - nr = get_size (dnr, who); - - if (dnc >= 0.0) - { - nc = get_size (dnc, who); - - // Check for overflow. - if (nr > 0 && nc > 0 - && nc > std::numeric_limits::max () / nr) - ::error ("%s: size too large for Octave's index type", who.c_str ()); - } - } - - static std::string - expand_char_class (const std::string& s) - { - std::string retval; - - std::size_t len = s.length (); - - std::size_t i = 0; - - while (i < len) - { - unsigned char c = s[i++]; - - if (c == '-' && i > 1 && i < len - && ( static_cast (s[i-2]) - <= static_cast (s[i]))) - { - // Add all characters from the range except the first (we - // already added it below). - - for (c = s[i-2]+1; c < s[i]; c++) - retval += c; - } - else - { - // Add the character to the class. Only add '-' if it is - // the last character in the class. - - if (c != '-' || i == len) - retval += c; - } - } - - return retval; - } - - class - scanf_format_elt - { - public: - - enum special_conversion - { - whitespace_conversion = 1, - literal_conversion = 2, - null = 3 - }; - - scanf_format_elt (const std::string& txt = "", int w = 0, bool d = false, - char typ = '\0', char mod = '\0', - const std::string& ch_class = "") - : text (txt), width (w), discard (d), type (typ), - modifier (mod), char_class (ch_class) - { } - - scanf_format_elt (const scanf_format_elt&) = default; - - scanf_format_elt& operator = (const scanf_format_elt&) = default; - - ~scanf_format_elt (void) = default; - - // The C-style format string. - std::string text; - - // The maximum field width. - int width; - - // TRUE if we are not storing the result of this conversion. - bool discard; - - // Type of conversion -- 'd', 'i', 'o', 'u', 'x', 'e', 'f', 'g', - // 'c', 's', 'p', '%', or '['. - char type; - - // A length modifier -- 'h', 'l', or 'L'. - char modifier; - - // The class of characters in a '[' format. - std::string char_class; - }; - - class - scanf_format_list - { - public: - - scanf_format_list (const std::string& fmt = ""); - - // No copying! - - scanf_format_list (const scanf_format_list&) = delete; - - scanf_format_list& operator = (const scanf_format_list&) = delete; - - ~scanf_format_list (void); - - octave_idx_type num_conversions (void) { return m_nconv; } - - // The length can be different than the number of conversions. - // For example, "x %d y %d z" has 2 conversions but the length of - // the list is 3 because of the characters that appear after the - // last conversion. - - std::size_t length (void) const { return m_fmt_elts.size (); } - - const scanf_format_elt * first (void) - { - m_curr_idx = 0; - return current (); - } - - const scanf_format_elt * current (void) const - { - return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr; - } - - const scanf_format_elt * next (bool cycle = true) - { - static scanf_format_elt dummy - ("", 0, false, scanf_format_elt::null, '\0', ""); - - m_curr_idx++; - - if (m_curr_idx >= length ()) +// Programming Note: There are two very different error functions used +// in the stream code. When invoked with "error (...)" the member +// function from stream or base_stream is called. This +// function sets the error state on the stream AND returns control to +// the caller. The caller must then return a value at the end of the +// function. When invoked with "::error (...)" the exception-based +// error function from error.h is used. This function will throw an +// exception and not return control to the caller. BE CAREFUL and +// invoke the correct error function! + +// Possible values for conv_err: +// +// 1 : not a real scalar +// 2 : value is NaN +// 3 : value is not an integer + +static int +convert_to_valid_int (const octave_value& tc, int& conv_err) +{ + conv_err = 0; + + int retval = 0; + + double dval = 0.0; + + try + { + dval = tc.double_value (); + } + catch (const execution_exception&) + { + interpreter& interp = __get_interpreter__ (); + + interp.recover_from_exception (); + + conv_err = 1; + } + + if (! conv_err) + { + if (! lo_ieee_isnan (dval)) { - if (cycle) - m_curr_idx = 0; + int ival = math::nint (dval); + + if (ival == dval) + retval = ival; else - return &dummy; + conv_err = 3; + } + else + conv_err = 2; + } + + return retval; +} + +static octave_idx_type +get_size (double d, const std::string& who) +{ + octave_idx_type retval = -1; + + if (lo_ieee_isnan (d)) + ::error ("%s: NaN invalid as size specification", who.c_str ()); + + if (math::isinf (d)) + retval = -1; + else + { + if (d < 0.0) + ::error ("%s: negative value invalid as size specification", + who.c_str ()); + + static const double out_of_range_top + = static_cast (std::numeric_limits::max ()) + + 1.; + if (d >= out_of_range_top) + ::error ("%s: dimension too large for Octave's index type", + who.c_str ()); + + retval = math::nint_big (d); + } + + return retval; +} + +static void +get_size (const Array& size, + octave_idx_type& nr, octave_idx_type& nc, + bool& one_elt_size_spec, const std::string& who) +{ + nr = -1; + nc = -1; + + one_elt_size_spec = false; + + double dnr = -1.0; + double dnc = -1.0; + + octave_idx_type sz_len = size.numel (); + + if (sz_len == 1) + { + one_elt_size_spec = true; + + dnr = size(0); + + dnc = (dnr == 0.0) ? 0.0 : 1.0; + } + else if (sz_len == 2) + { + dnr = size(0); + + if (math::isinf (dnr)) + ::error ("%s: infinite value invalid as size specification", + who.c_str ()); + + dnc = size(1); + } + else + ::error ("%s: invalid size specification (must be 2-D)", who.c_str ()); + + nr = get_size (dnr, who); + + if (dnc >= 0.0) + { + nc = get_size (dnc, who); + + // Check for overflow. + if (nr > 0 && nc > 0 + && nc > std::numeric_limits::max () / nr) + ::error ("%s: size too large for Octave's index type", who.c_str ()); + } +} + +static std::string +expand_char_class (const std::string& s) +{ + std::string retval; + + std::size_t len = s.length (); + + std::size_t i = 0; + + while (i < len) + { + unsigned char c = s[i++]; + + if (c == '-' && i > 1 && i < len + && ( static_cast (s[i-2]) + <= static_cast (s[i]))) + { + // Add all characters from the range except the first (we + // already added it below). + + for (c = s[i-2]+1; c < s[i]; c++) + retval += c; + } + else + { + // Add the character to the class. Only add '-' if it is + // the last character in the class. + + if (c != '-' || i == len) + retval += c; } - - return current (); - } - - void printme (void) const; - - bool ok (void) const { return (m_nconv >= 0); } - - operator bool () const { return ok (); } - - bool all_character_conversions (void); - - bool all_numeric_conversions (void); - - private: - - void add_elt_to_list (int width, bool discard, char type, char modifier, - const std::string& char_class = ""); - - void process_conversion (const std::string& s, std::size_t& i, - std::size_t n, int& width, bool& discard, - char& type, char& modifier); - - int finish_conversion (const std::string& s, std::size_t& i, std::size_t n, - int width, bool discard, char& type, - char modifier); - - //-------- - - // Number of conversions specified by this format string, or -1 if - // invalid conversions have been found. - octave_idx_type m_nconv; - - // Index to current element; - std::size_t m_curr_idx; - - // List of format elements. - std::deque m_fmt_elts; - - // Temporary buffer. - std::ostringstream m_buf; - + } + + return retval; +} + +class +scanf_format_elt +{ +public: + + enum special_conversion + { + whitespace_conversion = 1, + literal_conversion = 2, + null = 3 }; - scanf_format_list::scanf_format_list (const std::string& s) - : m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf () + scanf_format_elt (const std::string& txt = "", int w = 0, bool d = false, + char typ = '\0', char mod = '\0', + const std::string& ch_class = "") + : text (txt), width (w), discard (d), type (typ), + modifier (mod), char_class (ch_class) + { } + + scanf_format_elt (const scanf_format_elt&) = default; + + scanf_format_elt& operator = (const scanf_format_elt&) = default; + + ~scanf_format_elt (void) = default; + + // The C-style format string. + std::string text; + + // The maximum field width. + int width; + + // TRUE if we are not storing the result of this conversion. + bool discard; + + // Type of conversion -- 'd', 'i', 'o', 'u', 'x', 'e', 'f', 'g', + // 'c', 's', 'p', '%', or '['. + char type; + + // A length modifier -- 'h', 'l', or 'L'. + char modifier; + + // The class of characters in a '[' format. + std::string char_class; +}; + +class +scanf_format_list +{ +public: + + scanf_format_list (const std::string& fmt = ""); + + // No copying! + + scanf_format_list (const scanf_format_list&) = delete; + + scanf_format_list& operator = (const scanf_format_list&) = delete; + + ~scanf_format_list (void); + + octave_idx_type num_conversions (void) { return m_nconv; } + + // The length can be different than the number of conversions. + // For example, "x %d y %d z" has 2 conversions but the length of + // the list is 3 because of the characters that appear after the + // last conversion. + + std::size_t length (void) const { return m_fmt_elts.size (); } + + const scanf_format_elt * first (void) { - std::size_t n = s.length (); - - std::size_t i = 0; - - int width = 0; - bool discard = false; - char modifier = '\0'; - char type = '\0'; - - bool have_more = true; - - while (i < n) + m_curr_idx = 0; + return current (); + } + + const scanf_format_elt * current (void) const + { + return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr; + } + + const scanf_format_elt * next (bool cycle = true) + { + static scanf_format_elt dummy + ("", 0, false, scanf_format_elt::null, '\0', ""); + + m_curr_idx++; + + if (m_curr_idx >= length ()) { - have_more = true; - - if (s[i] == '%') - { - // Process percent-escape conversion type. - - process_conversion (s, i, n, width, discard, type, modifier); - - have_more = (m_buf.tellp () != 0); - } - else if (isspace (s[i])) - { - type = scanf_format_elt::whitespace_conversion; - - width = 0; - discard = false; - modifier = '\0'; - m_buf << ' '; - - while (++i < n && isspace (s[i])) - ; // skip whitespace - - add_elt_to_list (width, discard, type, modifier); - - have_more = false; - } + if (cycle) + m_curr_idx = 0; else - { - type = scanf_format_elt::literal_conversion; - - width = 0; - discard = false; - modifier = '\0'; - - while (i < n && ! isspace (s[i]) && s[i] != '%') - m_buf << s[i++]; - - add_elt_to_list (width, discard, type, modifier); - - have_more = false; - } - - if (m_nconv < 0) - { - have_more = false; - break; - } + return &dummy; } - if (have_more) - add_elt_to_list (width, discard, type, modifier); - - m_buf.clear (); - m_buf.str (""); - } - - scanf_format_list::~scanf_format_list (void) - { - std::size_t n = m_fmt_elts.size (); - - for (std::size_t i = 0; i < n; i++) - { - scanf_format_elt *elt = m_fmt_elts[i]; - delete elt; - } + return current (); } - void - scanf_format_list::add_elt_to_list (int width, bool discard, char type, - char modifier, - const std::string& char_class) - { - std::string text = m_buf.str (); - - if (! text.empty ()) - { - scanf_format_elt *elt - = new scanf_format_elt (text, width, discard, type, - modifier, char_class); - - m_fmt_elts.push_back (elt); - } - - m_buf.clear (); - m_buf.str (""); - } - - void - scanf_format_list::process_conversion (const std::string& s, std::size_t& i, - std::size_t n, int& width, - bool& discard, char& type, - char& modifier) - { - width = 0; - discard = false; - modifier = '\0'; - type = '\0'; - - m_buf << s[i++]; - - bool have_width = false; - - while (i < n) - { - switch (s[i]) - { - case '*': - if (discard) + void printme (void) const; + + bool ok (void) const { return (m_nconv >= 0); } + + operator bool () const { return ok (); } + + bool all_character_conversions (void); + + bool all_numeric_conversions (void); + +private: + + void add_elt_to_list (int width, bool discard, char type, char modifier, + const std::string& char_class = ""); + + void process_conversion (const std::string& s, std::size_t& i, + std::size_t n, int& width, bool& discard, + char& type, char& modifier); + + int finish_conversion (const std::string& s, std::size_t& i, std::size_t n, + int width, bool discard, char& type, + char modifier); + + //-------- + + // Number of conversions specified by this format string, or -1 if + // invalid conversions have been found. + octave_idx_type m_nconv; + + // Index to current element; + std::size_t m_curr_idx; + + // List of format elements. + std::deque m_fmt_elts; + + // Temporary buffer. + std::ostringstream m_buf; + +}; + +scanf_format_list::scanf_format_list (const std::string& s) + : m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf () +{ + std::size_t n = s.length (); + + std::size_t i = 0; + + int width = 0; + bool discard = false; + char modifier = '\0'; + char type = '\0'; + + bool have_more = true; + + while (i < n) + { + have_more = true; + + if (s[i] == '%') + { + // Process percent-escape conversion type. + + process_conversion (s, i, n, width, discard, type, modifier); + + have_more = (m_buf.tellp () != 0); + } + else if (isspace (s[i])) + { + type = scanf_format_elt::whitespace_conversion; + + width = 0; + discard = false; + modifier = '\0'; + m_buf << ' '; + + while (++i < n && isspace (s[i])) + ; // skip whitespace + + add_elt_to_list (width, discard, type, modifier); + + have_more = false; + } + else + { + type = scanf_format_elt::literal_conversion; + + width = 0; + discard = false; + modifier = '\0'; + + while (i < n && ! isspace (s[i]) && s[i] != '%') + m_buf << s[i++]; + + add_elt_to_list (width, discard, type, modifier); + + have_more = false; + } + + if (m_nconv < 0) + { + have_more = false; + break; + } + } + + if (have_more) + add_elt_to_list (width, discard, type, modifier); + + m_buf.clear (); + m_buf.str (""); +} + +scanf_format_list::~scanf_format_list (void) +{ + std::size_t n = m_fmt_elts.size (); + + for (std::size_t i = 0; i < n; i++) + { + scanf_format_elt *elt = m_fmt_elts[i]; + delete elt; + } +} + +void +scanf_format_list::add_elt_to_list (int width, bool discard, char type, + char modifier, + const std::string& char_class) +{ + std::string text = m_buf.str (); + + if (! text.empty ()) + { + scanf_format_elt *elt + = new scanf_format_elt (text, width, discard, type, + modifier, char_class); + + m_fmt_elts.push_back (elt); + } + + m_buf.clear (); + m_buf.str (""); +} + +void +scanf_format_list::process_conversion (const std::string& s, std::size_t& i, + std::size_t n, int& width, + bool& discard, char& type, + char& modifier) +{ + width = 0; + discard = false; + modifier = '\0'; + type = '\0'; + + m_buf << s[i++]; + + bool have_width = false; + + while (i < n) + { + switch (s[i]) + { + case '*': + if (discard) + m_nconv = -1; + else + { + discard = true; + m_buf << s[i++]; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (have_width) + m_nconv = -1; + else + { + char c = s[i++]; + width = 10 * width + c - '0'; + have_width = true; + m_buf << c; + while (i < n && isdigit (s[i])) + { + c = s[i++]; + width = 10 * width + c - '0'; + m_buf << c; + } + } + break; + + case 'h': case 'l': case 'L': + if (modifier != '\0') + m_nconv = -1; + else + modifier = s[i++]; + break; + + // We accept X for compatibility with undocumented Matlab behavior. + case 'd': case 'i': case 'o': case 'u': case 'x': + case 'X': + if (modifier == 'L') + { m_nconv = -1; - else - { - discard = true; - m_buf << s[i++]; - } - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (have_width) - m_nconv = -1; - else - { - char c = s[i++]; - width = 10 * width + c - '0'; - have_width = true; - m_buf << c; - while (i < n && isdigit (s[i])) - { - c = s[i++]; - width = 10 * width + c - '0'; - m_buf << c; - } - } - break; - - case 'h': case 'l': case 'L': - if (modifier != '\0') + break; + } + goto fini; + + // We accept E and G for compatibility with undocumented + // Matlab behavior. + case 'e': case 'f': case 'g': + case 'E': case 'G': + if (modifier == 'h') + { m_nconv = -1; - else - modifier = s[i++]; - break; - - // We accept X for compatibility with undocumented Matlab behavior. - case 'd': case 'i': case 'o': case 'u': case 'x': - case 'X': - if (modifier == 'L') - { - m_nconv = -1; - break; - } - goto fini; - - // We accept E and G for compatibility with undocumented - // Matlab behavior. - case 'e': case 'f': case 'g': - case 'E': case 'G': - if (modifier == 'h') - { - m_nconv = -1; - break; - } - - // No float or long double conversions, thanks. - m_buf << 'l'; - - goto fini; - - case 'c': case 's': case 'p': case '%': case '[': - if (modifier != '\0') - { - m_nconv = -1; - break; - } - goto fini; - - fini: + break; + } + + // No float or long double conversions, thanks. + m_buf << 'l'; + + goto fini; + + case 'c': case 's': case 'p': case '%': case '[': + if (modifier != '\0') { - if (finish_conversion (s, i, n, width, discard, - type, modifier) == 0) - return; + m_nconv = -1; + break; } - break; - - default: - m_nconv = -1; - break; + goto fini; + + fini: + { + if (finish_conversion (s, i, n, width, discard, + type, modifier) == 0) + return; } - - if (m_nconv < 0) + break; + + default: + m_nconv = -1; break; - } - - m_nconv = -1; - } - - int - scanf_format_list::finish_conversion (const std::string& s, std::size_t& i, - std::size_t n, int width, bool discard, - char& type, char modifier) - { - int retval = 0; - - std::string char_class; - - std::size_t beg_idx = std::string::npos; - std::size_t end_idx = std::string::npos; - - if (s[i] == '%') - { - type = '%'; - m_buf << s[i++]; - } - else - { - type = s[i]; - - if (s[i] == '[') - { + } + + if (m_nconv < 0) + break; + } + + m_nconv = -1; +} + +int +scanf_format_list::finish_conversion (const std::string& s, std::size_t& i, + std::size_t n, int width, bool discard, + char& type, char modifier) +{ + int retval = 0; + + std::string char_class; + + std::size_t beg_idx = std::string::npos; + std::size_t end_idx = std::string::npos; + + if (s[i] == '%') + { + type = '%'; + m_buf << s[i++]; + } + else + { + type = s[i]; + + if (s[i] == '[') + { + m_buf << s[i++]; + + if (i < n) + { + beg_idx = i; + + if (s[i] == '^') + { + type = '^'; + m_buf << s[i++]; + + if (i < n) + { + beg_idx = i; + + if (s[i] == ']') + m_buf << s[i++]; + } + } + else if (s[i] == ']') + m_buf << s[i++]; + } + + while (i < n && s[i] != ']') m_buf << s[i++]; - if (i < n) - { - beg_idx = i; - - if (s[i] == '^') - { - type = '^'; - m_buf << s[i++]; - - if (i < n) - { - beg_idx = i; - - if (s[i] == ']') - m_buf << s[i++]; - } - } - else if (s[i] == ']') - m_buf << s[i++]; - } - - while (i < n && s[i] != ']') + if (i < n && s[i] == ']') + { + end_idx = i-1; m_buf << s[i++]; - - if (i < n && s[i] == ']') - { - end_idx = i-1; - m_buf << s[i++]; - } - - if (s[i-1] != ']') - retval = m_nconv = -1; - } - else - m_buf << s[i++]; - - m_nconv++; - } - - if (m_nconv >= 0) - { - if (beg_idx != std::string::npos && end_idx != std::string::npos) - char_class = expand_char_class (s.substr (beg_idx, - end_idx - beg_idx + 1)); - - add_elt_to_list (width, discard, type, modifier, char_class); - } - - return retval; - } - - void - scanf_format_list::printme (void) const - { - std::size_t n = m_fmt_elts.size (); - - for (std::size_t i = 0; i < n; i++) - { - scanf_format_elt *elt = m_fmt_elts[i]; - - std::cerr + } + + if (s[i-1] != ']') + retval = m_nconv = -1; + } + else + m_buf << s[i++]; + + m_nconv++; + } + + if (m_nconv >= 0) + { + if (beg_idx != std::string::npos && end_idx != std::string::npos) + char_class = expand_char_class (s.substr (beg_idx, + end_idx - beg_idx + 1)); + + add_elt_to_list (width, discard, type, modifier, char_class); + } + + return retval; +} + +void +scanf_format_list::printme (void) const +{ + std::size_t n = m_fmt_elts.size (); + + for (std::size_t i = 0; i < n; i++) + { + scanf_format_elt *elt = m_fmt_elts[i]; + + std::cerr << "width: " << elt->width << "\n" << "discard: " << elt->discard << "\n" << "type: "; - if (elt->type == scanf_format_elt::literal_conversion) - std::cerr << "literal text\n"; - else if (elt->type == scanf_format_elt::whitespace_conversion) - std::cerr << "whitespace\n"; - else - std::cerr << elt->type << "\n"; - - std::cerr + if (elt->type == scanf_format_elt::literal_conversion) + std::cerr << "literal text\n"; + else if (elt->type == scanf_format_elt::whitespace_conversion) + std::cerr << "whitespace\n"; + else + std::cerr << elt->type << "\n"; + + std::cerr << "modifier: " << elt->modifier << "\n" << "char_class: '" << undo_string_escapes (elt->char_class) << "'\n" << "text: '" << undo_string_escapes (elt->text) << "'\n\n"; - } - } - - bool - scanf_format_list::all_character_conversions (void) - { - std::size_t n = m_fmt_elts.size (); - - if (n > 0) - { - for (std::size_t i = 0; i < n; i++) - { - scanf_format_elt *elt = m_fmt_elts[i]; - - switch (elt->type) - { - case 'c': case 's': case '%': case '[': case '^': - case scanf_format_elt::literal_conversion: - case scanf_format_elt::whitespace_conversion: - break; - - default: - return false; - break; - } - } - - return true; - } - else - return false; - } - - bool - scanf_format_list::all_numeric_conversions (void) - { - std::size_t n = m_fmt_elts.size (); - - if (n > 0) - { - for (std::size_t i = 0; i < n; i++) - { - scanf_format_elt *elt = m_fmt_elts[i]; - - switch (elt->type) - { - case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': - case 'e': case 'f': case 'g': case 'E': case 'G': - break; - - default: - return false; - break; - } - } - - return true; - } - else - return false; - } - - class - printf_format_elt - { - public: - - printf_format_elt (const std::string& txt = "", int n = 0, int w = -1, - int p = -1, const std::string& f = "", - char typ = '\0', char mod = '\0') - : text (txt), args (n), fw (w), prec (p), flags (f), - type (typ), modifier (mod) - { } - - printf_format_elt (const printf_format_elt&) = default; - - printf_format_elt& operator = (const printf_format_elt&) = default; - - ~printf_format_elt (void) = default; - - // The C-style format string. - std::string text; - - // How many args do we expect to consume? - int args; - - // Field width. - int fw; - - // Precision. - int prec; - - // Flags -- '-', '+', ' ', '0', or '#'. - std::string flags; - - // Type of conversion -- 'd', 'i', 'o', 'x', 'X', 'u', 'c', 's', - // 'f', 'e', 'E', 'g', 'G', 'p', or '%' - char type; - - // A length modifier -- 'h', 'l', or 'L'. - char modifier; - }; - - class - printf_format_list - { - public: - - printf_format_list (const std::string& fmt = ""); - - // No copying! - - printf_format_list (const printf_format_list&) = delete; - - printf_format_list& operator = (const printf_format_list&) = delete; - - ~printf_format_list (void); - - octave_idx_type num_conversions (void) { return m_nconv; } - - const printf_format_elt * first (void) - { - m_curr_idx = 0; - return current (); - } - - const printf_format_elt * current (void) const - { - return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr; - } - - std::size_t length (void) const { return m_fmt_elts.size (); } - - const printf_format_elt * next (bool cycle = true) - { - m_curr_idx++; - - if (m_curr_idx >= length ()) + } +} + +bool +scanf_format_list::all_character_conversions (void) +{ + std::size_t n = m_fmt_elts.size (); + + if (n > 0) + { + for (std::size_t i = 0; i < n; i++) { - if (cycle) - m_curr_idx = 0; - else - return nullptr; + scanf_format_elt *elt = m_fmt_elts[i]; + + switch (elt->type) + { + case 'c': case 's': case '%': case '[': case '^': + case scanf_format_elt::literal_conversion: + case scanf_format_elt::whitespace_conversion: + break; + + default: + return false; + break; + } + } + + return true; + } + else + return false; +} + +bool +scanf_format_list::all_numeric_conversions (void) +{ + std::size_t n = m_fmt_elts.size (); + + if (n > 0) + { + for (std::size_t i = 0; i < n; i++) + { + scanf_format_elt *elt = m_fmt_elts[i]; + + switch (elt->type) + { + case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': + case 'e': case 'f': case 'g': case 'E': case 'G': + break; + + default: + return false; + break; + } } - return current (); - } - - bool last_elt_p (void) { return (m_curr_idx + 1 == length ()); } - - void printme (void) const; - - bool ok (void) const { return (m_nconv >= 0); } - - operator bool () const { return ok (); } - - private: - - void add_elt_to_list (int args, const std::string& flags, int fw, - int prec, char type, char modifier); - - void process_conversion (const std::string& s, std::size_t& i, - std::size_t n, - int& args, std::string& flags, int& fw, - int& prec, char& modifier, char& type); - - void finish_conversion (const std::string& s, std::size_t& i, int args, - const std::string& flags, int fw, int prec, - char modifier, char& type); - - //-------- - - // Number of conversions specified by this format string, or -1 if - // invalid conversions have been found. - octave_idx_type m_nconv; - - // Index to current element; - std::size_t m_curr_idx; - - // List of format elements. - std::deque m_fmt_elts; - - // Temporary buffer. - std::ostringstream m_buf; - - }; - - printf_format_list::printf_format_list (const std::string& s) - : m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf () + return true; + } + else + return false; +} + +class +printf_format_elt +{ +public: + + printf_format_elt (const std::string& txt = "", int n = 0, int w = -1, + int p = -1, const std::string& f = "", + char typ = '\0', char mod = '\0') + : text (txt), args (n), fw (w), prec (p), flags (f), + type (typ), modifier (mod) + { } + + printf_format_elt (const printf_format_elt&) = default; + + printf_format_elt& operator = (const printf_format_elt&) = default; + + ~printf_format_elt (void) = default; + + // The C-style format string. + std::string text; + + // How many args do we expect to consume? + int args; + + // Field width. + int fw; + + // Precision. + int prec; + + // Flags -- '-', '+', ' ', '0', or '#'. + std::string flags; + + // Type of conversion -- 'd', 'i', 'o', 'x', 'X', 'u', 'c', 's', + // 'f', 'e', 'E', 'g', 'G', 'p', or '%' + char type; + + // A length modifier -- 'h', 'l', or 'L'. + char modifier; +}; + +class +printf_format_list +{ +public: + + printf_format_list (const std::string& fmt = ""); + + // No copying! + + printf_format_list (const printf_format_list&) = delete; + + printf_format_list& operator = (const printf_format_list&) = delete; + + ~printf_format_list (void); + + octave_idx_type num_conversions (void) { return m_nconv; } + + const printf_format_elt * first (void) + { + m_curr_idx = 0; + return current (); + } + + const printf_format_elt * current (void) const + { + return length () > 0 ? m_fmt_elts[m_curr_idx] : nullptr; + } + + std::size_t length (void) const { return m_fmt_elts.size (); } + + const printf_format_elt * next (bool cycle = true) { - std::size_t n = s.length (); - - std::size_t i = 0; - - int args = 0; - std::string flags; - int fw = -1; - int prec = -1; - char modifier = '\0'; - char type = '\0'; - - bool have_more = true; - bool empty_buf = true; - - if (n == 0) + m_curr_idx++; + + if (m_curr_idx >= length ()) { - printf_format_elt *elt - = new printf_format_elt ("", args, fw, prec, flags, type, modifier); - - m_fmt_elts.push_back (elt); + if (cycle) + m_curr_idx = 0; + else + return nullptr; } - else - { - while (i < n) - { - have_more = true; - - empty_buf = (m_buf.tellp () == 0); - - switch (s[i]) + + return current (); + } + + bool last_elt_p (void) { return (m_curr_idx + 1 == length ()); } + + void printme (void) const; + + bool ok (void) const { return (m_nconv >= 0); } + + operator bool () const { return ok (); } + +private: + + void add_elt_to_list (int args, const std::string& flags, int fw, + int prec, char type, char modifier); + + void process_conversion (const std::string& s, std::size_t& i, + std::size_t n, + int& args, std::string& flags, int& fw, + int& prec, char& modifier, char& type); + + void finish_conversion (const std::string& s, std::size_t& i, int args, + const std::string& flags, int fw, int prec, + char modifier, char& type); + + //-------- + + // Number of conversions specified by this format string, or -1 if + // invalid conversions have been found. + octave_idx_type m_nconv; + + // Index to current element; + std::size_t m_curr_idx; + + // List of format elements. + std::deque m_fmt_elts; + + // Temporary buffer. + std::ostringstream m_buf; + +}; + +printf_format_list::printf_format_list (const std::string& s) + : m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf () +{ + std::size_t n = s.length (); + + std::size_t i = 0; + + int args = 0; + std::string flags; + int fw = -1; + int prec = -1; + char modifier = '\0'; + char type = '\0'; + + bool have_more = true; + bool empty_buf = true; + + if (n == 0) + { + printf_format_elt *elt + = new printf_format_elt ("", args, fw, prec, flags, type, modifier); + + m_fmt_elts.push_back (elt); + } + else + { + while (i < n) + { + have_more = true; + + empty_buf = (m_buf.tellp () == 0); + + switch (s[i]) + { + case '%': { - case '%': - { - if (empty_buf) - { - process_conversion (s, i, n, args, flags, fw, prec, - modifier, type); - - // If there is nothing in the buffer, then - // add_elt_to_list must have just been called, so we - // are already done with the current element and we - // don't need to call add_elt_to_list if this is our - // last trip through the loop. - - have_more = (m_buf.tellp () != 0); - } - else - add_elt_to_list (args, flags, fw, prec, type, modifier); - } - break; - - default: - { - args = 0; - flags = ""; - fw = -1; - prec = -1; - modifier = '\0'; - type = '\0'; - m_buf << s[i++]; - } - break; - } - - if (m_nconv < 0) - { - have_more = false; - break; + if (empty_buf) + { + process_conversion (s, i, n, args, flags, fw, prec, + modifier, type); + + // If there is nothing in the buffer, then + // add_elt_to_list must have just been called, so we + // are already done with the current element and we + // don't need to call add_elt_to_list if this is our + // last trip through the loop. + + have_more = (m_buf.tellp () != 0); + } + else + add_elt_to_list (args, flags, fw, prec, type, modifier); } - } - - if (have_more) - add_elt_to_list (args, flags, fw, prec, type, modifier); - - m_buf.clear (); - m_buf.str (""); - } - } - - printf_format_list::~printf_format_list (void) - { - std::size_t n = m_fmt_elts.size (); - - for (std::size_t i = 0; i < n; i++) - { - printf_format_elt *elt = m_fmt_elts[i]; - delete elt; - } - } - - void - printf_format_list::add_elt_to_list (int args, const std::string& flags, - int fw, int prec, char type, - char modifier) - { - std::string text = m_buf.str (); - - if (! text.empty ()) - { - printf_format_elt *elt - = new printf_format_elt (text, args, fw, prec, flags, - type, modifier); - - m_fmt_elts.push_back (elt); - } - - m_buf.clear (); - m_buf.str (""); - } - - void - printf_format_list::process_conversion (const std::string& s, std::size_t& i, - std::size_t n, int& args, - std::string& flags, int& fw, - int& prec, char& modifier, - char& type) - { - args = 0; - flags = ""; - fw = -1; - prec = -1; - modifier = '\0'; - type = '\0'; - - m_buf << s[i++]; - - bool nxt = false; - - while (i < n) - { - switch (s[i]) - { - case '-': case '+': case ' ': case '0': case '#': - flags += s[i]; - m_buf << s[i++]; - break; - - default: - nxt = true; - break; - } - - if (nxt) - break; - } - - if (i < n) - { - if (s[i] == '*') - { - fw = -2; - args++; - m_buf << s[i++]; - } - else - { - if (isdigit (s[i])) + break; + + default: { - int nn = 0; - std::string tmp = s.substr (i); - sscanf (tmp.c_str (), "%d%n", &fw, &nn); - } - - while (i < n && isdigit (s[i])) - m_buf << s[i++]; - } - } - - if (i < n && s[i] == '.') - { - // nothing before the . means 0. - if (fw == -1) - fw = 0; - - // . followed by nothing is 0. - prec = 0; - - m_buf << s[i++]; - - if (i < n) - { - if (s[i] == '*') - { - prec = -2; - args++; + args = 0; + flags = ""; + fw = -1; + prec = -1; + modifier = '\0'; + type = '\0'; m_buf << s[i++]; } - else - { - if (isdigit (s[i])) - { - int nn = 0; - std::string tmp = s.substr (i); - sscanf (tmp.c_str (), "%d%n", &prec, &nn); - } - - while (i < n && isdigit (s[i])) - m_buf << s[i++]; - } - } - } - - if (i < n) - { - // Accept and record modifier, but don't place it in the format - // item text. All integer conversions are handled as 64-bit - // integers. - - switch (s[i]) - { - case 'h': case 'l': case 'L': - modifier = s[i++]; - break; - - default: - break; - } - } - - if (i < n) - finish_conversion (s, i, args, flags, fw, prec, modifier, type); - else + break; + } + + if (m_nconv < 0) + { + have_more = false; + break; + } + } + + if (have_more) + add_elt_to_list (args, flags, fw, prec, type, modifier); + + m_buf.clear (); + m_buf.str (""); + } +} + +printf_format_list::~printf_format_list (void) +{ + std::size_t n = m_fmt_elts.size (); + + for (std::size_t i = 0; i < n; i++) + { + printf_format_elt *elt = m_fmt_elts[i]; + delete elt; + } +} + +void +printf_format_list::add_elt_to_list (int args, const std::string& flags, + int fw, int prec, char type, + char modifier) +{ + std::string text = m_buf.str (); + + if (! text.empty ()) + { + printf_format_elt *elt + = new printf_format_elt (text, args, fw, prec, flags, + type, modifier); + + m_fmt_elts.push_back (elt); + } + + m_buf.clear (); + m_buf.str (""); +} + +void +printf_format_list::process_conversion (const std::string& s, std::size_t& i, + std::size_t n, int& args, + std::string& flags, int& fw, + int& prec, char& modifier, + char& type) +{ + args = 0; + flags = ""; + fw = -1; + prec = -1; + modifier = '\0'; + type = '\0'; + + m_buf << s[i++]; + + bool nxt = false; + + while (i < n) + { + switch (s[i]) + { + case '-': case '+': case ' ': case '0': case '#': + flags += s[i]; + m_buf << s[i++]; + break; + + default: + nxt = true; + break; + } + + if (nxt) + break; + } + + if (i < n) + { + if (s[i] == '*') + { + fw = -2; + args++; + m_buf << s[i++]; + } + else + { + if (isdigit (s[i])) + { + int nn = 0; + std::string tmp = s.substr (i); + sscanf (tmp.c_str (), "%d%n", &fw, &nn); + } + + while (i < n && isdigit (s[i])) + m_buf << s[i++]; + } + } + + if (i < n && s[i] == '.') + { + // nothing before the . means 0. + if (fw == -1) + fw = 0; + + // . followed by nothing is 0. + prec = 0; + + m_buf << s[i++]; + + if (i < n) + { + if (s[i] == '*') + { + prec = -2; + args++; + m_buf << s[i++]; + } + else + { + if (isdigit (s[i])) + { + int nn = 0; + std::string tmp = s.substr (i); + sscanf (tmp.c_str (), "%d%n", &prec, &nn); + } + + while (i < n && isdigit (s[i])) + m_buf << s[i++]; + } + } + } + + if (i < n) + { + // Accept and record modifier, but don't place it in the format + // item text. All integer conversions are handled as 64-bit + // integers. + + switch (s[i]) + { + case 'h': case 'l': case 'L': + modifier = s[i++]; + break; + + default: + break; + } + } + + if (i < n) + finish_conversion (s, i, args, flags, fw, prec, modifier, type); + else + m_nconv = -1; +} + +void +printf_format_list::finish_conversion (const std::string& s, std::size_t& i, + int args, const std::string& flags, + int fw, int prec, char modifier, + char& type) +{ + switch (s[i]) + { + case 'd': case 'i': case 'o': case 'x': case 'X': + case 'u': case 'c': + if (modifier == 'L') + { + m_nconv = -1; + break; + } + goto fini; + + case 'f': case 'e': case 'E': case 'g': case 'G': + if (modifier == 'h' || modifier == 'l') + { + m_nconv = -1; + break; + } + goto fini; + + case 's': case 'p': case '%': + if (modifier != '\0') + { + m_nconv = -1; + break; + } + goto fini; + + fini: + + type = s[i]; + + m_buf << s[i++]; + + if (type != '%' || args != 0) + m_nconv++; + + if (type != '%') + args++; + + add_elt_to_list (args, flags, fw, prec, type, modifier); + + break; + + default: m_nconv = -1; - } - - void - printf_format_list::finish_conversion (const std::string& s, std::size_t& i, - int args, const std::string& flags, - int fw, int prec, char modifier, - char& type) - { - switch (s[i]) - { - case 'd': case 'i': case 'o': case 'x': case 'X': - case 'u': case 'c': - if (modifier == 'L') - { - m_nconv = -1; - break; - } - goto fini; - - case 'f': case 'e': case 'E': case 'g': case 'G': - if (modifier == 'h' || modifier == 'l') - { - m_nconv = -1; - break; - } - goto fini; - - case 's': case 'p': case '%': - if (modifier != '\0') - { - m_nconv = -1; - break; - } - goto fini; - - fini: - - type = s[i]; - - m_buf << s[i++]; - - if (type != '%' || args != 0) - m_nconv++; - - if (type != '%') - args++; - - add_elt_to_list (args, flags, fw, prec, type, modifier); - - break; - - default: - m_nconv = -1; - break; - } - } - - void - printf_format_list::printme (void) const - { - std::size_t n = m_fmt_elts.size (); - - for (std::size_t i = 0; i < n; i++) - { - printf_format_elt *elt = m_fmt_elts[i]; - - std::cerr + break; + } +} + +void +printf_format_list::printme (void) const +{ + std::size_t n = m_fmt_elts.size (); + + for (std::size_t i = 0; i < n; i++) + { + printf_format_elt *elt = m_fmt_elts[i]; + + std::cerr << "args: " << elt->args << "\n" << "flags: '" << elt->flags << "'\n" << "width: " << elt->fw << "\n" @@ -1176,3176 +1176,3182 @@ << "type: '" << elt->type << "'\n" << "modifier: '" << elt->modifier << "'\n" << "text: '" << undo_string_escapes (elt->text) << "'\n\n"; - } - } - - // Calculate x^n. Used for ...e+nn so that, for example, 1e2 is - // exactly 100 and 5e-1 is 1/2 - - static double - pown (double x, unsigned int n) - { - double retval = 1; - - for (unsigned int d = n; d; d >>= 1) - { - if (d & 1) - retval *= x; - x *= x; - } - - return retval; - } - - static Cell - init_inf_nan (void) - { - Cell retval (dim_vector (1, 2)); - - retval(0) = Cell (octave_value ("inf")); - retval(1) = Cell (octave_value ("nan")); - - return retval; - } - - // Delimited stream, optimized to read strings of characters separated - // by single-character delimiters. - // - // The reason behind this class is that octstream doesn't provide - // seek/tell, but the opportunity has been taken to optimise for the - // textscan workload. - // - // The function reads chunks into a 4kiB buffer, and marks where the - // last delimiter occurs. Reads up to this delimiter can be fast. - // After that last delimiter, the remaining text is moved to the front - // of the buffer and the buffer is refilled. This also allows cheap - // seek and tell operations within a "fast read" block. - - class - delimited_stream + } +} + +// Calculate x^n. Used for ...e+nn so that, for example, 1e2 is +// exactly 100 and 5e-1 is 1/2 + +static double +pown (double x, unsigned int n) +{ + double retval = 1; + + for (unsigned int d = n; d; d >>= 1) + { + if (d & 1) + retval *= x; + x *= x; + } + + return retval; +} + +static Cell +init_inf_nan (void) +{ + Cell retval (dim_vector (1, 2)); + + retval(0) = Cell (octave_value ("inf")); + retval(1) = Cell (octave_value ("nan")); + + return retval; +} + +// Delimited stream, optimized to read strings of characters separated +// by single-character delimiters. +// +// The reason behind this class is that octstream doesn't provide +// seek/tell, but the opportunity has been taken to optimise for the +// textscan workload. +// +// The function reads chunks into a 4kiB buffer, and marks where the +// last delimiter occurs. Reads up to this delimiter can be fast. +// After that last delimiter, the remaining text is moved to the front +// of the buffer and the buffer is refilled. This also allows cheap +// seek and tell operations within a "fast read" block. + +class +delimited_stream +{ +public: + + delimited_stream (std::istream& is, const std::string& delimiters, + int longest_lookahead, octave_idx_type bsize = 4096); + + delimited_stream (std::istream& is, const delimited_stream& ds); + + // No copying! + + delimited_stream (const delimited_stream&) = delete; + + delimited_stream& operator = (const delimited_stream&) = delete; + + ~delimited_stream (void); + + // Called when optimized sequence of get is finished. Ensures that + // there is a remaining delimiter in buf, or loads more data in. + void field_done (void) { - public: - - delimited_stream (std::istream& is, const std::string& delimiters, - int longest_lookahead, octave_idx_type bsize = 4096); - - delimited_stream (std::istream& is, const delimited_stream& ds); - - // No copying! - - delimited_stream (const delimited_stream&) = delete; - - delimited_stream& operator = (const delimited_stream&) = delete; - - ~delimited_stream (void); - - // Called when optimized sequence of get is finished. Ensures that - // there is a remaining delimiter in buf, or loads more data in. - void field_done (void) - { - if (m_idx >= m_last) - refresh_buf (); - } - - // Load new data into buffer, and set eob, last, idx. - // Return EOF at end of file, 0 otherwise. - int refresh_buf (bool initialize = false); - - // Get a character, relying on caller to call field_done if - // a delimiter has been reached. - int get (void) - { - if (m_delimited) - return eof () ? std::istream::traits_type::eof () : *m_idx++; - else - return get_undelim (); - } - - // Get a character, checking for underrun of the buffer. - int get_undelim (void); - - // Read character that will be got by the next get. - // FIXME: This will not set EOF if delimited stream is at EOF and a peek - // is attempted. This does *NOT* behave like C++ input stream. - // For a compatible peek function, use peek_undelim. See bug #56917. - int peek (void) - { return eof () ? std::istream::traits_type::eof () : *m_idx; } - - // Read character that will be got by the next get. - int peek_undelim (void); - - // Undo a 'get' or 'get_undelim'. It is the caller's responsibility - // to avoid overflow by calling putbacks only for a character got by - // get() or get_undelim(), with no intervening - // get, get_delim, field_done, refresh_buf, getline, read or seekg. - void putback (char /*ch*/ = 0) { if (! eof ()) --m_idx; } - - int getline (std::string& dest, char delim); - - // int skipline (char delim); - - char * read (char *buffer, int size, char* &new_start); - - // Return a position suitable to "seekg", valid only within this - // block between calls to field_done. - char * tellg (void) { return m_idx; } - - void seekg (char *old_idx) { m_idx = old_idx; } - - bool eof (void) - { - return (m_eob == m_buf + m_overlap && m_i_stream.eof ()) - || (m_flags & std::ios_base::eofbit); - } - - operator const void* (void) - { return (! eof () && ! m_flags) ? this : nullptr; } - - bool fail (void) { return m_flags & std::ios_base::failbit; } - - std::ios_base::iostate rdstate (void) { return m_flags; } - - void setstate (std::ios_base::iostate m) { m_flags = m_flags | m; } - - void clear (std::ios_base::iostate m - = (std::ios_base::eofbit & ~std::ios_base::eofbit)) - { - m_flags = m_flags & m; - } - - // Report if any characters have been consumed. - // (get, read, etc. not cancelled by putback or seekg) - - void progress_benchmark (void) { m_progress_marker = m_idx; } - - bool no_progress (void) { return m_progress_marker == m_idx; } - - // Number of characters remaining until end of stream if it is already - // buffered. int_max otherwise. - - std::ptrdiff_t remaining (void) - { - if (m_eob < m_buf + m_bufsize) - return m_eob - m_idx; - else - return std::numeric_limits::max (); - } - - private: - - // Number of characters to read from the file at once. - int m_bufsize; - - // Stream to read from. - std::istream& m_i_stream; - - // Temporary storage for a "chunk" of data. - char *m_buf; - - // Current read pointer. - char *m_idx; - - // Location of last delimiter in the buffer at buf (undefined if - // delimited is false). - char *m_last; - - // Position after last character in buffer. - char *m_eob; - - // Overlap with old content when refreshing buffer. - std::ptrdiff_t m_overlap; - - // True if there is delimiter in the buffer after idx. - bool m_delimited; - - // Longest lookahead required. - int m_longest; - - // Sequence of single-character delimiters. - const std::string m_delims; - - // Position of start of buf in original stream. - std::streampos m_buf_in_file; - - // Marker to see if a read consumes any characters. - char *m_progress_marker; - - std::ios_base::iostate m_flags; - }; - - // Create a delimited stream, reading from is, with delimiters delims, - // and allowing reading of up to tellg + longest_lookeahead. When is - // is at EOF, lookahead may be padded by ASCII nuls. - - delimited_stream::delimited_stream (std::istream& is, - const std::string& delimiters, - int longest_lookahead, - octave_idx_type bsize) - : m_bufsize (bsize), m_i_stream (is), m_longest (longest_lookahead), - m_delims (delimiters), - m_flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0 + if (m_idx >= m_last) + refresh_buf (); + } + + // Load new data into buffer, and set eob, last, idx. + // Return EOF at end of file, 0 otherwise. + int refresh_buf (bool initialize = false); + + // Get a character, relying on caller to call field_done if + // a delimiter has been reached. + int get (void) { - m_buf = new char[m_bufsize]; - m_eob = m_buf + m_bufsize; - m_idx = m_eob; // refresh_buf shouldn't try to copy old data - m_progress_marker = m_idx; - refresh_buf (true); // load the first batch of data + if (m_delimited) + return eof () ? std::istream::traits_type::eof () : *m_idx++; + else + return get_undelim (); } - // Used to create a stream from a strstream from data read from a dstr. - delimited_stream::delimited_stream (std::istream& is, - const delimited_stream& ds) - : delimited_stream (is, ds.m_delims, ds.m_longest, ds.m_bufsize) - { } - - delimited_stream::~delimited_stream (void) + // Get a character, checking for underrun of the buffer. + int get_undelim (void); + + // Read character that will be got by the next get. + // FIXME: This will not set EOF if delimited stream is at EOF and a peek + // is attempted. This does *NOT* behave like C++ input stream. + // For a compatible peek function, use peek_undelim. See bug #56917. + int peek (void) + { return eof () ? std::istream::traits_type::eof () : *m_idx; } + + // Read character that will be got by the next get. + int peek_undelim (void); + + // Undo a 'get' or 'get_undelim'. It is the caller's responsibility + // to avoid overflow by calling putbacks only for a character got by + // get() or get_undelim(), with no intervening + // get, get_delim, field_done, refresh_buf, getline, read or seekg. + void putback (char /*ch*/ = 0) { if (! eof ()) --m_idx; } + + int getline (std::string& dest, char delim); + + // int skipline (char delim); + + char * read (char *buffer, int size, char *&new_start); + + // Return a position suitable to "seekg", valid only within this + // block between calls to field_done. + char * tellg (void) { return m_idx; } + + void seekg (char *old_idx) { m_idx = old_idx; } + + bool eof (void) { - // Seek to the correct position in i_stream. - if (! eof ()) - { - m_i_stream.clear (); - m_i_stream.seekg (m_buf_in_file); - m_i_stream.read (m_buf, m_idx - m_buf - m_overlap); - } - - delete [] m_buf; + return (m_eob == m_buf + m_overlap && m_i_stream.eof ()) + || (m_flags & std::ios_base::eofbit); } - // Read a character from the buffer, refilling the buffer from the file - // if necessary. - - int - delimited_stream::get_undelim (void) + operator const void *(void) + { return (! eof () && ! m_flags) ? this : nullptr; } + + bool fail (void) { return m_flags & std::ios_base::failbit; } + + std::ios_base::iostate rdstate (void) { return m_flags; } + + void setstate (std::ios_base::iostate m) { m_flags = m_flags | m; } + + void clear (std::ios_base::iostate m + = (std::ios_base::eofbit & ~std::ios_base::eofbit)) { - int retval; - if (eof ()) - { - setstate (std::ios_base::failbit); - return std::istream::traits_type::eof (); - } - - if (m_idx < m_eob) - retval = *m_idx++; + m_flags = m_flags & m; + } + + // Report if any characters have been consumed. + // (get, read, etc. not cancelled by putback or seekg) + + void progress_benchmark (void) { m_progress_marker = m_idx; } + + bool no_progress (void) { return m_progress_marker == m_idx; } + + // Number of characters remaining until end of stream if it is already + // buffered. int_max otherwise. + + std::ptrdiff_t remaining (void) + { + if (m_eob < m_buf + m_bufsize) + return m_eob - m_idx; else - { - refresh_buf (); - - if (eof ()) - { - setstate (std::ios_base::eofbit); - retval = std::istream::traits_type::eof (); - } - else - retval = *m_idx++; - } - - if (m_idx >= m_last) - m_delimited = false; - - return retval; - } - - // Return the next character to be read without incrementing the - // pointer, refilling the buffer from the file if necessary. - - int - delimited_stream::peek_undelim (void) - { - int retval = get_undelim (); - putback (); - - return retval; - } - - // Copy remaining unprocessed data to the start of the buffer and load - // new data to fill it. Return EOF if the file is at EOF before - // reading any data and all of the data that has been read has been - // processed. - - int - delimited_stream::refresh_buf (bool initialize) - { - if (eof ()) - return std::istream::traits_type::eof (); - - int retval; - - if (m_eob < m_idx) - m_idx = m_eob; - - std::size_t old_remaining = m_eob - m_idx; - std::size_t old_overlap = 0; - - if (initialize || (m_idx - m_buf <= 0)) - m_overlap = 0; - else - { - old_overlap = m_overlap; - // Retain the last 25 bytes in the buffer. That should be more than enough - // to putback an entire double precision floating point number in decimal - // including 3 digit exponent and signs. Do we ever need to putback more - // than that? - m_overlap = 25; - // Assure we don't "underflow" with the overlap - m_overlap = std::min (m_overlap, m_idx - m_buf - 1); - } - - octave_quit (); // allow ctrl-C - - if (old_remaining + m_overlap > 0) - { - m_buf_in_file += (m_idx - old_overlap - m_buf); - std::memmove (m_buf, m_idx - m_overlap, m_overlap + old_remaining); - } - else - m_buf_in_file = m_i_stream.tellg (); // record for destructor - - // where original idx would have been - m_progress_marker -= m_idx - m_overlap - m_buf; - m_idx = m_buf + m_overlap; - - int gcount; // chars read - if (! m_i_stream.eof ()) - { - m_i_stream.read (m_buf + m_overlap + old_remaining, - m_bufsize - m_overlap - old_remaining); - gcount = m_i_stream.gcount (); - } - else - gcount = 0; - - m_eob = m_buf + m_overlap + old_remaining + gcount; - m_last = m_eob; - if (gcount == 0) - { - m_delimited = false; - - if (m_eob != m_buf + m_overlap) - // no more data in file, but still some to go - retval = 0; - else - // file and buffer are both done. - retval = std::istream::traits_type::eof (); - } - else - { - m_delimited = true; - - for (m_last = m_eob - m_longest; m_last - m_buf - m_overlap >= 0; - m_last--) - { - if (m_delims.find (*m_last) != std::string::npos) - break; - } - - if (m_last < m_buf + m_overlap) - m_delimited = false; - - retval = 0; - } - - // Ensure fast peek doesn't give valid char - if (retval == std::istream::traits_type::eof ()) - *m_idx = '\0'; // FIXME: check that no TreatAsEmpty etc starts w. \0? - - return retval; + return std::numeric_limits::max (); } - // Return a pointer to a block of data of size size, assuming that a - // sufficiently large buffer is available in buffer, if required. - // If called when delimited == true, and size is no greater than - // longest_lookahead then this will not call refresh_buf, so seekg - // still works. Otherwise, seekg may be invalidated. - - char * - delimited_stream::read (char *buffer, int size, char* &prior_tell) - { - char *retval; - - if (m_eob - m_idx >= size) - { - retval = m_idx; - m_idx += size; - if (m_idx > m_last) - m_delimited = false; - } - else - { - // If there was a tellg pointing to an earlier point than the current - // read position, try to keep it in the active buffer. - // In the current code, prior_tell==idx for each call, - // so this is not necessary, just a precaution. - - if (m_eob - prior_tell + size < m_bufsize) - { - octave_idx_type gap = m_idx - prior_tell; - m_idx = prior_tell; - refresh_buf (); - m_idx += gap; - } - else // can't keep the tellg in range. May skip some data. - { - refresh_buf (); - } - - prior_tell = m_buf; - - if (m_eob - m_idx > size) - { - retval = m_idx; - m_idx += size; - if (m_idx > m_last) - m_delimited = false; - } - else - { - if (size <= m_bufsize) // small read, but reached EOF - { - retval = m_idx; - memset (m_eob, 0, size + (m_idx - m_buf)); - m_idx += size; - } - else // Reading more than the whole buf; return it in buffer - { - retval = buffer; - // FIXME: read bufsize at a time - int i; - for (i = 0; i < size && ! eof (); i++) - *buffer++ = get_undelim (); - if (eof ()) - memset (buffer, 0, size - i); - } - } - } - - return retval; - } - - // Return in OUT an entire line, terminated by delim. On input, OUT - // must have length at least 1. - - int - delimited_stream::getline (std::string& out, char delim) - { - int len = out.length (); - int used = 0; - int ch; - while ((ch = get_undelim ()) != delim - && ch != std::istream::traits_type::eof ()) - { - out[used++] = ch; - if (used == len) - { - len <<= 1; - out.resize (len); - } - } - out.resize (used); - field_done (); - - return ch; - } - - // A single conversion specifier, such as %f or %c. - - class - textscan_format_elt - { - public: - - enum special_conversion - { - whitespace_conversion = 1, - literal_conversion = 2 - }; - - textscan_format_elt (const std::string& txt, int w = 0, int p = -1, - int bw = 0, bool dis = false, char typ = '\0', - const std::string& ch_class = std::string ()) - : text (txt), width (w), prec (p), bitwidth (bw), - char_class (ch_class), type (typ), discard (dis), - numeric (typ == 'd' || typ == 'u' || type == 'f' || type == 'n') - { } - - textscan_format_elt (const textscan_format_elt& e) - : text (e.text), width (e.width), prec (e.prec), - bitwidth (e.bitwidth), char_class (e.char_class), type (e.type), - discard (e.discard), numeric (e.numeric) - { } - - textscan_format_elt& operator = (const textscan_format_elt& e) - { - if (this != &e) +private: + + // Number of characters to read from the file at once. + int m_bufsize; + + // Stream to read from. + std::istream& m_i_stream; + + // Temporary storage for a "chunk" of data. + char *m_buf; + + // Current read pointer. + char *m_idx; + + // Location of last delimiter in the buffer at buf (undefined if + // delimited is false). + char *m_last; + + // Position after last character in buffer. + char *m_eob; + + // Overlap with old content when refreshing buffer. + std::ptrdiff_t m_overlap; + + // True if there is delimiter in the buffer after idx. + bool m_delimited; + + // Longest lookahead required. + int m_longest; + + // Sequence of single-character delimiters. + const std::string m_delims; + + // Position of start of buf in original stream. + std::streampos m_buf_in_file; + + // Marker to see if a read consumes any characters. + char *m_progress_marker; + + std::ios_base::iostate m_flags; +}; + +// Create a delimited stream, reading from is, with delimiters delims, +// and allowing reading of up to tellg + longest_lookeahead. When is +// is at EOF, lookahead may be padded by ASCII nuls. + +delimited_stream::delimited_stream (std::istream& is, + const std::string& delimiters, + int longest_lookahead, + octave_idx_type bsize) + : m_bufsize (bsize), m_i_stream (is), m_longest (longest_lookahead), + m_delims (delimiters), + m_flags (std::ios::failbit & ~std::ios::failbit) // can't cast 0 +{ + m_buf = new char[m_bufsize]; + m_eob = m_buf + m_bufsize; + m_idx = m_eob; // refresh_buf shouldn't try to copy old data + m_progress_marker = m_idx; + refresh_buf (true); // load the first batch of data +} + +// Used to create a stream from a strstream from data read from a dstr. +delimited_stream::delimited_stream (std::istream& is, + const delimited_stream& ds) + : delimited_stream (is, ds.m_delims, ds.m_longest, ds.m_bufsize) +{ } + +delimited_stream::~delimited_stream (void) +{ + // Seek to the correct position in i_stream. + if (! eof ()) + { + m_i_stream.clear (); + m_i_stream.seekg (m_buf_in_file); + m_i_stream.read (m_buf, m_idx - m_buf - m_overlap); + } + + delete [] m_buf; +} + +// Read a character from the buffer, refilling the buffer from the file +// if necessary. + +int +delimited_stream::get_undelim (void) +{ + int retval; + if (eof ()) + { + setstate (std::ios_base::failbit); + return std::istream::traits_type::eof (); + } + + if (m_idx < m_eob) + retval = *m_idx++; + else + { + refresh_buf (); + + if (eof ()) { - text = e.text; - width = e.width; - prec = e.prec; - bitwidth = e.bitwidth; - discard = e.discard; - type = e.type; - numeric = e.numeric; - char_class = e.char_class; + setstate (std::ios_base::eofbit); + retval = std::istream::traits_type::eof (); + } + else + retval = *m_idx++; + } + + if (m_idx >= m_last) + m_delimited = false; + + return retval; +} + +// Return the next character to be read without incrementing the +// pointer, refilling the buffer from the file if necessary. + +int +delimited_stream::peek_undelim (void) +{ + int retval = get_undelim (); + putback (); + + return retval; +} + +// Copy remaining unprocessed data to the start of the buffer and load +// new data to fill it. Return EOF if the file is at EOF before +// reading any data and all of the data that has been read has been +// processed. + +int +delimited_stream::refresh_buf (bool initialize) +{ + if (eof ()) + return std::istream::traits_type::eof (); + + int retval; + + if (m_eob < m_idx) + m_idx = m_eob; + + std::size_t old_remaining = m_eob - m_idx; + std::size_t old_overlap = 0; + + if (initialize || (m_idx - m_buf <= 0)) + m_overlap = 0; + else + { + old_overlap = m_overlap; + // Retain the last 25 bytes in the buffer. That should be more than enough + // to putback an entire double precision floating point number in decimal + // including 3 digit exponent and signs. Do we ever need to putback more + // than that? + m_overlap = 25; + // Assure we don't "underflow" with the overlap + m_overlap = std::min (m_overlap, m_idx - m_buf - 1); + } + + octave_quit (); // allow ctrl-C + + if (old_remaining + m_overlap > 0) + { + m_buf_in_file += (m_idx - old_overlap - m_buf); + std::memmove (m_buf, m_idx - m_overlap, m_overlap + old_remaining); + } + else + m_buf_in_file = m_i_stream.tellg (); // record for destructor + + // where original idx would have been + m_progress_marker -= m_idx - m_overlap - m_buf; + m_idx = m_buf + m_overlap; + + int gcount; // chars read + if (! m_i_stream.eof ()) + { + m_i_stream.read (m_buf + m_overlap + old_remaining, + m_bufsize - m_overlap - old_remaining); + gcount = m_i_stream.gcount (); + } + else + gcount = 0; + + m_eob = m_buf + m_overlap + old_remaining + gcount; + m_last = m_eob; + if (gcount == 0) + { + m_delimited = false; + + if (m_eob != m_buf + m_overlap) + // no more data in file, but still some to go + retval = 0; + else + // file and buffer are both done. + retval = std::istream::traits_type::eof (); + } + else + { + m_delimited = true; + + for (m_last = m_eob - m_longest; m_last - m_buf - m_overlap >= 0; + m_last--) + { + if (m_delims.find (*m_last) != std::string::npos) + break; + } + + if (m_last < m_buf + m_overlap) + m_delimited = false; + + retval = 0; + } + + // Ensure fast peek doesn't give valid char + if (retval == std::istream::traits_type::eof ()) + *m_idx = '\0'; // FIXME: check that no TreatAsEmpty etc starts w. \0? + + return retval; +} + +// Return a pointer to a block of data of size size, assuming that a +// sufficiently large buffer is available in buffer, if required. +// If called when delimited == true, and size is no greater than +// longest_lookahead then this will not call refresh_buf, so seekg +// still works. Otherwise, seekg may be invalidated. + +char * +delimited_stream::read (char *buffer, int size, char *&prior_tell) +{ + char *retval; + + if (m_eob - m_idx >= size) + { + retval = m_idx; + m_idx += size; + if (m_idx > m_last) + m_delimited = false; + } + else + { + // If there was a tellg pointing to an earlier point than the current + // read position, try to keep it in the active buffer. + // In the current code, prior_tell==idx for each call, + // so this is not necessary, just a precaution. + + if (m_eob - prior_tell + size < m_bufsize) + { + octave_idx_type gap = m_idx - prior_tell; + m_idx = prior_tell; + refresh_buf (); + m_idx += gap; + } + else // can't keep the tellg in range. May skip some data. + { + refresh_buf (); + } + + prior_tell = m_buf; + + if (m_eob - m_idx > size) + { + retval = m_idx; + m_idx += size; + if (m_idx > m_last) + m_delimited = false; + } + else + { + if (size <= m_bufsize) // small read, but reached EOF + { + retval = m_idx; + memset (m_eob, 0, size + (m_idx - m_buf)); + m_idx += size; + } + else // Reading more than the whole buf; return it in buffer + { + retval = buffer; + // FIXME: read bufsize at a time + int i; + for (i = 0; i < size && ! eof (); i++) + *buffer++ = get_undelim (); + if (eof ()) + memset (buffer, 0, size - i); + } + } + } + + return retval; +} + +// Return in OUT an entire line, terminated by delim. On input, OUT +// must have length at least 1. + +int +delimited_stream::getline (std::string& out, char delim) +{ + int len = out.length (); + int used = 0; + int ch; + while ((ch = get_undelim ()) != delim + && ch != std::istream::traits_type::eof ()) + { + out[used++] = ch; + if (used == len) + { + len <<= 1; + out.resize (len); } - - return *this; - } - - // The C-style format string. - std::string text; - - // The maximum field width. - unsigned int width; - - // The maximum number of digits to read after the decimal in a - // floating point conversion. - int prec; - - // The size of the result. For integers, bitwidth may be 8, 16, 34, - // or 64. For floating point values, bitwidth may be 32 or 64. - int bitwidth; - - // The class of characters in a '[' or '^' format. - std::string char_class; - - // Type of conversion - // -- 'd', 'u', 'f', 'n', 's', 'q', 'c', '%', 'C', 'D', '[' or '^'. - char type; - - // TRUE if we are not storing the result of this conversion. - bool discard; - - // TRUE if the type is 'd', 'u', 'f', 'n' - bool numeric; + } + out.resize (used); + field_done (); + + return ch; +} + +// A single conversion specifier, such as %f or %c. + +class +textscan_format_elt +{ +public: + + enum special_conversion + { + whitespace_conversion = 1, + literal_conversion = 2 }; - // The (parsed) sequence of format specifiers. - - class textscan; - - class - textscan_format_list + textscan_format_elt (const std::string& txt, int w = 0, int p = -1, + int bw = 0, bool dis = false, char typ = '\0', + const std::string& ch_class = std::string ()) + : text (txt), width (w), prec (p), bitwidth (bw), + char_class (ch_class), type (typ), discard (dis), + numeric (typ == 'd' || typ == 'u' || type == 'f' || type == 'n') + { } + + textscan_format_elt (const textscan_format_elt& e) + : text (e.text), width (e.width), prec (e.prec), + bitwidth (e.bitwidth), char_class (e.char_class), type (e.type), + discard (e.discard), numeric (e.numeric) + { } + + textscan_format_elt& operator = (const textscan_format_elt& e) + { + if (this != &e) + { + text = e.text; + width = e.width; + prec = e.prec; + bitwidth = e.bitwidth; + discard = e.discard; + type = e.type; + numeric = e.numeric; + char_class = e.char_class; + } + + return *this; + } + + // The C-style format string. + std::string text; + + // The maximum field width. + unsigned int width; + + // The maximum number of digits to read after the decimal in a + // floating point conversion. + int prec; + + // The size of the result. For integers, bitwidth may be 8, 16, 34, + // or 64. For floating point values, bitwidth may be 32 or 64. + int bitwidth; + + // The class of characters in a '[' or '^' format. + std::string char_class; + + // Type of conversion + // -- 'd', 'u', 'f', 'n', 's', 'q', 'c', '%', 'C', 'D', '[' or '^'. + char type; + + // TRUE if we are not storing the result of this conversion. + bool discard; + + // TRUE if the type is 'd', 'u', 'f', 'n' + bool numeric; +}; + +// The (parsed) sequence of format specifiers. + +class textscan; + +class +textscan_format_list +{ +public: + + textscan_format_list (const std::string& fmt = std::string (), + const std::string& who = "textscan"); + // No copying! + + textscan_format_list (const textscan_format_list&) = delete; + + textscan_format_list& operator = (const textscan_format_list&) = delete; + + ~textscan_format_list (void); + + octave_idx_type num_conversions (void) const { return m_nconv; } + + // The length can be different than the number of conversions. + // For example, "x %d y %d z" has 2 conversions but the length of + // the list is 3 because of the characters that appear after the + // last conversion. + + std::size_t numel (void) const { return m_fmt_elts.size (); } + + const textscan_format_elt * first (void) + { + m_curr_idx = 0; + return current (); + } + + const textscan_format_elt * current (void) const + { + return numel () > 0 ? m_fmt_elts[m_curr_idx] : nullptr; + } + + const textscan_format_elt * next (bool cycle = true) { - public: - - textscan_format_list (const std::string& fmt = std::string (), - const std::string& who = "textscan"); - // No copying! - - textscan_format_list (const textscan_format_list&) = delete; - - textscan_format_list& operator = (const textscan_format_list&) = delete; - - ~textscan_format_list (void); - - octave_idx_type num_conversions (void) const { return m_nconv; } - - // The length can be different than the number of conversions. - // For example, "x %d y %d z" has 2 conversions but the length of - // the list is 3 because of the characters that appear after the - // last conversion. - - std::size_t numel (void) const { return m_fmt_elts.size (); } - - const textscan_format_elt * first (void) - { - m_curr_idx = 0; - return current (); - } - - const textscan_format_elt * current (void) const - { - return numel () > 0 ? m_fmt_elts[m_curr_idx] : nullptr; - } - - const textscan_format_elt * next (bool cycle = true) - { - m_curr_idx++; - - if (m_curr_idx >= numel ()) - { - if (cycle) - m_curr_idx = 0; - else - return nullptr; - } - - return current (); - } - - void printme (void) const; - - bool ok (void) const { return (m_nconv >= 0); } - - operator const void* (void) const { return ok () ? this : nullptr; } - - // What function name should be shown when reporting errors. - std::string who; - - // True if number of %f to be set from data file. - bool set_from_first; - - // At least one conversion specifier is s,q,c, or [...]. - bool has_string; - - int read_first_row (delimited_stream& is, textscan& ts); - - std::list out_buf (void) const - { return (m_output_container); } - - private: - - void add_elt_to_list (unsigned int width, int prec, int bitwidth, - octave_value val_type, bool discard, - char type, - const std::string& char_class = std::string ()); - - void process_conversion (const std::string& s, std::size_t& i, - std::size_t n); - - std::string parse_char_class (const std::string& pattern) const; - - int finish_conversion (const std::string& s, std::size_t& i, std::size_t n, - unsigned int width, int prec, int bitwidth, - octave_value& val_type, - bool discard, char& type); - - //-------- - - // Number of conversions specified by this format string, or -1 if - // invalid conversions have been found. - octave_idx_type m_nconv; - - // Index to current element; - std::size_t m_curr_idx; - - // List of format elements. - std::deque m_fmt_elts; - - // list holding column arrays of types specified by conversions - std::list m_output_container; - - // Temporary buffer. - std::ostringstream m_buf; - - }; - - // Main class to implement textscan. Read data and parse it - // according to a format. - // - // The calling sequence is - // - // textscan scanner (); - // scanner.scan (...); - - class - OCTINTERP_API - textscan - { - public: - - textscan (const std::string& who_arg = "textscan", - const std::string& encoding = "utf-8"); - - // No copying! - - textscan (const textscan&) = delete; - - textscan& operator = (const textscan&) = delete; - - ~textscan (void) = default; - - octave_value scan (std::istream& isp, const std::string& fmt, - octave_idx_type ntimes, - const octave_value_list& options, - octave_idx_type& read_count); - - private: - - friend class textscan_format_list; - - octave_value do_scan (std::istream& isp, textscan_format_list& fmt_list, - octave_idx_type ntimes); - - void parse_options (const octave_value_list& args, - textscan_format_list& fmt_list); - - int read_format_once (delimited_stream& isp, textscan_format_list& fmt_list, - std::list& retval, - Array row, int& done_after); - - void scan_one (delimited_stream& is, const textscan_format_elt& fmt, - octave_value& ov, Array row); - - // Methods to process a particular conversion specifier. - double read_double (delimited_stream& is, - const textscan_format_elt& fmt) const; - - void scan_complex (delimited_stream& is, const textscan_format_elt& fmt, - Complex& val) const; - - int scan_bracket (delimited_stream& is, const std::string& pattern, - std::string& val) const; - - int scan_caret (delimited_stream& is, const std::string& pattern, + m_curr_idx++; + + if (m_curr_idx >= numel ()) + { + if (cycle) + m_curr_idx = 0; + else + return nullptr; + } + + return current (); + } + + void printme (void) const; + + bool ok (void) const { return (m_nconv >= 0); } + + operator const void *(void) const { return ok () ? this : nullptr; } + + // What function name should be shown when reporting errors. + std::string who; + + // True if number of %f to be set from data file. + bool set_from_first; + + // At least one conversion specifier is s,q,c, or [...]. + bool has_string; + + int read_first_row (delimited_stream& is, textscan& ts); + + std::list out_buf (void) const + { return (m_output_container); } + +private: + + void add_elt_to_list (unsigned int width, int prec, int bitwidth, + octave_value val_type, bool discard, + char type, + const std::string& char_class = std::string ()); + + void process_conversion (const std::string& s, std::size_t& i, + std::size_t n); + + std::string parse_char_class (const std::string& pattern) const; + + int finish_conversion (const std::string& s, std::size_t& i, std::size_t n, + unsigned int width, int prec, int bitwidth, + octave_value& val_type, + bool discard, char& type); + + //-------- + + // Number of conversions specified by this format string, or -1 if + // invalid conversions have been found. + octave_idx_type m_nconv; + + // Index to current element; + std::size_t m_curr_idx; + + // List of format elements. + std::deque m_fmt_elts; + + // list holding column arrays of types specified by conversions + std::list m_output_container; + + // Temporary buffer. + std::ostringstream m_buf; + +}; + +// Main class to implement textscan. Read data and parse it +// according to a format. +// +// The calling sequence is +// +// textscan scanner (); +// scanner.scan (...); + +class +OCTINTERP_API +textscan +{ +public: + + textscan (const std::string& who_arg = "textscan", + const std::string& encoding = "utf-8"); + + // No copying! + + textscan (const textscan&) = delete; + + textscan& operator = (const textscan&) = delete; + + ~textscan (void) = default; + + octave_value scan (std::istream& isp, const std::string& fmt, + octave_idx_type ntimes, + const octave_value_list& options, + octave_idx_type& read_count); + +private: + + friend class textscan_format_list; + + octave_value do_scan (std::istream& isp, textscan_format_list& fmt_list, + octave_idx_type ntimes); + + void parse_options (const octave_value_list& args, + textscan_format_list& fmt_list); + + int read_format_once (delimited_stream& isp, textscan_format_list& fmt_list, + std::list& retval, + Array row, int& done_after); + + void scan_one (delimited_stream& is, const textscan_format_elt& fmt, + octave_value& ov, Array row); + + // Methods to process a particular conversion specifier. + double read_double (delimited_stream& is, + const textscan_format_elt& fmt) const; + + void scan_complex (delimited_stream& is, const textscan_format_elt& fmt, + Complex& val) const; + + int scan_bracket (delimited_stream& is, const std::string& pattern, + std::string& val) const; + + int scan_caret (delimited_stream& is, const std::string& pattern, + std::string& val) const; + + void scan_string (delimited_stream& is, const textscan_format_elt& fmt, std::string& val) const; - void scan_string (delimited_stream& is, const textscan_format_elt& fmt, - std::string& val) const; - - void scan_cstring (delimited_stream& is, const textscan_format_elt& fmt, - std::string& val) const; - - void scan_qstring (delimited_stream& is, const textscan_format_elt& fmt, - std::string& val); - - // Helper methods. - std::string read_until (delimited_stream& is, const Cell& delimiters, - const std::string& ends) const; - - int lookahead (delimited_stream& is, const Cell& targets, int max_len, - bool case_sensitive = true) const; - - bool match_literal (delimited_stream& isp, const textscan_format_elt& elem); - - int skip_whitespace (delimited_stream& is, bool EOLstop = true); - - int skip_delim (delimited_stream& is); - - bool is_delim (unsigned char ch) const - { - return ((m_delim_table.empty () - && (isspace (ch) || ch == m_eol1 || ch == m_eol2)) - || m_delim_table[ch] != '\0'); - } - - bool isspace (unsigned int ch) const - { return m_whitespace_table[ch & 0xff]; } - - // True if the only delimiter is whitespace. - bool whitespace_delim (void) const { return m_delim_table.empty (); } - - //-------- - - // What function name should be shown when reporting errors. - std::string m_who; - - std::string m_encoding; - - std::string m_buf; - - // Three cases for delim_table and delim_list - // 1. delim_table empty, delim_list empty: whitespace delimiters - // 2. delim_table = look-up table of delim chars, delim_list empty. - // 3. delim_table non-empty, delim_list = Cell array of delim strings - - std::string m_whitespace_table; - - // delim_table[i] == '\0' if i is not a delimiter. - std::string m_delim_table; - - // String of delimiter characters. - std::string m_delims; - - Cell m_comment_style; - - // How far ahead to look to detect an open comment. - int m_comment_len; - - // First character of open comment. - int m_comment_char; - - octave_idx_type m_buffer_size; - - std::string m_date_locale; - - // 'inf' and 'nan' for formatted_double. - Cell m_inf_nan; - - // Array of strings of delimiters. - Cell m_delim_list; - - // Longest delimiter. - int m_delim_len; - - octave_value m_empty_value; - std::string m_exp_chars; - int m_header_lines; - Cell m_treat_as_empty; - - // Longest string to treat as "N/A". - int m_treat_as_empty_len; - - std::string m_whitespace; - - short m_eol1; - short m_eol2; - short m_return_on_error; - - bool m_collect_output; - bool multiple_delims_as_one; - bool m_default_exp; - - octave_idx_type m_lines; - }; - - textscan_format_list::textscan_format_list (const std::string& s, - const std::string& who_arg) - : who (who_arg), set_from_first (false), has_string (false), - m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf () + void scan_cstring (delimited_stream& is, const textscan_format_elt& fmt, + std::string& val) const; + + void scan_qstring (delimited_stream& is, const textscan_format_elt& fmt, + std::string& val); + + // Helper methods. + std::string read_until (delimited_stream& is, const Cell& delimiters, + const std::string& ends) const; + + int lookahead (delimited_stream& is, const Cell& targets, int max_len, + bool case_sensitive = true) const; + + bool match_literal (delimited_stream& isp, const textscan_format_elt& elem); + + int skip_whitespace (delimited_stream& is, bool EOLstop = true); + + int skip_delim (delimited_stream& is); + + bool is_delim (unsigned char ch) const { - std::size_t n = s.length (); - - std::size_t i = 0; - - unsigned int width = -1; // Unspecified width = max (except %c) - int prec = -1; - int bitwidth = 0; - bool discard = false; - char type = '\0'; - - bool have_more = true; - - if (s.empty ()) - { - m_buf.clear (); - m_buf.str (""); - - m_buf << "%f"; - - bitwidth = 64; - type = 'f'; - add_elt_to_list (width, prec, bitwidth, octave_value (NDArray ()), - discard, type); - have_more = false; - set_from_first = true; - m_nconv = 1; - } - else - { - set_from_first = false; - - while (i < n) + return ((m_delim_table.empty () + && (isspace (ch) || ch == m_eol1 || ch == m_eol2)) + || m_delim_table[ch] != '\0'); + } + + bool isspace (unsigned int ch) const + { return m_whitespace_table[ch & 0xff]; } + + // True if the only delimiter is whitespace. + bool whitespace_delim (void) const { return m_delim_table.empty (); } + + //-------- + + // What function name should be shown when reporting errors. + std::string m_who; + + std::string m_encoding; + + std::string m_buf; + + // Three cases for delim_table and delim_list + // 1. delim_table empty, delim_list empty: whitespace delimiters + // 2. delim_table = look-up table of delim chars, delim_list empty. + // 3. delim_table non-empty, delim_list = Cell array of delim strings + + std::string m_whitespace_table; + + // delim_table[i] == '\0' if i is not a delimiter. + std::string m_delim_table; + + // String of delimiter characters. + std::string m_delims; + + Cell m_comment_style; + + // How far ahead to look to detect an open comment. + int m_comment_len; + + // First character of open comment. + int m_comment_char; + + octave_idx_type m_buffer_size; + + std::string m_date_locale; + + // 'inf' and 'nan' for formatted_double. + Cell m_inf_nan; + + // Array of strings of delimiters. + Cell m_delim_list; + + // Longest delimiter. + int m_delim_len; + + octave_value m_empty_value; + std::string m_exp_chars; + int m_header_lines; + Cell m_treat_as_empty; + + // Longest string to treat as "N/A". + int m_treat_as_empty_len; + + std::string m_whitespace; + + short m_eol1; + short m_eol2; + short m_return_on_error; + + bool m_collect_output; + bool multiple_delims_as_one; + bool m_default_exp; + + octave_idx_type m_lines; +}; + +textscan_format_list::textscan_format_list (const std::string& s, + const std::string& who_arg) + : who (who_arg), set_from_first (false), has_string (false), + m_nconv (0), m_curr_idx (0), m_fmt_elts (), m_buf () +{ + std::size_t n = s.length (); + + std::size_t i = 0; + + unsigned int width = -1; // Unspecified width = max (except %c) + int prec = -1; + int bitwidth = 0; + bool discard = false; + char type = '\0'; + + bool have_more = true; + + if (s.empty ()) + { + m_buf.clear (); + m_buf.str (""); + + m_buf << "%f"; + + bitwidth = 64; + type = 'f'; + add_elt_to_list (width, prec, bitwidth, octave_value (NDArray ()), + discard, type); + have_more = false; + set_from_first = true; + m_nconv = 1; + } + else + { + set_from_first = false; + + while (i < n) + { + have_more = true; + + if (s[i] == '%' && (i+1 == n || s[i+1] != '%')) + { + // Process percent-escape conversion type. + + process_conversion (s, i, n); + + // If there is nothing in the buffer, then add_elt_to_list + // must have just been called, so we are already done with + // the current element and we don't need to call + // add_elt_to_list if this is our last trip through the + // loop. + + have_more = (m_buf.tellp () != 0); + } + else if (isspace (s[i])) + { + while (++i < n && isspace (s[i])) + /* skip whitespace */; + + have_more = false; + } + else + { + type = textscan_format_elt::literal_conversion; + + width = 0; + prec = -1; + bitwidth = 0; + discard = true; + + while (i < n && ! isspace (s[i]) + && (s[i] != '%' || (i+1 < n && s[i+1] == '%'))) + { + if (s[i] == '%') // if double %, skip one + i++; + m_buf << s[i++]; + width++; + } + + add_elt_to_list (width, prec, bitwidth, octave_value (), + discard, type); + + have_more = false; + } + + if (m_nconv < 0) + { + have_more = false; + break; + } + } + } + + if (have_more) + add_elt_to_list (width, prec, bitwidth, octave_value (), discard, type); + + m_buf.clear (); + m_buf.str (""); +} + +textscan_format_list::~textscan_format_list (void) +{ + std::size_t n = numel (); + + for (std::size_t i = 0; i < n; i++) + { + textscan_format_elt *elt = m_fmt_elts[i]; + delete elt; + } +} + +void +textscan_format_list::add_elt_to_list (unsigned int width, int prec, + int bitwidth, octave_value val_type, + bool discard, char type, + const std::string& char_class) +{ + std::string text = m_buf.str (); + + if (! text.empty ()) + { + textscan_format_elt *elt + = new textscan_format_elt (text, width, prec, bitwidth, discard, + type, char_class); + + if (! discard) + m_output_container.push_back (val_type); + + m_fmt_elts.push_back (elt); + } + + m_buf.clear (); + m_buf.str (""); +} + +void +textscan_format_list::process_conversion (const std::string& s, + std::size_t& i, std::size_t n) +{ + unsigned width = 0; + int prec = -1; + int bitwidth = 0; + bool discard = false; + octave_value val_type; + char type = '\0'; + + m_buf << s[i++]; + + bool have_width = false; + + while (i < n) + { + switch (s[i]) + { + case '*': + if (discard) + m_nconv = -1; + else + { + discard = true; + m_buf << s[i++]; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (have_width) + m_nconv = -1; + else + { + char c = s[i++]; + width = width * 10 + c - '0'; + have_width = true; + m_buf << c; + while (i < n && isdigit (s[i])) + { + c = s[i++]; + width = width * 10 + c - '0'; + m_buf << c; + } + + if (i < n && s[i] == '.') + { + m_buf << s[i++]; + prec = 0; + while (i < n && isdigit (s[i])) + { + c = s[i++]; + prec = prec * 10 + c - '0'; + m_buf << c; + } + } + } + break; + + case 'd': case 'u': { - have_more = true; - - if (s[i] == '%' && (i+1 == n || s[i+1] != '%')) - { - // Process percent-escape conversion type. - - process_conversion (s, i, n); - - // If there is nothing in the buffer, then add_elt_to_list - // must have just been called, so we are already done with - // the current element and we don't need to call - // add_elt_to_list if this is our last trip through the - // loop. - - have_more = (m_buf.tellp () != 0); - } - else if (isspace (s[i])) - { - while (++i < n && isspace (s[i])) - /* skip whitespace */; - - have_more = false; - } - else - { - type = textscan_format_elt::literal_conversion; - - width = 0; - prec = -1; - bitwidth = 0; - discard = true; - - while (i < n && ! isspace (s[i]) - && (s[i] != '%' || (i+1 < n && s[i+1] == '%'))) - { - if (s[i] == '%') // if double %, skip one - i++; - m_buf << s[i++]; - width++; - } - - add_elt_to_list (width, prec, bitwidth, octave_value (), - discard, type); - - have_more = false; - } - - if (m_nconv < 0) - { - have_more = false; - break; - } - } - } - - if (have_more) - add_elt_to_list (width, prec, bitwidth, octave_value (), discard, type); - - m_buf.clear (); - m_buf.str (""); - } - - textscan_format_list::~textscan_format_list (void) - { - std::size_t n = numel (); - - for (std::size_t i = 0; i < n; i++) - { - textscan_format_elt *elt = m_fmt_elts[i]; - delete elt; - } - } - - void - textscan_format_list::add_elt_to_list (unsigned int width, int prec, - int bitwidth, octave_value val_type, - bool discard, char type, - const std::string& char_class) - { - std::string text = m_buf.str (); - - if (! text.empty ()) - { - textscan_format_elt *elt - = new textscan_format_elt (text, width, prec, bitwidth, discard, - type, char_class); - - if (! discard) - m_output_container.push_back (val_type); - - m_fmt_elts.push_back (elt); - } - - m_buf.clear (); - m_buf.str (""); - } - - void - textscan_format_list::process_conversion (const std::string& s, - std::size_t& i, std::size_t n) - { - unsigned width = 0; - int prec = -1; - int bitwidth = 0; - bool discard = false; - octave_value val_type; - char type = '\0'; - - m_buf << s[i++]; - - bool have_width = false; - - while (i < n) - { - switch (s[i]) - { - case '*': - if (discard) - m_nconv = -1; - else - { - discard = true; - m_buf << s[i++]; - } - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (have_width) - m_nconv = -1; - else - { - char c = s[i++]; - width = width * 10 + c - '0'; - have_width = true; - m_buf << c; - while (i < n && isdigit (s[i])) - { - c = s[i++]; - width = width * 10 + c - '0'; - m_buf << c; - } - - if (i < n && s[i] == '.') - { - m_buf << s[i++]; - prec = 0; - while (i < n && isdigit (s[i])) - { - c = s[i++]; - prec = prec * 10 + c - '0'; - m_buf << c; - } - } - } - break; - - case 'd': case 'u': - { - bool done = true; - m_buf << (type = s[i++]); - if (i < n) - { - if (s[i] == '8') - { - bitwidth = 8; - if (type == 'd') - val_type = octave_value (int8NDArray ()); - else - val_type = octave_value (uint8NDArray ()); - m_buf << s[i++]; - } - else if (s[i] == '1' && i+1 < n && s[i+1] == '6') - { - bitwidth = 16; - if (type == 'd') - val_type = octave_value (int16NDArray ()); - else - val_type = octave_value (uint16NDArray ()); - m_buf << s[i++]; - m_buf << s[i++]; - } - else if (s[i] == '3' && i+1 < n && s[i+1] == '2') - { - done = false; // use default size below - m_buf << s[i++]; - m_buf << s[i++]; - } - else if (s[i] == '6' && i+1 < n && s[i+1] == '4') - { - bitwidth = 64; - if (type == 'd') - val_type = octave_value (int64NDArray ()); - else - val_type = octave_value (uint64NDArray ()); - m_buf << s[i++]; - m_buf << s[i++]; - } - else - done = false; - } - else - done = false; - - if (! done) - { - bitwidth = 32; - if (type == 'd') - val_type = octave_value (int32NDArray ()); - else - val_type = octave_value (uint32NDArray ()); - } - goto fini; - } - - case 'f': + bool done = true; m_buf << (type = s[i++]); - bitwidth = 64; if (i < n) { - if (s[i] == '3' && i+1 < n && s[i+1] == '2') + if (s[i] == '8') + { + bitwidth = 8; + if (type == 'd') + val_type = octave_value (int8NDArray ()); + else + val_type = octave_value (uint8NDArray ()); + m_buf << s[i++]; + } + else if (s[i] == '1' && i+1 < n && s[i+1] == '6') { - bitwidth = 32; - val_type = octave_value (FloatNDArray ()); + bitwidth = 16; + if (type == 'd') + val_type = octave_value (int16NDArray ()); + else + val_type = octave_value (uint16NDArray ()); + m_buf << s[i++]; + m_buf << s[i++]; + } + else if (s[i] == '3' && i+1 < n && s[i+1] == '2') + { + done = false; // use default size below m_buf << s[i++]; m_buf << s[i++]; } else if (s[i] == '6' && i+1 < n && s[i+1] == '4') { - val_type = octave_value (NDArray ()); + bitwidth = 64; + if (type == 'd') + val_type = octave_value (int64NDArray ()); + else + val_type = octave_value (uint64NDArray ()); m_buf << s[i++]; m_buf << s[i++]; } else - val_type = octave_value (NDArray ()); + done = false; } else - val_type = octave_value (NDArray ()); - goto fini; - - case 'n': - m_buf << (type = s[i++]); - bitwidth = 64; - val_type = octave_value (NDArray ()); - goto fini; - - case 's': case 'q': case '[': case 'c': - if (! discard) - val_type = octave_value (Cell ()); - m_buf << (type = s[i++]); - has_string = true; + done = false; + + if (! done) + { + bitwidth = 32; + if (type == 'd') + val_type = octave_value (int32NDArray ()); + else + val_type = octave_value (uint32NDArray ()); + } goto fini; - - fini: - { - if (! have_width) - { - if (type == 'c') // %c defaults to one character - width = 1; - else - width = static_cast (-1); // others: unlimited - } - - if (finish_conversion (s, i, n, width, prec, bitwidth, val_type, - discard, type) == 0) - return; - } - break; - - default: - error ("%s: '%%%c' is not a valid format specifier", - who.c_str (), s[i]); } - if (m_nconv < 0) - break; - } - - m_nconv = -1; - } - - // Parse [...] and [^...] - // - // Matlab does not expand expressions like A-Z, but they are useful, and - // so we parse them "carefully". We treat '-' as a usual character - // unless both start and end characters are from the same class (upper - // case, lower case, numeric), or this is not the first '-' in the - // pattern. - // - // Keep both a running list of characters and a mask of which chars have - // occurred. The first is efficient for patterns with few characters. - // The latter is efficient for [^...] patterns. - - std::string - textscan_format_list::parse_char_class (const std::string& pattern) const - { - int len = pattern.length (); - if (len == 0) - return ""; - - std::string retval (256, '\0'); - std::string mask (256, '\0'); // number of times chr has been seen - - int in = 0, out = 0; - unsigned char ch, prev = 0; - bool flip = false; - - ch = pattern[in]; - if (ch == '^') - { - in++; - flip = true; - } - mask[pattern[in]] = '\1'; - retval[out++] = pattern[in++]; // even copy ']' if it is first - - bool prev_was_range = false; // disallow "a-m-z" as a pattern - bool prev_prev_was_range = false; - for (; in < len; in++) - { - bool was_range = false; - ch = pattern[in]; - if (ch == ']') - break; - - if (prev == '-' && in > 1 && isalnum (ch) && ! prev_prev_was_range) + case 'f': + m_buf << (type = s[i++]); + bitwidth = 64; + if (i < n) + { + if (s[i] == '3' && i+1 < n && s[i+1] == '2') + { + bitwidth = 32; + val_type = octave_value (FloatNDArray ()); + m_buf << s[i++]; + m_buf << s[i++]; + } + else if (s[i] == '6' && i+1 < n && s[i+1] == '4') + { + val_type = octave_value (NDArray ()); + m_buf << s[i++]; + m_buf << s[i++]; + } + else + val_type = octave_value (NDArray ()); + } + else + val_type = octave_value (NDArray ()); + goto fini; + + case 'n': + m_buf << (type = s[i++]); + bitwidth = 64; + val_type = octave_value (NDArray ()); + goto fini; + + case 's': case 'q': case '[': case 'c': + if (! discard) + val_type = octave_value (Cell ()); + m_buf << (type = s[i++]); + has_string = true; + goto fini; + + fini: { - unsigned char start_of_range = pattern[in-2]; - if (start_of_range < ch - && ((isupper (ch) && isupper (start_of_range)) - || (islower (ch) && islower (start_of_range)) - || (isdigit (ch) && isdigit (start_of_range)) - || mask['-'] > 1)) // not the first '-' + if (! have_width) { - was_range = true; - out--; - mask['-']--; - for (int i = start_of_range; i <= ch; i++) - { - if (mask[i] == '\0') - { - mask[i] = '\1'; - retval[out++] = i; - } - } + if (type == 'c') // %c defaults to one character + width = 1; + else + width = static_cast (-1); // others: unlimited } + + if (finish_conversion (s, i, n, width, prec, bitwidth, val_type, + discard, type) == 0) + return; } - if (! was_range) - { - if (mask[ch]++ == 0) - retval[out++] = ch; - else if (ch != '-') - warning_with_id ("Octave:textscan-pattern", - "%s: [...] contains two '%c's", - who.c_str (), ch); - - if (prev == '-' && mask['-'] >= 2) - warning_with_id - ("Octave:textscan-pattern", - "%s: [...] contains two '-'s outside range expressions", - who.c_str ()); - } - prev = ch; - prev_prev_was_range = prev_was_range; - prev_was_range = was_range; - } - - if (flip) // [^...] - { - out = 0; - for (int i = 0; i < 256; i++) - if (! mask[i]) - retval[out++] = i; - } - - retval.resize (out); - - return retval; - } - - int - textscan_format_list::finish_conversion (const std::string& s, std::size_t& i, - std::size_t n, unsigned int width, - int prec, int bitwidth, - octave_value& val_type, bool discard, - char& type) - { - int retval = 0; - - std::string char_class; - - std::size_t beg_idx = std::string::npos; - std::size_t end_idx = std::string::npos; - - if (type != '%') - { - m_nconv++; - if (type == '[') - { - if (i < n) - { - beg_idx = i; - - if (s[i] == '^') - { - type = '^'; - m_buf << s[i++]; - - if (i < n) - { - beg_idx = i; - - if (s[i] == ']') - m_buf << s[i++]; - } - } - else if (s[i] == ']') + break; + + default: + error ("%s: '%%%c' is not a valid format specifier", + who.c_str (), s[i]); + } + + if (m_nconv < 0) + break; + } + + m_nconv = -1; +} + +// Parse [...] and [^...] +// +// Matlab does not expand expressions like A-Z, but they are useful, and +// so we parse them "carefully". We treat '-' as a usual character +// unless both start and end characters are from the same class (upper +// case, lower case, numeric), or this is not the first '-' in the +// pattern. +// +// Keep both a running list of characters and a mask of which chars have +// occurred. The first is efficient for patterns with few characters. +// The latter is efficient for [^...] patterns. + +std::string +textscan_format_list::parse_char_class (const std::string& pattern) const +{ + int len = pattern.length (); + if (len == 0) + return ""; + + std::string retval (256, '\0'); + std::string mask (256, '\0'); // number of times chr has been seen + + int in = 0, out = 0; + unsigned char ch, prev = 0; + bool flip = false; + + ch = pattern[in]; + if (ch == '^') + { + in++; + flip = true; + } + mask[pattern[in]] = '\1'; + retval[out++] = pattern[in++]; // even copy ']' if it is first + + bool prev_was_range = false; // disallow "a-m-z" as a pattern + bool prev_prev_was_range = false; + for (; in < len; in++) + { + bool was_range = false; + ch = pattern[in]; + if (ch == ']') + break; + + if (prev == '-' && in > 1 && isalnum (ch) && ! prev_prev_was_range) + { + unsigned char start_of_range = pattern[in-2]; + if (start_of_range < ch + && ((isupper (ch) && isupper (start_of_range)) + || (islower (ch) && islower (start_of_range)) + || (isdigit (ch) && isdigit (start_of_range)) + || mask['-'] > 1)) // not the first '-' + { + was_range = true; + out--; + mask['-']--; + for (int i = start_of_range; i <= ch; i++) + { + if (mask[i] == '\0') + { + mask[i] = '\1'; + retval[out++] = i; + } + } + } + } + if (! was_range) + { + if (mask[ch]++ == 0) + retval[out++] = ch; + else if (ch != '-') + warning_with_id ("Octave:textscan-pattern", + "%s: [...] contains two '%c's", + who.c_str (), ch); + + if (prev == '-' && mask['-'] >= 2) + warning_with_id + ("Octave:textscan-pattern", + "%s: [...] contains two '-'s outside range expressions", + who.c_str ()); + } + prev = ch; + prev_prev_was_range = prev_was_range; + prev_was_range = was_range; + } + + if (flip) // [^...] + { + out = 0; + for (int i = 0; i < 256; i++) + if (! mask[i]) + retval[out++] = i; + } + + retval.resize (out); + + return retval; +} + +int +textscan_format_list::finish_conversion (const std::string& s, std::size_t& i, + std::size_t n, unsigned int width, + int prec, int bitwidth, + octave_value& val_type, bool discard, + char& type) +{ + int retval = 0; + + std::string char_class; + + std::size_t beg_idx = std::string::npos; + std::size_t end_idx = std::string::npos; + + if (type != '%') + { + m_nconv++; + if (type == '[') + { + if (i < n) + { + beg_idx = i; + + if (s[i] == '^') + { + type = '^'; m_buf << s[i++]; - } - - while (i < n && s[i] != ']') - m_buf << s[i++]; - - if (i < n && s[i] == ']') - { - end_idx = i-1; + + if (i < n) + { + beg_idx = i; + + if (s[i] == ']') + m_buf << s[i++]; + } + } + else if (s[i] == ']') m_buf << s[i++]; - } - - if (s[i-1] != ']') - retval = m_nconv = -1; - } - } - - if (m_nconv >= 0) - { - if (beg_idx != std::string::npos && end_idx != std::string::npos) - char_class = parse_char_class (s.substr (beg_idx, - end_idx - beg_idx + 1)); - - add_elt_to_list (width, prec, bitwidth, val_type, discard, type, - char_class); - } - - return retval; - } - - void - textscan_format_list::printme (void) const - { - std::size_t n = numel (); - - for (std::size_t i = 0; i < n; i++) - { - textscan_format_elt *elt = m_fmt_elts[i]; - - std::cerr + } + + while (i < n && s[i] != ']') + m_buf << s[i++]; + + if (i < n && s[i] == ']') + { + end_idx = i-1; + m_buf << s[i++]; + } + + if (s[i-1] != ']') + retval = m_nconv = -1; + } + } + + if (m_nconv >= 0) + { + if (beg_idx != std::string::npos && end_idx != std::string::npos) + char_class = parse_char_class (s.substr (beg_idx, + end_idx - beg_idx + 1)); + + add_elt_to_list (width, prec, bitwidth, val_type, discard, type, + char_class); + } + + return retval; +} + +void +textscan_format_list::printme (void) const +{ + std::size_t n = numel (); + + for (std::size_t i = 0; i < n; i++) + { + textscan_format_elt *elt = m_fmt_elts[i]; + + std::cerr << "width: " << elt->width << "\n" << "digits " << elt->prec << "\n" << "bitwidth: " << elt->bitwidth << "\n" << "discard: " << elt->discard << "\n" << "type: "; - if (elt->type == textscan_format_elt::literal_conversion) - std::cerr << "literal text\n"; - else if (elt->type == textscan_format_elt::whitespace_conversion) - std::cerr << "whitespace\n"; - else - std::cerr << elt->type << "\n"; - - std::cerr + if (elt->type == textscan_format_elt::literal_conversion) + std::cerr << "literal text\n"; + else if (elt->type == textscan_format_elt::whitespace_conversion) + std::cerr << "whitespace\n"; + else + std::cerr << elt->type << "\n"; + + std::cerr << "char_class: '" << undo_string_escapes (elt->char_class) << "'\n" << "text: '" << undo_string_escapes (elt->text) << "'\n\n"; - } - } - - // If FORMAT is explicitly "", it is assumed to be "%f" repeated enough - // times to read the first row of the file. Set it now. - - int - textscan_format_list::read_first_row (delimited_stream& is, textscan& ts) - { - // Read first line and strip end-of-line, which may be two characters - std::string first_line (20, ' '); - - is.getline (first_line, static_cast (ts.m_eol2)); - - if (! first_line.empty () && first_line.back () == ts.m_eol1) - first_line.pop_back (); - - std::istringstream strstr (first_line); - delimited_stream ds (strstr, is); - - dim_vector dv (1, 1); // initial size of each output_container - Complex val; - octave_value val_type; - m_nconv = 0; - int max_empty = 1000; // failsafe, if ds fails but not with eof - int retval = 0; - - // read line, creating output_container as we go - while (! ds.eof ()) - { - bool already_skipped_delim = false; - ts.skip_whitespace (ds, false); - ds.progress_benchmark (); - ts.scan_complex (ds, *m_fmt_elts[0], val); - if (ds.fail ()) - { - ds.clear (ds.rdstate () & ~std::ios::failbit); - - if (ds.eof ()) - break; - - // Unless this was a missing value (i.e., followed by a delimiter), - // return with an error status. - ts.skip_delim (ds); - if (ds.no_progress ()) - { - retval = 4; - break; - } - already_skipped_delim = true; - - val = ts.m_empty_value.scalar_value (); - - if (! --max_empty) - break; - } - - if (val.imag () == 0) - val_type = octave_value (NDArray (dv, val.real ())); - else - val_type = octave_value (ComplexNDArray (dv, val)); - - m_output_container.push_back (val_type); - - if (! already_skipped_delim) + } +} + +// If FORMAT is explicitly "", it is assumed to be "%f" repeated enough +// times to read the first row of the file. Set it now. + +int +textscan_format_list::read_first_row (delimited_stream& is, textscan& ts) +{ + // Read first line and strip end-of-line, which may be two characters + std::string first_line (20, ' '); + + is.getline (first_line, static_cast (ts.m_eol2)); + + if (! first_line.empty () && first_line.back () == ts.m_eol1) + first_line.pop_back (); + + std::istringstream strstr (first_line); + delimited_stream ds (strstr, is); + + dim_vector dv (1, 1); // initial size of each output_container + Complex val; + octave_value val_type; + m_nconv = 0; + int max_empty = 1000; // failsafe, if ds fails but not with eof + int retval = 0; + + // read line, creating output_container as we go + while (! ds.eof ()) + { + bool already_skipped_delim = false; + ts.skip_whitespace (ds, false); + ds.progress_benchmark (); + ts.scan_complex (ds, *m_fmt_elts[0], val); + if (ds.fail ()) + { + ds.clear (ds.rdstate () & ~std::ios::failbit); + + if (ds.eof ()) + break; + + // Unless this was a missing value (i.e., followed by a delimiter), + // return with an error status. ts.skip_delim (ds); - - if (ds.no_progress ()) - break; - - m_nconv++; - } - - m_output_container.pop_front (); // discard empty element from constructor - - // Create fmt_list now that the size is known - for (octave_idx_type i = 1; i < m_nconv; i++) - m_fmt_elts.push_back (new textscan_format_elt (*m_fmt_elts[0])); - - return retval; // May have returned 4 above. - } - - textscan::textscan (const std::string& who_arg, const std::string& encoding) - : m_who (who_arg), m_encoding (encoding), m_buf (), m_whitespace_table (), - m_delim_table (), m_delims (), m_comment_style (), m_comment_len (0), - m_comment_char (-2), m_buffer_size (0), m_date_locale (), - m_inf_nan (init_inf_nan ()), - m_empty_value (numeric_limits::NaN ()), - m_exp_chars ("edED"), m_header_lines (0), m_treat_as_empty (), - m_treat_as_empty_len (0), m_whitespace (" \b\t"), m_eol1 ('\r'), - m_eol2 ('\n'), m_return_on_error (1), m_collect_output (false), - multiple_delims_as_one (false), m_default_exp (true), m_lines (0) - { } - - octave_value - textscan::scan (std::istream& isp, const std::string& fmt, - octave_idx_type ntimes, const octave_value_list& options, - octave_idx_type& count) - { - textscan_format_list fmt_list (fmt); - - parse_options (options, fmt_list); - - octave_value result = do_scan (isp, fmt_list, ntimes); - - // FIXME: this is probably not the best way to get count. The - // position could easily be larger than octave_idx_type when using - // 32-bit indexing. - - std::ios::iostate state = isp.rdstate (); - isp.clear (); - count = static_cast (isp.tellg ()); - isp.setstate (state); - - return result; - } - - octave_value - textscan::do_scan (std::istream& isp, textscan_format_list& fmt_list, - octave_idx_type ntimes) - { - octave_value retval; - - if (fmt_list.num_conversions () == -1) - error ("%s: invalid format specified", m_who.c_str ()); - - if (fmt_list.num_conversions () == 0) - error ("%s: no valid format conversion specifiers", m_who.c_str ()); - - // skip the first header_lines - std::string dummy; - for (int i = 0; i < m_header_lines && isp; i++) - getline (isp, dummy, static_cast (m_eol2)); - - // Create our own buffered stream, for fast get/putback/tell/seek. - - // First, see how far ahead it should let us look. - int max_lookahead = std::max ({m_comment_len, m_treat_as_empty_len, - m_delim_len, 3}); // 3 for NaN and Inf - - // Next, choose a buffer size to avoid reading too much, or too often. - octave_idx_type buf_size = 4096; - if (m_buffer_size) - buf_size = m_buffer_size; - else if (ntimes > 0) - { - // Avoid overflow of 80*ntimes... - buf_size = std::min (buf_size, std::max (ntimes, 80 * ntimes)); - buf_size = std::max (buf_size, ntimes); - } - // Finally, create the stream. - delimited_stream is (isp, - (m_delims.empty () ? m_whitespace + "\r\n" - : m_delims), - max_lookahead, buf_size); - - // Grow retval dynamically. "size" is half the initial size - // (FIXME: Should we start smaller if ntimes is large?) - octave_idx_type size = ((ntimes < 8 && ntimes >= 0) ? ntimes : 1); - Array row_idx (dim_vector (1, 2)); - row_idx(1) = 0; - - int err = 0; - octave_idx_type row = 0; - - if (multiple_delims_as_one) // bug #44750? - skip_delim (is); - - int done_after; // Number of columns read when EOF seen. - - // If FORMAT explicitly "", read first line and see how many "%f" match - if (fmt_list.set_from_first) - { - err = fmt_list.read_first_row (is, *this); - m_lines = 1; - - done_after = fmt_list.numel () + 1; - if (! err) - row = 1; // the above puts the first line into fmt_list.out_buf () - } - else - done_after = fmt_list.out_buf ().size () + 1; - - std::list out = fmt_list.out_buf (); - - // We will later merge adjacent columns of the same type. - // Check now which columns to merge. - // Reals may become complex, and so we can't trust types - // after reading in data. - // If the format was "", that conversion may already have happened, - // so force all to be merged (as all are %f). - bool merge_with_prev[fmt_list.numel ()]; - int conv = 0; - if (m_collect_output) - { - int prev_type = -1; - for (const auto& col : out) - { - if (col.type_id () == prev_type - || (fmt_list.set_from_first && prev_type != -1)) - merge_with_prev[conv++] = true; - else - merge_with_prev[conv++] = false; - - prev_type = col.type_id (); - } - } - - // This should be caught by earlier code, but this avoids a possible - // infinite loop below. - if (fmt_list.num_conversions () == 0) - error ("%s: No conversions specified", m_who.c_str ()); - - // Read the data. This is the main loop. - if (! err) - { - for (/* row set ~30 m_lines above */; - row < ntimes || ntimes == -1; - row++) - { - if (row == 0 || row >= size) - { - size += (size+1); - for (auto& col : out) - col = col.resize (dim_vector (size, 1), 0); - } - - row_idx(0) = row; - err = read_format_once (is, fmt_list, out, row_idx, done_after); - - if ((err & ~1) > 0 || ! is || (m_lines >= ntimes && ntimes > -1)) + if (ds.no_progress ()) + { + retval = 4; break; - } - } - - if ((err & 4) && ! m_return_on_error) - error ("%s: Read error in field %d of row %" OCTAVE_IDX_TYPE_FORMAT, - m_who.c_str (), done_after + 1, row + 1); - - // If file does not end in EOL, do not pad columns with NaN. - bool uneven_columns = false; - if (err & 4) - uneven_columns = true; - else if (isp.eof ()) - { - isp.clear (); - isp.seekg (-1, std::ios_base::end); - int last_char = isp.get (); - isp.setstate (isp.eofbit); - uneven_columns = (last_char != m_eol1 && last_char != m_eol2); - } - - // convert return value to Cell array - Array ra_idx (dim_vector (1, 2)); - - // (err & 1) means "error, and no columns read this row - // FIXME: This may redundant now that done_after=0 says the same - if (err & 1) - done_after = out.size () + 1; - - int valid_rows = (row == ntimes - ? ntimes - : ((err & 1) && (err & 8)) ? row : row+1); - dim_vector dv (valid_rows, 1); - - ra_idx(0) = 0; - int i = 0; - if (! m_collect_output) - { - retval = Cell (dim_vector (1, out.size ())); - for (auto& col : out) - { - // trim last columns if that was requested - if (i == done_after && uneven_columns) - dv = dim_vector (std::max (valid_rows - 1, 0), 1); - - ra_idx(1) = i; - retval = cat_op (retval, octave_value (Cell (col.resize (dv, 0))), - ra_idx); - i++; - } - } - else // group adjacent cells of the same type into a single cell - { - octave_value cur; // current cell, accumulating columns - octave_idx_type group_size = 0; // columns in this cell - int prev_type = -1; - - conv = 0; - retval = Cell (); - for (auto& col : out) - { - if (! merge_with_prev[conv++]) // including first time - { - if (prev_type != -1) - { - ra_idx(1) = i++; - retval = cat_op (retval, octave_value (Cell (cur)), ra_idx); - } - cur = octave_value (col.resize (dv, 0)); - group_size = 1; - prev_type = col.type_id (); - } - else - { - ra_idx(1) = group_size++; - cur = cat_op (cur, octave_value (col.resize (dv, 0)), ra_idx); - } - } - ra_idx(1) = i; - retval = cat_op (retval, octave_value (Cell (cur)), ra_idx); - } - - return retval; - } - - // Read a double considering the "precision" field of FMT and the - // EXP_CHARS option of OPTIONS. - - double - textscan::read_double (delimited_stream& is, - const textscan_format_elt& fmt) const - { - int sign = 1; - unsigned int width_left = fmt.width; - double retval = 0; - bool valid = false; // syntactically correct double? - - int ch = is.peek_undelim (); - - if (ch == '+') - { - is.get (); - ch = is.peek_undelim (); - if (width_left) - width_left--; - } - else if (ch == '-') - { - sign = -1; - is.get (); - ch = is.peek_undelim (); - if (width_left) - width_left--; - } - - // Read integer part - if (ch != '.') - { - if (ch >= '0' && ch <= '9') // valid if at least one digit - valid = true; + } + already_skipped_delim = true; + + val = ts.m_empty_value.scalar_value (); + + if (! --max_empty) + break; + } + + if (val.imag () == 0) + val_type = octave_value (NDArray (dv, val.real ())); + else + val_type = octave_value (ComplexNDArray (dv, val)); + + m_output_container.push_back (val_type); + + if (! already_skipped_delim) + ts.skip_delim (ds); + + if (ds.no_progress ()) + break; + + m_nconv++; + } + + m_output_container.pop_front (); // discard empty element from constructor + + // Create fmt_list now that the size is known + for (octave_idx_type i = 1; i < m_nconv; i++) + m_fmt_elts.push_back (new textscan_format_elt (*m_fmt_elts[0])); + + return retval; // May have returned 4 above. +} + +textscan::textscan (const std::string& who_arg, const std::string& encoding) + : m_who (who_arg), m_encoding (encoding), m_buf (), m_whitespace_table (), + m_delim_table (), m_delims (), m_comment_style (), m_comment_len (0), + m_comment_char (-2), m_buffer_size (0), m_date_locale (), + m_inf_nan (init_inf_nan ()), + m_empty_value (numeric_limits::NaN ()), + m_exp_chars ("edED"), m_header_lines (0), m_treat_as_empty (), + m_treat_as_empty_len (0), m_whitespace (" \b\t"), m_eol1 ('\r'), + m_eol2 ('\n'), m_return_on_error (1), m_collect_output (false), + multiple_delims_as_one (false), m_default_exp (true), m_lines (0) +{ } + +octave_value +textscan::scan (std::istream& isp, const std::string& fmt, + octave_idx_type ntimes, const octave_value_list& options, + octave_idx_type& count) +{ + textscan_format_list fmt_list (fmt); + + parse_options (options, fmt_list); + + octave_value result = do_scan (isp, fmt_list, ntimes); + + // FIXME: this is probably not the best way to get count. The + // position could easily be larger than octave_idx_type when using + // 32-bit indexing. + + std::ios::iostate state = isp.rdstate (); + isp.clear (); + count = static_cast (isp.tellg ()); + isp.setstate (state); + + return result; +} + +octave_value +textscan::do_scan (std::istream& isp, textscan_format_list& fmt_list, + octave_idx_type ntimes) +{ + octave_value retval; + + if (fmt_list.num_conversions () == -1) + error ("%s: invalid format specified", m_who.c_str ()); + + if (fmt_list.num_conversions () == 0) + error ("%s: no valid format conversion specifiers", m_who.c_str ()); + + // skip the first header_lines + std::string dummy; + for (int i = 0; i < m_header_lines && isp; i++) + getline (isp, dummy, static_cast (m_eol2)); + + // Create our own buffered stream, for fast get/putback/tell/seek. + + // First, see how far ahead it should let us look. + int max_lookahead = std::max ({m_comment_len, m_treat_as_empty_len, + m_delim_len, 3}); // 3 for NaN and Inf + + // Next, choose a buffer size to avoid reading too much, or too often. + octave_idx_type buf_size = 4096; + if (m_buffer_size) + buf_size = m_buffer_size; + else if (ntimes > 0) + { + // Avoid overflow of 80*ntimes... + buf_size = std::min (buf_size, std::max (ntimes, 80 * ntimes)); + buf_size = std::max (buf_size, ntimes); + } + // Finally, create the stream. + delimited_stream is (isp, + (m_delims.empty () ? m_whitespace + "\r\n" + : m_delims), + max_lookahead, buf_size); + + // Grow retval dynamically. "size" is half the initial size + // (FIXME: Should we start smaller if ntimes is large?) + octave_idx_type size = ((ntimes < 8 && ntimes >= 0) ? ntimes : 1); + Array row_idx (dim_vector (1, 2)); + row_idx(1) = 0; + + int err = 0; + octave_idx_type row = 0; + + if (multiple_delims_as_one) // bug #44750? + skip_delim (is); + + int done_after; // Number of columns read when EOF seen. + + // If FORMAT explicitly "", read first line and see how many "%f" match + if (fmt_list.set_from_first) + { + err = fmt_list.read_first_row (is, *this); + m_lines = 1; + + done_after = fmt_list.numel () + 1; + if (! err) + row = 1; // the above puts the first line into fmt_list.out_buf () + } + else + done_after = fmt_list.out_buf ().size () + 1; + + std::list out = fmt_list.out_buf (); + + // We will later merge adjacent columns of the same type. + // Check now which columns to merge. + // Reals may become complex, and so we can't trust types + // after reading in data. + // If the format was "", that conversion may already have happened, + // so force all to be merged (as all are %f). + bool merge_with_prev[fmt_list.numel ()]; + int conv = 0; + if (m_collect_output) + { + int prev_type = -1; + for (const auto& col : out) + { + if (col.type_id () == prev_type + || (fmt_list.set_from_first && prev_type != -1)) + merge_with_prev[conv++] = true; + else + merge_with_prev[conv++] = false; + + prev_type = col.type_id (); + } + } + + // This should be caught by earlier code, but this avoids a possible + // infinite loop below. + if (fmt_list.num_conversions () == 0) + error ("%s: No conversions specified", m_who.c_str ()); + + // Read the data. This is the main loop. + if (! err) + { + for (/* row set ~30 m_lines above */; + row < ntimes || ntimes == -1; + row++) + { + if (row == 0 || row >= size) + { + size += (size+1); + for (auto& col : out) + col = col.resize (dim_vector (size, 1), 0); + } + + row_idx(0) = row; + err = read_format_once (is, fmt_list, out, row_idx, done_after); + + if ((err & ~1) > 0 || ! is || (m_lines >= ntimes && ntimes > -1)) + break; + } + } + + if ((err & 4) && ! m_return_on_error) + error ("%s: Read error in field %d of row %" OCTAVE_IDX_TYPE_FORMAT, + m_who.c_str (), done_after + 1, row + 1); + + // If file does not end in EOL, do not pad columns with NaN. + bool uneven_columns = false; + if (err & 4) + uneven_columns = true; + else if (isp.eof ()) + { + isp.clear (); + isp.seekg (-1, std::ios_base::end); + int last_char = isp.get (); + isp.setstate (isp.eofbit); + uneven_columns = (last_char != m_eol1 && last_char != m_eol2); + } + + // convert return value to Cell array + Array ra_idx (dim_vector (1, 2)); + + // (err & 1) means "error, and no columns read this row + // FIXME: This may redundant now that done_after=0 says the same + if (err & 1) + done_after = out.size () + 1; + + int valid_rows = (row == ntimes + ? ntimes + : ((err & 1) && (err & 8)) ? row : row+1); + dim_vector dv (valid_rows, 1); + + ra_idx(0) = 0; + int i = 0; + if (! m_collect_output) + { + retval = Cell (dim_vector (1, out.size ())); + for (auto& col : out) + { + // trim last columns if that was requested + if (i == done_after && uneven_columns) + dv = dim_vector (std::max (valid_rows - 1, 0), 1); + + ra_idx(1) = i; + retval = cat_op (retval, octave_value (Cell (col.resize (dv, 0))), + ra_idx); + i++; + } + } + else // group adjacent cells of the same type into a single cell + { + octave_value cur; // current cell, accumulating columns + octave_idx_type group_size = 0; // columns in this cell + int prev_type = -1; + + conv = 0; + retval = Cell (); + for (auto& col : out) + { + if (! merge_with_prev[conv++]) // including first time + { + if (prev_type != -1) + { + ra_idx(1) = i++; + retval = cat_op (retval, octave_value (Cell (cur)), ra_idx); + } + cur = octave_value (col.resize (dv, 0)); + group_size = 1; + prev_type = col.type_id (); + } + else + { + ra_idx(1) = group_size++; + cur = cat_op (cur, octave_value (col.resize (dv, 0)), ra_idx); + } + } + ra_idx(1) = i; + retval = cat_op (retval, octave_value (Cell (cur)), ra_idx); + } + + return retval; +} + +// Read a double considering the "precision" field of FMT and the +// EXP_CHARS option of OPTIONS. + +double +textscan::read_double (delimited_stream& is, + const textscan_format_elt& fmt) const +{ + int sign = 1; + unsigned int width_left = fmt.width; + double retval = 0; + bool valid = false; // syntactically correct double? + + int ch = is.peek_undelim (); + + if (ch == '+') + { + is.get (); + ch = is.peek_undelim (); + if (width_left) + width_left--; + } + else if (ch == '-') + { + sign = -1; + is.get (); + ch = is.peek_undelim (); + if (width_left) + width_left--; + } + + // Read integer part + if (ch != '.') + { + if (ch >= '0' && ch <= '9') // valid if at least one digit + valid = true; + while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9') + retval = retval * 10 + (ch - '0'); + width_left++; + } + + // Read fractional part, up to specified precision + if (ch == '.' && width_left) + { + double multiplier = 1; + int precision = fmt.prec; + int i; + + width_left--; // Consider width of '.' + + if (precision == -1) + precision = 1<<30; // FIXME: Should be MAXINT + + if (! valid) // if there was nothing before '.'... + is.get (); // ...ch was a "peek", not "get". + + for (i = 0; i < precision; i++) + { + if (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9') + retval += (ch - '0') * (multiplier *= 0.1); + else + { + width_left++; + break; + } + } + + // round up if we truncated and the next digit is >= 5 + if ((i == precision || ! width_left) && (ch = is.get ()) >= '5' + && ch <= '9') + retval += multiplier; + + if (i > 0) + valid = true; // valid if at least one digit after '.' + else if (! valid) // if there was nothing before and after '.' + { + is.putback (ch); + ch = '.'; + } + + // skip remainder after '.', to field width, to look for exponent + if (i == precision) while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9') - retval = retval * 10 + (ch - '0'); - width_left++; - } - - // Read fractional part, up to specified precision - if (ch == '.' && width_left) - { - double multiplier = 1; - int precision = fmt.prec; - int i; - - width_left--; // Consider width of '.' - - if (precision == -1) - precision = 1<<30; // FIXME: Should be MAXINT - - if (! valid) // if there was nothing before '.'... - is.get (); // ...ch was a "peek", not "get". - - for (i = 0; i < precision; i++) - { - if (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9') - retval += (ch - '0') * (multiplier *= 0.1); - else - { - width_left++; - break; - } - } - - // round up if we truncated and the next digit is >= 5 - if ((i == precision || ! width_left) && (ch = is.get ()) >= '5' - && ch <= '9') - retval += multiplier; - - if (i > 0) - valid = true; // valid if at least one digit after '.' - else if (! valid) // if there was nothing before and after '.' - { + ; // discard + + width_left++; + } + + // look for exponent part in, e.g., 6.023E+23 + bool used_exp = false; + if (valid && width_left > 1 && m_exp_chars.find (ch) != std::string::npos) + { + int ch1 = is.peek_undelim (); + if (ch1 == '-' || ch1 == '+' || (ch1 >= '0' && ch1 <= '9')) + { + // if 1.0e+$ or some such, this will set failbit, as we want + width_left--; // count "E" + int exp = 0; + int exp_sign = 1; + if (ch1 == '+') + { + width_left--; + is.get (); + } + else if (ch1 == '-') + { + width_left--; + exp_sign = -1; + is.get (); + } + valid = false; + while (width_left-- && is && (ch = is.get_undelim ()) >= '0' && ch <= '9') + { + exp = exp*10 + ch - '0'; + valid = true; + } + width_left++; + if (ch != std::istream::traits_type::eof () && width_left) is.putback (ch); - ch = '.'; - } - - // skip remainder after '.', to field width, to look for exponent - if (i == precision) - while (width_left-- && is && (ch = is.get ()) >= '0' && ch <= '9') - ; // discard - - width_left++; - } - - // look for exponent part in, e.g., 6.023E+23 - bool used_exp = false; - if (valid && width_left > 1 && m_exp_chars.find (ch) != std::string::npos) - { - int ch1 = is.peek_undelim (); - if (ch1 == '-' || ch1 == '+' || (ch1 >= '0' && ch1 <= '9')) - { - // if 1.0e+$ or some such, this will set failbit, as we want - width_left--; // count "E" - int exp = 0; - int exp_sign = 1; - if (ch1 == '+') - { - width_left--; - is.get (); - } - else if (ch1 == '-') - { - width_left--; - exp_sign = -1; - is.get (); - } - valid = false; - while (width_left-- && is && (ch = is.get_undelim ()) >= '0' && ch <= '9') - { - exp = exp*10 + ch - '0'; - valid = true; - } - width_left++; - if (ch != std::istream::traits_type::eof () && width_left) - is.putback (ch); - - double multiplier = pown (10, exp); - if (exp_sign > 0) - retval *= multiplier; - else - retval /= multiplier; - - used_exp = true; - } - } - is.clear (); - if (! used_exp && ch != std::istream::traits_type::eof () && width_left) - is.putback (ch); - - // Check for +/- inf and NaN - if (! valid && width_left >= 3 && is.remaining () >= 3) - { - int i = lookahead (is, m_inf_nan, 3, false); // false->case insensitive - if (i == 0) - { - retval = numeric_limits::Inf (); - valid = true; - } - else if (i == 1) - { - retval = numeric_limits::NaN (); - valid = true; - } - } - - if (! valid) - is.setstate (std::ios::failbit); - else - is.setstate (is.rdstate () & ~std::ios::failbit); - - return retval * sign; - } - - // Read a single number: real, complex, inf, NaN, possibly with limited - // precision. Calls to this should be preceded by skip_whitespace. - // Calling that inside scan_complex would violate its const declaration. - - void - textscan::scan_complex (delimited_stream& is, const textscan_format_elt& fmt, - Complex& val) const - { - double im = 0; - double re = 0; - bool as_empty = false; // did we fail but match a "treat_as_empty" string? - bool inf = false; - - int ch = is.peek_undelim (); - if (ch == '+' || ch == '-') // check for [+-][ij] with no coefficients - { - ch = is.get (); - int ch2 = is.peek_undelim (); - if (ch2 == 'i' || ch2 == 'j') - { - double value = 1; - is.get (); - // Check not -inf - if (is.peek_undelim () == 'n') - { - char *pos = is.tellg (); - std::ios::iostate state = is.rdstate (); - - is.get (); - ch2 = is.get_undelim (); - if (ch2 == 'f') - { - inf = true; - re = (ch == '+' ? numeric_limits::Inf () - : -numeric_limits::Inf ()); - value = 0; - } - else - { - is.clear (state); - // FIXME: Buffer might have refreshed. - // pos might no longer be valid. - is.seekg (pos); // reset to position before look-ahead - } - } - - im = (ch == '+') ? value : -value; - } - else - is.putback (ch); - } - - if (! im && ! inf) // if not [+-][ij] or [+-]inf, read real normally - { - char *pos = is.tellg (); - std::ios::iostate state = is.rdstate (); - //re = read_value (is); - // FIXME: read_double might refresh the buffer. So seekg might be off. - re = read_double (is, fmt); - - // check for "treat as empty" string - if (m_treat_as_empty.numel () - && (is.fail () || math::is_NaN_or_NA (Complex (re)) - || re == numeric_limits::Inf ())) - { - - for (int i = 0; i < m_treat_as_empty.numel (); i++) - { - if (ch == m_treat_as_empty (i).string_value ()[0]) - { - as_empty = true; // first char matches, so read the lot - break; - } - } - if (as_empty) // if first char matched... - { - as_empty = false; // ...look for the whole string - - is.clear (state); // treat_as_empty "-" causes partial read - is.seekg (pos); // reset to position before failed read - - // treat_as_empty strings may be different sizes. - // Read ahead longest, put it all back, then re-read the string - // that matches. - std::string look_buf (m_treat_as_empty_len, '\0'); - char *look = is.read (&look_buf[0], look_buf.size (), pos); - - is.clear (state); - is.seekg (pos); // reset to position before look-ahead - // FIXME: is.read could invalidate pos - - for (int i = 0; i < m_treat_as_empty.numel (); i++) - { - std::string s = m_treat_as_empty (i).string_value (); - if (! strncmp (s.c_str (), look, s.size ())) - { - as_empty = true; - // read just the right amount - is.read (&look_buf[0], s.size (), pos); - break; - } - } - } - } - - if (! is.eof () && ! as_empty) - { - state = is.rdstate (); // before tellg, since that fails at EOF - - ch = is.peek_undelim (); - // ch == EOF if read failed; no need to chk fail - if (ch == 'i' || ch == 'j') // pure imaginary - { - is.get (); - im = re; - re = 0; - } - else if (ch == '+' || ch == '-') // see if it is real+imag[ij] - { - // save stream state in case we have to restore it - pos = is.tellg (); - state = is.rdstate (); - - //im = read_value (is); - // FIXME: read_double might refresh the buffer. - // So seekg might be off after this. - im = read_double (is, fmt); - if (is.fail ()) - im = 1; - - if (is.peek_undelim () == 'i' || is.peek_undelim () == 'j') - is.get (); - else - { - im = 0; // no valid imaginary part. Restore state - is.clear (state); // eof shouldn't cause fail. - is.seekg (pos); - } - } - else if (is.eof ()) // we've read enough to be a "valid" read - is.clear (state); // failed peek shouldn't cause fail - } - } - if (as_empty) - val = m_empty_value.scalar_value (); - else - val = Complex (re, im); - } - - // Return in VAL the run of characters from IS NOT contained in PATTERN. - - int - textscan::scan_caret (delimited_stream& is, const std::string& pattern, - std::string& val) const - { - int c1 = std::istream::traits_type::eof (); - std::ostringstream obuf; // FIXME: is this optimized for growing? - - while (is && ((c1 = (is && ! is.eof ()) - ? is.get_undelim () - : std::istream::traits_type::eof ()) - != std::istream::traits_type::eof ()) - && pattern.find (c1) == std::string::npos) - obuf << static_cast (c1); - - val = obuf.str (); - - if (c1 != std::istream::traits_type::eof ()) - is.putback (c1); - - return c1; - } - - // Read until one of the strings in DELIMITERS is found. For - // efficiency, ENDS is a list of the last character of each delimiter. - - std::string - textscan::read_until (delimited_stream& is, const Cell& delimiters, - const std::string& ends) const - { - std::string retval (""); - bool done = false; - do - { - // find sequence ending with an ending char - std::string next; - scan_caret (is, ends.c_str (), next); - retval = retval + next; // FIXME: could use repeated doubling of size - - int last = (! is.eof () - ? is.get_undelim () : std::istream::traits_type::eof ()); - - if (last != std::istream::traits_type::eof ()) - { - if (last == m_eol1 || last == m_eol2) - break; - - retval = retval + static_cast (last); - for (int i = 0; i < delimiters.numel (); i++) - { - std::string delim = delimiters(i).string_value (); - std::size_t start = (retval.length () > delim.length () - ? retval.length () - delim.length () - : 0); - std::string may_match = retval.substr (start); - if (may_match == delim) - { - done = true; - retval = retval.substr (0, start); - if (start == 0) - is.putback (last); - break; - } - } - } - } - while (! done && is && ! is.eof ()); - - return retval; - } - - // Read stream until either fmt.width chars have been read, or - // options.delimiter has been found. Does *not* rely on fmt being 's'. - // Used by formats like %6f to limit to 6. - - void - textscan::scan_string (delimited_stream& is, const textscan_format_elt& fmt, - std::string& val) const - { - if (m_delim_list.isempty ()) - { - unsigned int i = 0; - unsigned int width = fmt.width; - - for (i = 0; i < width; i++) - { - // Grow string in an exponential fashion if necessary. - if (i >= val.length ()) - val.append (std::max (val.length (), - static_cast (16)), '\0'); - - int ch = is.get_undelim (); - if (is_delim (ch) || ch == std::istream::traits_type::eof ()) - { - is.putback (ch); - break; - } - else - val[i] = ch; - } - val = val.substr (0, i); // trim pre-allocation - } - else // Cell array of multi-character delimiters - { - std::string ends (m_delim_list.numel () + 2, '\0'); - int i; - for (i = 0; i < m_delim_list.numel (); i++) - { - std::string tmp = m_delim_list(i).string_value (); - ends[i] = tmp.back (); - } - ends[i++] = m_eol1; - ends[i++] = m_eol2; - val = textscan::read_until (is, m_delim_list, ends); - } - - // convert from codepage - if (m_encoding.compare ("utf-8")) - val = string::u8_from_encoding ("textscan", val, m_encoding); - } - - // Return in VAL the run of characters from IS contained in PATTERN. - - int - textscan::scan_bracket (delimited_stream& is, const std::string& pattern, - std::string& val) const - { - int c1 = std::istream::traits_type::eof (); - std::ostringstream obuf; // Is this optimized for growing? - - while (is && pattern.find (c1 = is.get_undelim ()) != std::string::npos) - obuf << static_cast (c1); - - val = obuf.str (); - if (c1 != std::istream::traits_type::eof ()) - is.putback (c1); - return c1; - } - - // Return in VAL a string, either delimited by whitespace/delimiters, or - // enclosed in a pair of double quotes ("..."). Enclosing quotes are - // removed. A consecutive pair "" is inserted into VAL as a single ". - - void - textscan::scan_qstring (delimited_stream& is, const textscan_format_elt& fmt, - std::string& val) - { - skip_whitespace (is); - - if (is.peek_undelim () != '"') - scan_string (is, fmt, val); - else - { - is.get (); - scan_caret (is, R"(")", val); // read everything until " - is.get (); // swallow " - - while (is && is.peek_undelim () == '"') // if double ", - { // insert one in stream, - is.get (); // keep looking for single " - std::string val1; - scan_caret (is, R"(")", val1); - val = val + '"' + val1; - is.get_undelim (); - } - } - - // convert from codepage - if (m_encoding.compare ("utf-8")) - val = string::u8_from_encoding ("textscan", val, m_encoding); - } - - // Read from IS into VAL a string of the next fmt.width characters, - // including any whitespace or delimiters. - - void - textscan::scan_cstring (delimited_stream& is, const textscan_format_elt& fmt, - std::string& val) const - { - val.resize (fmt.width); - - for (unsigned int i = 0; is && i < fmt.width; i++) - { - int ch = is.get_undelim (); - if (ch != std::istream::traits_type::eof ()) - val[i] = ch; - else - { - val.resize (i); - break; - } - } - - // convert from codepage - if (m_encoding.compare ("utf-8")) - val = string::u8_from_encoding ("textscan", val, m_encoding); - } - - // Read a single '%...' conversion and place it in position ROW of OV. - - void - textscan::scan_one (delimited_stream& is, const textscan_format_elt& fmt, - octave_value& ov, Array row) - { - skip_whitespace (is); - - is.clear (); - - octave_value val; - if (fmt.numeric) - { - if (fmt.type == 'f' || fmt.type == 'n') - { - Complex v; - skip_whitespace (is); - scan_complex (is, fmt, v); - - if (! fmt.discard && ! is.fail ()) - { - if (fmt.bitwidth == 64) - { - if (ov.isreal () && v.imag () == 0) - ov.internal_rep ()->fast_elem_insert (row(0), v.real ()); - else - { - if (ov.isreal ()) // cat does type conversion - ov = cat_op (ov, octave_value (v), row); - else - ov.internal_rep ()->fast_elem_insert (row(0), v); - } - } - else - { - if (ov.isreal () && v.imag () == 0) - ov.internal_rep ()->fast_elem_insert (row(0), - float (v.real ())); - else - { - if (ov.isreal ()) // cat does type conversion - ov = cat_op (ov, octave_value (v), row); - else - ov.internal_rep ()->fast_elem_insert (row(0), - FloatComplex (v)); - } - } - } - } - else - { - double v; // Matlab docs say 1e30 etc should be valid for %d and - // 1000 as a %d8 should be 127, so read as double. - // Some loss of precision for d64 and u64. - skip_whitespace (is); - v = read_double (is, fmt); - if (! fmt.discard && ! is.fail ()) - switch (fmt.bitwidth) + + double multiplier = pown (10, exp); + if (exp_sign > 0) + retval *= multiplier; + else + retval /= multiplier; + + used_exp = true; + } + } + is.clear (); + if (! used_exp && ch != std::istream::traits_type::eof () && width_left) + is.putback (ch); + + // Check for +/- inf and NaN + if (! valid && width_left >= 3 && is.remaining () >= 3) + { + int i = lookahead (is, m_inf_nan, 3, false); // false->case insensitive + if (i == 0) + { + retval = numeric_limits::Inf (); + valid = true; + } + else if (i == 1) + { + retval = numeric_limits::NaN (); + valid = true; + } + } + + if (! valid) + is.setstate (std::ios::failbit); + else + is.setstate (is.rdstate () & ~std::ios::failbit); + + return retval * sign; +} + +// Read a single number: real, complex, inf, NaN, possibly with limited +// precision. Calls to this should be preceded by skip_whitespace. +// Calling that inside scan_complex would violate its const declaration. + +void +textscan::scan_complex (delimited_stream& is, const textscan_format_elt& fmt, + Complex& val) const +{ + double im = 0; + double re = 0; + bool as_empty = false; // did we fail but match a "treat_as_empty" string? + bool inf = false; + + int ch = is.peek_undelim (); + if (ch == '+' || ch == '-') // check for [+-][ij] with no coefficients + { + ch = is.get (); + int ch2 = is.peek_undelim (); + if (ch2 == 'i' || ch2 == 'j') + { + double value = 1; + is.get (); + // Check not -inf + if (is.peek_undelim () == 'n') + { + char *pos = is.tellg (); + std::ios::iostate state = is.rdstate (); + + is.get (); + ch2 = is.get_undelim (); + if (ch2 == 'f') { - case 64: - switch (fmt.type) + inf = true; + re = (ch == '+' ? numeric_limits::Inf () + : -numeric_limits::Inf ()); + value = 0; + } + else + { + is.clear (state); + // FIXME: Buffer might have refreshed. + // pos might no longer be valid. + is.seekg (pos); // reset to position before look-ahead + } + } + + im = (ch == '+') ? value : -value; + } + else + is.putback (ch); + } + + if (! im && ! inf) // if not [+-][ij] or [+-]inf, read real normally + { + char *pos = is.tellg (); + std::ios::iostate state = is.rdstate (); + //re = read_value (is); + // FIXME: read_double might refresh the buffer. So seekg might be off. + re = read_double (is, fmt); + + // check for "treat as empty" string + if (m_treat_as_empty.numel () + && (is.fail () || math::is_NaN_or_NA (Complex (re)) + || re == numeric_limits::Inf ())) + { + + for (int i = 0; i < m_treat_as_empty.numel (); i++) + { + if (ch == m_treat_as_empty (i).string_value ()[0]) + { + as_empty = true; // first char matches, so read the lot + break; + } + } + if (as_empty) // if first char matched... + { + as_empty = false; // ...look for the whole string + + is.clear (state); // treat_as_empty "-" causes partial read + is.seekg (pos); // reset to position before failed read + + // treat_as_empty strings may be different sizes. + // Read ahead longest, put it all back, then re-read the string + // that matches. + std::string look_buf (m_treat_as_empty_len, '\0'); + char *look = is.read (&look_buf[0], look_buf.size (), pos); + + is.clear (state); + is.seekg (pos); // reset to position before look-ahead + // FIXME: is.read could invalidate pos + + for (int i = 0; i < m_treat_as_empty.numel (); i++) + { + std::string s = m_treat_as_empty (i).string_value (); + if (! strncmp (s.c_str (), look, s.size ())) { - case 'd': - { - octave_int64 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } - break; - - case 'u': - { - octave_uint64 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } + as_empty = true; + // read just the right amount + is.read (&look_buf[0], s.size (), pos); break; } - break; - - case 32: - switch (fmt.type) - { - case 'd': - { - octave_int32 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } - break; - - case 'u': - { - octave_uint32 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } - break; - } - break; - - case 16: - if (fmt.type == 'd') - { - octave_int16 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } - else - { - octave_uint16 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } - break; - - case 8: - if (fmt.type == 'd') - { - octave_int8 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } - else - { - octave_uint8 vv = v; - ov.internal_rep ()->fast_elem_insert (row(0), vv); - } + } + } + } + + if (! is.eof () && ! as_empty) + { + state = is.rdstate (); // before tellg, since that fails at EOF + + ch = is.peek_undelim (); + // ch == EOF if read failed; no need to chk fail + if (ch == 'i' || ch == 'j') // pure imaginary + { + is.get (); + im = re; + re = 0; + } + else if (ch == '+' || ch == '-') // see if it is real+imag[ij] + { + // save stream state in case we have to restore it + pos = is.tellg (); + state = is.rdstate (); + + //im = read_value (is); + // FIXME: read_double might refresh the buffer. + // So seekg might be off after this. + im = read_double (is, fmt); + if (is.fail ()) + im = 1; + + if (is.peek_undelim () == 'i' || is.peek_undelim () == 'j') + is.get (); + else + { + im = 0; // no valid imaginary part. Restore state + is.clear (state); // eof shouldn't cause fail. + is.seekg (pos); + } + } + else if (is.eof ()) // we've read enough to be a "valid" read + is.clear (state); // failed peek shouldn't cause fail + } + } + if (as_empty) + val = m_empty_value.scalar_value (); + else + val = Complex (re, im); +} + +// Return in VAL the run of characters from IS NOT contained in PATTERN. + +int +textscan::scan_caret (delimited_stream& is, const std::string& pattern, + std::string& val) const +{ + int c1 = std::istream::traits_type::eof (); + std::ostringstream obuf; // FIXME: is this optimized for growing? + + while (is && ((c1 = (is && ! is.eof ()) + ? is.get_undelim () + : std::istream::traits_type::eof ()) + != std::istream::traits_type::eof ()) + && pattern.find (c1) == std::string::npos) + obuf << static_cast (c1); + + val = obuf.str (); + + if (c1 != std::istream::traits_type::eof ()) + is.putback (c1); + + return c1; +} + +// Read until one of the strings in DELIMITERS is found. For +// efficiency, ENDS is a list of the last character of each delimiter. + +std::string +textscan::read_until (delimited_stream& is, const Cell& delimiters, + const std::string& ends) const +{ + std::string retval (""); + bool done = false; + do + { + // find sequence ending with an ending char + std::string next; + scan_caret (is, ends.c_str (), next); + retval = retval + next; // FIXME: could use repeated doubling of size + + int last = (! is.eof () + ? is.get_undelim () : std::istream::traits_type::eof ()); + + if (last != std::istream::traits_type::eof ()) + { + if (last == m_eol1 || last == m_eol2) + break; + + retval = retval + static_cast (last); + for (int i = 0; i < delimiters.numel (); i++) + { + std::string delim = delimiters(i).string_value (); + std::size_t start = (retval.length () > delim.length () + ? retval.length () - delim.length () + : 0); + std::string may_match = retval.substr (start); + if (may_match == delim) + { + done = true; + retval = retval.substr (0, start); + if (start == 0) + is.putback (last); break; } - } - - if (is.fail () & ! fmt.discard) - ov = cat_op (ov, m_empty_value, row); - } - else - { - std::string vv (" "); // initial buffer. Grows as needed - switch (fmt.type) - { - case 's': - scan_string (is, fmt, vv); - break; - - case 'q': - scan_qstring (is, fmt, vv); - break; - - case 'c': - scan_cstring (is, fmt, vv); - break; - - case '[': - scan_bracket (is, fmt.char_class.c_str (), vv); - break; - - case '^': - scan_caret (is, fmt.char_class.c_str (), vv); - break; - } - - if (! fmt.discard) - ov.internal_rep ()->fast_elem_insert (row (0), - Cell (octave_value (vv))); - - // FIXME: why does failbit get set at EOF, instead of eofbit? - if (! vv.empty ()) - is.clear (is.rdstate () & ~std::ios_base::failbit); - } - - is.field_done (); - } - - // Read data corresponding to the entire format string once, placing the - // values in row ROW of retval. - - int - textscan::read_format_once (delimited_stream& is, - textscan_format_list& fmt_list, - std::list& retval, - Array row, int& done_after) - { - const textscan_format_elt *elem = fmt_list.first (); - auto out = retval.begin (); - bool no_conversions = true; - bool done = false; - bool conversion_failed = false; // Record for ReturnOnError - bool nothing_worked = true; - - octave_quit (); - - for (std::size_t i = 0; i < fmt_list.numel (); i++) - { - bool this_conversion_failed = false; - - // Clear fail of previous numeric conversions. - is.clear (); - - switch (elem->type) - { - case 'C': - case 'D': - warning ("%s: conversion %c not yet implemented", - m_who.c_str (), elem->type); - break; - - case 'u': - case 'd': - case 'f': - case 'n': - case 's': - case '[': - case '^': - case 'q': - case 'c': - scan_one (is, *elem, *out, row); - break; - - case textscan_format_elt::literal_conversion : - match_literal (is, *elem); - break; - - default: - error ("Unknown format element '%c'", elem->type); - } - - if (! is.fail ()) - { - if (! elem->discard) - no_conversions = false; - } - else - { - is.clear (is.rdstate () & ~std::ios::failbit); - - if (! is.eof ()) - { - if (m_delim_list.isempty ()) - { - if (! is_delim (is.peek_undelim ())) - this_conversion_failed = true; - } - else // Cell array of multi-character delimiters - { - char *pos = is.tellg (); - if (-1 == lookahead (is, m_delim_list, m_delim_len)) - this_conversion_failed = true; - is.clear (); - is.seekg (pos); // reset to position before look-ahead - } - } - } - - if (! elem->discard) - out++; - - elem = fmt_list.next (); - char *pos = is.tellg (); - - // 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 ()) - { - if (! done) - done_after = i+1; - - // note EOF, but process others to get empty_val. - done = true; - } - - if (this_conversion_failed) - { - if (is.tellg () == pos && ! conversion_failed) - { - // done_after = first failure - done_after = i; // note fail, but parse others to get empty_val - conversion_failed = true; - } - else - this_conversion_failed = false; - } - else if (! done && ! conversion_failed) - nothing_worked = false; - } - - if (done) - is.setstate (std::ios::eofbit); - - return no_conversions - + (is.eof () ? 2 : 0) - + (conversion_failed ? 4 : 0) - + (nothing_worked ? 8 : 0); - - } - - void - textscan::parse_options (const octave_value_list& args, - textscan_format_list& fmt_list) - { - int last = args.length (); - int n = last; - - if (n & 1) - error ("%s: %d parameters given, but only %d values", - m_who.c_str (), n-n/2, n/2); - - m_delim_len = 1; - bool have_delims = false; - for (int i = 0; i < last; i += 2) - { - std::string param = args(i).xstring_value ("%s: Invalid parameter type <%s> for parameter %d", - m_who.c_str (), - args(i).type_name ().c_str (), - i/2 + 1); - std::transform (param.begin (), param.end (), param.begin (), ::tolower); - - if (param == "delimiter") - { - bool invalid = true; - if (args(i+1).is_string ()) - { - invalid = false; - have_delims = true; - m_delims = args(i+1).string_value (); - if (args(i+1).is_sq_string ()) - m_delims = do_string_escapes (m_delims); - } - else if (args(i+1).iscell ()) - { - invalid = false; - m_delim_list = args(i+1).cell_value (); - m_delim_table = " "; // non-empty, to flag non-default delim - - // Check that all elements are strings, and find max length - for (int j = 0; j < m_delim_list.numel (); j++) - { - if (! m_delim_list(j).is_string ()) - invalid = true; - else - { - if (m_delim_list(j).is_sq_string ()) - m_delim_list(j) = do_string_escapes (m_delim_list(j) - .string_value ()); - octave_idx_type len = m_delim_list(j).string_value () - .length (); - m_delim_len = std::max (static_cast (len), - m_delim_len); - } - } - } - if (invalid) - error ("%s: Delimiters must be either a string or cell array of strings", - m_who.c_str ()); - } - else if (param == "commentstyle") - { - if (args(i+1).is_string ()) - { - // check here for names like "C++", "C", "shell", ...? - m_comment_style = Cell (args(i+1)); - } - else if (args(i+1).iscell ()) - { - m_comment_style = args(i+1).cell_value (); - int len = m_comment_style.numel (); - if ((len >= 1 && ! m_comment_style (0).is_string ()) - || (len >= 2 && ! m_comment_style (1).is_string ()) - || (len >= 3)) - error ("%s: CommentStyle must be either a string or cell array of one or two strings", - m_who.c_str ()); - } - else - error ("%s: CommentStyle must be either a string or cell array of one or two strings", - m_who.c_str ()); - - // How far ahead do we need to look to detect an open comment - // and which character do we look for? - if (m_comment_style.numel () >= 1) - { - m_comment_len = m_comment_style (0).string_value ().size (); - m_comment_char = m_comment_style (0).string_value ()[0]; - } - } - else if (param == "treatasempty") - { - bool invalid = false; - if (args(i+1).is_string ()) - { - m_treat_as_empty = Cell (args(i+1)); - m_treat_as_empty_len = args(i+1).string_value ().size (); - } - else if (args(i+1).iscell ()) - { - m_treat_as_empty = args(i+1).cell_value (); - for (int j = 0; j < m_treat_as_empty.numel (); j++) - if (! m_treat_as_empty (j).is_string ()) - invalid = true; + } + } + } + while (! done && is && ! is.eof ()); + + return retval; +} + +// Read stream until either fmt.width chars have been read, or +// options.delimiter has been found. Does *not* rely on fmt being 's'. +// Used by formats like %6f to limit to 6. + +void +textscan::scan_string (delimited_stream& is, const textscan_format_elt& fmt, + std::string& val) const +{ + if (m_delim_list.isempty ()) + { + unsigned int i = 0; + unsigned int width = fmt.width; + + for (i = 0; i < width; i++) + { + // Grow string in an exponential fashion if necessary. + if (i >= val.length ()) + val.append (std::max (val.length (), + static_cast (16)), '\0'); + + int ch = is.get_undelim (); + if (is_delim (ch) || ch == std::istream::traits_type::eof ()) + { + is.putback (ch); + break; + } + else + val[i] = ch; + } + val = val.substr (0, i); // trim pre-allocation + } + else // Cell array of multi-character delimiters + { + std::string ends (m_delim_list.numel () + 2, '\0'); + int i; + for (i = 0; i < m_delim_list.numel (); i++) + { + std::string tmp = m_delim_list(i).string_value (); + ends[i] = tmp.back (); + } + ends[i++] = m_eol1; + ends[i++] = m_eol2; + val = textscan::read_until (is, m_delim_list, ends); + } + + // convert from codepage + if (m_encoding.compare ("utf-8")) + val = string::u8_from_encoding ("textscan", val, m_encoding); +} + +// Return in VAL the run of characters from IS contained in PATTERN. + +int +textscan::scan_bracket (delimited_stream& is, const std::string& pattern, + std::string& val) const +{ + int c1 = std::istream::traits_type::eof (); + std::ostringstream obuf; // Is this optimized for growing? + + while (is && pattern.find (c1 = is.get_undelim ()) != std::string::npos) + obuf << static_cast (c1); + + val = obuf.str (); + if (c1 != std::istream::traits_type::eof ()) + is.putback (c1); + return c1; +} + +// Return in VAL a string, either delimited by whitespace/delimiters, or +// enclosed in a pair of double quotes ("..."). Enclosing quotes are +// removed. A consecutive pair "" is inserted into VAL as a single ". + +void +textscan::scan_qstring (delimited_stream& is, const textscan_format_elt& fmt, + std::string& val) +{ + skip_whitespace (is); + + if (is.peek_undelim () != '"') + scan_string (is, fmt, val); + else + { + is.get (); + scan_caret (is, R"(")", val); // read everything until " + is.get (); // swallow " + + while (is && is.peek_undelim () == '"') // if double ", + { + // insert one in stream, + is.get (); // keep looking for single " + std::string val1; + scan_caret (is, R"(")", val1); + val = val + '"' + val1; + is.get_undelim (); + } + } + + // convert from codepage + if (m_encoding.compare ("utf-8")) + val = string::u8_from_encoding ("textscan", val, m_encoding); +} + +// Read from IS into VAL a string of the next fmt.width characters, +// including any whitespace or delimiters. + +void +textscan::scan_cstring (delimited_stream& is, const textscan_format_elt& fmt, + std::string& val) const +{ + val.resize (fmt.width); + + for (unsigned int i = 0; is && i < fmt.width; i++) + { + int ch = is.get_undelim (); + if (ch != std::istream::traits_type::eof ()) + val[i] = ch; + else + { + val.resize (i); + break; + } + } + + // convert from codepage + if (m_encoding.compare ("utf-8")) + val = string::u8_from_encoding ("textscan", val, m_encoding); +} + +// Read a single '%...' conversion and place it in position ROW of OV. + +void +textscan::scan_one (delimited_stream& is, const textscan_format_elt& fmt, + octave_value& ov, Array row) +{ + skip_whitespace (is); + + is.clear (); + + octave_value val; + if (fmt.numeric) + { + if (fmt.type == 'f' || fmt.type == 'n') + { + Complex v; + skip_whitespace (is); + scan_complex (is, fmt, v); + + if (! fmt.discard && ! is.fail ()) + { + if (fmt.bitwidth == 64) + { + if (ov.isreal () && v.imag () == 0) + ov.internal_rep ()->fast_elem_insert (row(0), v.real ()); else { - int k = m_treat_as_empty (j).string_value ().size (); - if (k > m_treat_as_empty_len) - m_treat_as_empty_len = k; - } - } - if (invalid) - error ("%s: TreatAsEmpty must be either a string or cell array of one or two strings", - m_who.c_str ()); - - // FIXME: Ensure none is a prefix of a later one. Sort by length? - } - else if (param == "collectoutput") - { - m_collect_output = args(i+1).xbool_value ("%s: CollectOutput must be logical or numeric", m_who.c_str ()); - } - else if (param == "emptyvalue") - { - m_empty_value = args(i+1).xscalar_value ("%s: EmptyValue must be numeric", m_who.c_str ()); - } - else if (param == "headerlines") - { - m_header_lines = args(i+1).xscalar_value ("%s: HeaderLines must be numeric", m_who.c_str ()); - } - else if (param == "bufsize") - { - m_buffer_size = args(i+1).xscalar_value ("%s: BufSize must be numeric", m_who.c_str ()); - } - else if (param == "multipledelimsasone") - { - multiple_delims_as_one = args(i+1).xbool_value ("%s: MultipleDelimsAsOne must be logical or numeric", m_who.c_str ()); - } - else if (param == "returnonerror") - { - m_return_on_error = args(i+1).xbool_value ("%s: ReturnOnError must be logical or numeric", m_who.c_str ()); - } - else if (param == "whitespace") - { - m_whitespace = args(i+1).xstring_value ("%s: Whitespace must be a character string", m_who.c_str ()); - } - else if (param == "expchars") - { - m_exp_chars = args(i+1).xstring_value ("%s: ExpChars must be a character string", m_who.c_str ()); - m_default_exp = false; - } - else if (param == "endofline") - { - bool valid = true; - std::string s = args(i+1).xstring_value (R"(%s: EndOfLine must be at most one character or '\r\n')", m_who.c_str ()); - if (args(i+1).is_sq_string ()) - s = do_string_escapes (s); - int l = s.length (); - if (l == 0) - m_eol1 = m_eol2 = -2; - else if (l == 1) - m_eol1 = m_eol2 = s.c_str ()[0]; - else if (l == 2) - { - m_eol1 = s.c_str ()[0]; - m_eol2 = s.c_str ()[1]; - if (m_eol1 != '\r' || m_eol2 != '\n') // Why limit it? - valid = false; - } - else - valid = false; - - if (! valid) - error (R"(%s: EndOfLine must be at most one character or '\r\n')", - m_who.c_str ()); - } - else - error ("%s: unrecognized option '%s'", m_who.c_str (), param.c_str ()); - } - - // Remove any user-supplied delimiter from whitespace list - for (unsigned int j = 0; j < m_delims.length (); j++) - { - m_whitespace.erase (std::remove (m_whitespace.begin (), - m_whitespace.end (), - m_delims[j]), - m_whitespace.end ()); - } - for (int j = 0; j < m_delim_list.numel (); j++) - { - std::string delim = m_delim_list(j).string_value (); - if (delim.length () == 1) - m_whitespace.erase (std::remove (m_whitespace.begin (), - m_whitespace.end (), - delim[0]), - m_whitespace.end ()); - } - - m_whitespace_table = std::string (256, '\0'); - for (unsigned int i = 0; i < m_whitespace.length (); i++) - m_whitespace_table[m_whitespace[i]] = '1'; - - // For Matlab compatibility, add 0x20 to whitespace, unless - // whitespace is explicitly ignored. - if (! (m_whitespace.empty () && fmt_list.has_string)) - m_whitespace_table[' '] = '1'; - - // Create look-up table of delimiters, based on 'delimiter' - m_delim_table = std::string (256, '\0'); - if (m_eol1 >= 0 && m_eol1 < 256) - m_delim_table[m_eol1] = '1'; // EOL is always a delimiter - if (m_eol2 >= 0 && m_eol2 < 256) - m_delim_table[m_eol2] = '1'; // EOL is always a delimiter - if (! have_delims) - for (unsigned int i = 0; i < 256; i++) - { - if (isspace (i)) - m_delim_table[i] = '1'; - } - else - for (unsigned int i = 0; i < m_delims.length (); i++) - m_delim_table[m_delims[i]] = '1'; - } - - // Skip comments, and characters specified by the "Whitespace" option. - // If EOLstop == true, don't skip end of line. - - int - textscan::skip_whitespace (delimited_stream& is, bool EOLstop) - { - int c1 = std::istream::traits_type::eof (); - bool found_comment = false; - - do - { - found_comment = false; - int prev = -1; - while (is - && (c1 = is.get_undelim ()) != std::istream::traits_type::eof () - && ( ( (c1 == m_eol1 || c1 == m_eol2) && ++m_lines && ! EOLstop) - || isspace (c1))) - { - if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2) - m_lines--; - prev = c1; - } - - if (c1 == m_comment_char) // see if we match an open comment - { - // save stream state in case we have to restore it - char *pos = is.tellg (); - std::ios::iostate state = is.rdstate (); - - std::string tmp (m_comment_len, '\0'); - char *look = is.read (&tmp[0], m_comment_len-1, pos); // already read first char - if (is && m_comment_style.numel () > 0 - && ! strncmp (m_comment_style(0).string_value ().substr (1).c_str (), - look, m_comment_len-1)) - { - found_comment = true; - - std::string dummy; - if (m_comment_style.numel () == 1) // skip to end of line - { - std::string eol (3, '\0'); - eol[0] = m_eol1; - eol[1] = m_eol2; - - scan_caret (is, eol, dummy); - c1 = is.get_undelim (); - if (c1 == m_eol1 && m_eol1 != m_eol2 - && is.peek_undelim () == m_eol2) - is.get_undelim (); - m_lines++; - } - else // matching pair - { - std::string end_c = m_comment_style(1).string_value (); - // last char of end-comment sequence - std::string last = end_c.substr (end_c.size () - 1); - std::string may_match (""); - do - { - // find sequence ending with last char - scan_caret (is, last, dummy); - is.get_undelim (); // (read LAST itself) - - may_match = may_match + dummy + last; - if (may_match.length () > end_c.length ()) - { - std::size_t start = may_match.length () - - end_c.length (); - may_match = may_match.substr (start); - } - } - while (may_match != end_c && is && ! is.eof ()); - } - } - else // wasn't really a comment; restore state - { - is.clear (state); - is.seekg (pos); - } - } - } - while (found_comment); - - if (c1 != std::istream::traits_type::eof ()) - is.putback (c1); - - return c1; - } - - // See if the next few characters match one of the strings in target. - // For efficiency, MAX_LEN is the cached longest length of any target. - // Return -1 if none is found, or the index of the match. - - int - textscan::lookahead (delimited_stream& is, const Cell& targets, int max_len, - bool case_sensitive) const - { - // target strings may be different sizes. - // Read ahead longest, put it all back, then re-read the string - // that matches. - - char *pos = is.tellg (); - - std::string tmp (max_len, '\0'); - char *look = is.read (&tmp[0], tmp.size (), pos); - - is.clear (); - is.seekg (pos); // reset to position before read - // FIXME: pos may be corrupted by is.read - - int i; - int (*compare)(const char *, const char *, std::size_t); - compare = (case_sensitive ? strncmp : octave_strncasecmp); - - for (i = 0; i < targets.numel (); i++) - { - std::string s = targets (i).string_value (); - if (! (*compare) (s.c_str (), look, s.size ())) - { - is.read (&tmp[0], s.size (), pos); // read just the right amount - break; - } - } - - if (i == targets.numel ()) - i = -1; - - return i; - } - - // Skip delimiters -- multiple if MultipleDelimsAsOne specified. - int - textscan::skip_delim (delimited_stream& is) - { - int c1 = skip_whitespace (is); // Stop once EOL is read - if (m_delim_list.numel () == 0) // single character delimiter - { - if (is_delim (c1) || c1 == m_eol1 || c1 == m_eol2) - { - is.get (); - if (c1 == m_eol1 && is.peek_undelim () == m_eol2) - is.get (); // if \r\n, skip the \n too. - - if (multiple_delims_as_one) - { - int prev = -1; - // skip multiple delims. - // Increment lines for each end-of-line seen; - // Decrement for \r\n - while (is && ((c1 = is.get_undelim ()) - != std::istream::traits_type::eof ()) - && (((c1 == m_eol1 || c1 == m_eol2) && ++m_lines) - || isspace (c1) || is_delim (c1))) - { - if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2) - m_lines--; - prev = c1; - } - if (c1 != std::istream::traits_type::eof ()) - is.putback (c1); - } - } - } - else // multi-character delimiter - { - int first_match; - - if (c1 == m_eol1 || c1 == m_eol2 - || (-1 != (first_match = lookahead (is, m_delim_list, m_delim_len)))) - { - if (c1 == m_eol1) - { - is.get_undelim (); - if (is.peek_undelim () == m_eol2) - is.get_undelim (); - } - else if (c1 == m_eol2) - { - is.get_undelim (); - } - - if (multiple_delims_as_one) - { - int prev = -1; - // skip multiple delims. - // Increment lines for each end-of-line seen; - // decrement for \r\n. - while (is && ((c1 = skip_whitespace (is)) - != std::istream::traits_type::eof ()) - && (((c1 == m_eol1 || c1 == m_eol2) && ++m_lines) - || -1 != lookahead (is, m_delim_list, m_delim_len))) - { - if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2) - m_lines--; - prev = c1; - } - } - } - } - - return c1; - } - - // Read in as much of the input as coincides with the literal in the - // format string. Return "true" if the entire literal is matched, else - // false (and set failbit). - - bool - textscan::match_literal (delimited_stream& is, - const textscan_format_elt& fmt) - { - // "false" -> treat EOL as normal space - // since a delimiter at the start of a line is a mismatch, not empty field - skip_whitespace (is, false); - - for (unsigned int i = 0; i < fmt.width; i++) - { - int ch = is.get_undelim (); - if (ch != fmt.text[i]) - { - if (ch != std::istream::traits_type::eof ()) - is.putback (ch); - is.setstate (std::ios::failbit); - return false; - } - } - return true; - } - - void - base_stream::error (const std::string& msg) - { - m_fail = true; - m_errmsg = msg; - } - - void - base_stream::error (const std::string& who, const std::string& msg) - { - m_fail = true; - m_errmsg = who + ": " + msg; - } - - void - base_stream::clear (void) - { - m_fail = false; - m_errmsg = ""; - } - - void - base_stream::clearerr (void) - { - std::istream *is = input_stream (); - std::ostream *os = preferred_output_stream (); - - if (is) - is->clear (); - - if (os) - os->clear (); - } - - // Functions that are defined for all input streams (input streams - // are those that define is). - - std::string - base_stream::do_gets (octave_idx_type max_len, bool& err, - bool strip_newline, const std::string& who) - { - interpreter& interp = __get_interpreter__ (); - - if (interp.interactive () && file_number () == 0) - ::error ("%s: unable to read from stdin while running interactively", - who.c_str ()); - - std::string retval; - - err = false; - - std::istream *isp = input_stream (); - - if (! isp) - { - err = true; - invalid_operation (who, "reading"); - } - else - { - std::istream& is = *isp; - - std::ostringstream buf; - - int c = 0; - int char_count = 0; - - if (max_len != 0) - { - while (is && (c = is.get ()) != std::istream::traits_type::eof ()) - { - char_count++; - - // Handle CRLF, CR, or LF as line ending. - if (c == '\r') - { - if (! strip_newline) - buf << static_cast (c); - - c = is.get (); - - if (c != std::istream::traits_type::eof ()) - { - if (c == '\n') - { - char_count++; - - if (! strip_newline) - buf << static_cast (c); - } - else - is.putback (c); - } - - break; - } - else if (c == '\n') - { - if (! strip_newline) - buf << static_cast (c); - - break; - } - else - buf << static_cast (c); - - if (max_len > 0 && char_count == max_len) - break; - } - } - - if (! is.eof () && char_count > 0) - { - // GAGME. Matlab seems to check for EOF even if the last character - // in a file is a newline character. This is NOT what the - // corresponding C-library functions do. - int disgusting_compatibility_hack = is.get (); - if (! is.eof ()) - is.putback (disgusting_compatibility_hack); - } - - if (is.good () || (is.eof () && char_count > 0)) - { - retval = buf.str (); - if (encoding ().compare ("utf-8")) - retval = string::u8_from_encoding (who, retval, encoding ()); - } - else - { - err = true; - - if (is.eof () && char_count == 0) - error (who, "at end of file"); - else - error (who, "read error"); - } - } - - return retval; - } - - std::string - base_stream::getl (octave_idx_type max_len, bool& err, - const std::string& who) - { - return do_gets (max_len, err, true, who); - } - - std::string - base_stream::gets (octave_idx_type max_len, bool& err, - const std::string& who) - { - return do_gets (max_len, err, false, who); - } - - off_t - base_stream::skipl (off_t num, bool& err, const std::string& who) - { - interpreter& interp = __get_interpreter__ (); - - if (interp.interactive () && file_number () == 0) - ::error ("%s: unable to read from stdin while running interactively", - who.c_str ()); - - off_t cnt = -1; - - err = false; - - std::istream *isp = input_stream (); - - if (! isp) - { - err = true; - invalid_operation (who, "reading"); - } - else - { - std::istream& is = *isp; - - int c = 0; - int lastc = -1; - cnt = 0; - - while (is && (c = is.get ()) != std::istream::traits_type::eof ()) - { - // Handle CRLF, CR, or LF as line ending. - if (c == '\r' || (c == '\n' && lastc != '\r')) - { - if (++cnt == num) - break; - } - - lastc = c; - } - - // Maybe eat the following \n if \r was just met. - if (c == '\r' && is.peek () == '\n') - is.get (); - - if (is.bad ()) - { - err = true; - error (who, "read error"); - } - - if (err) - cnt = -1; - } - - return cnt; - } - - template - static std::istream& - octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, - T *valptr) - { - T value = T (); - - is >> std::ws; // skip through whitespace and advance stream pointer - std::streampos pos = is.tellg (); - - switch (fmt.type) - { - case 'o': - is >> std::oct >> value >> std::dec; - break; - - case 'x': - case 'X': - is >> std::hex >> value >> std::dec; - break; - - case 'i': - { - int c1 = is.get (); - - if (c1 != std::istream::traits_type::eof ()) - { - if (c1 == '0') - { - int c2 = is.peek (); - - if (c2 == 'x' || c2 == 'X') - { - is.ignore (); - if (std::isxdigit (is.peek ())) - is >> std::hex >> value >> std::dec; + if (ov.isreal ()) // cat does type conversion + ov = cat_op (ov, octave_value (v), row); else - value = 0; - } - else - { - if (c2 == '0' || c2 == '1' || c2 == '2' - || c2 == '3' || c2 == '4' || c2 == '5' - || c2 == '6' || c2 == '7') - is >> std::oct >> value >> std::dec; - else if (c2 == '8' || c2 == '9') - { - // FIXME: Would like to set error state on octave - // stream. See bug #46493. But only std::istream is - // input to fcn. - // error ("internal failure to match octal format"); - value = 0; - } - else - value = 0; + ov.internal_rep ()->fast_elem_insert (row(0), v); } } else { - is.putback (c1); - - is >> value; + if (ov.isreal () && v.imag () == 0) + ov.internal_rep ()->fast_elem_insert (row(0), + float (v.real ())); + else + { + if (ov.isreal ()) // cat does type conversion + ov = cat_op (ov, octave_value (v), row); + else + ov.internal_rep ()->fast_elem_insert (row(0), + FloatComplex (v)); + } + } + } + } + else + { + double v; // Matlab docs say 1e30 etc should be valid for %d and + // 1000 as a %d8 should be 127, so read as double. + // Some loss of precision for d64 and u64. + skip_whitespace (is); + v = read_double (is, fmt); + if (! fmt.discard && ! is.fail ()) + switch (fmt.bitwidth) + { + case 64: + switch (fmt.type) + { + case 'd': + { + octave_int64 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + break; + + case 'u': + { + octave_uint64 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + break; + } + break; + + case 32: + switch (fmt.type) + { + case 'd': + { + octave_int32 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + break; + + case 'u': + { + octave_uint32 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + break; + } + break; + + case 16: + if (fmt.type == 'd') + { + octave_int16 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + else + { + octave_uint16 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + break; + + case 8: + if (fmt.type == 'd') + { + octave_int8 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + else + { + octave_uint8 vv = v; + ov.internal_rep ()->fast_elem_insert (row(0), vv); + } + break; + } + } + + if (is.fail () & ! fmt.discard) + ov = cat_op (ov, m_empty_value, row); + } + else + { + std::string vv (" "); // initial buffer. Grows as needed + switch (fmt.type) + { + case 's': + scan_string (is, fmt, vv); + break; + + case 'q': + scan_qstring (is, fmt, vv); + break; + + case 'c': + scan_cstring (is, fmt, vv); + break; + + case '[': + scan_bracket (is, fmt.char_class.c_str (), vv); + break; + + case '^': + scan_caret (is, fmt.char_class.c_str (), vv); + break; + } + + if (! fmt.discard) + ov.internal_rep ()->fast_elem_insert (row (0), + Cell (octave_value (vv))); + + // FIXME: why does failbit get set at EOF, instead of eofbit? + if (! vv.empty ()) + is.clear (is.rdstate () & ~std::ios_base::failbit); + } + + is.field_done (); +} + +// Read data corresponding to the entire format string once, placing the +// values in row ROW of retval. + +int +textscan::read_format_once (delimited_stream& is, + textscan_format_list& fmt_list, + std::list& retval, + Array row, int& done_after) +{ + const textscan_format_elt *elem = fmt_list.first (); + auto out = retval.begin (); + bool no_conversions = true; + bool done = false; + bool conversion_failed = false; // Record for ReturnOnError + bool nothing_worked = true; + + octave_quit (); + + for (std::size_t i = 0; i < fmt_list.numel (); i++) + { + bool this_conversion_failed = false; + + // Clear fail of previous numeric conversions. + is.clear (); + + switch (elem->type) + { + case 'C': + case 'D': + warning ("%s: conversion %c not yet implemented", + m_who.c_str (), elem->type); + break; + + case 'u': + case 'd': + case 'f': + case 'n': + case 's': + case '[': + case '^': + case 'q': + case 'c': + scan_one (is, *elem, *out, row); + break; + + case textscan_format_elt::literal_conversion : + match_literal (is, *elem); + break; + + default: + error ("Unknown format element '%c'", elem->type); + } + + if (! is.fail ()) + { + if (! elem->discard) + no_conversions = false; + } + else + { + is.clear (is.rdstate () & ~std::ios::failbit); + + if (! is.eof ()) + { + if (m_delim_list.isempty ()) + { + if (! is_delim (is.peek_undelim ())) + this_conversion_failed = true; + } + else // Cell array of multi-character delimiters + { + char *pos = is.tellg (); + if (-1 == lookahead (is, m_delim_list, m_delim_len)) + this_conversion_failed = true; + is.clear (); + is.seekg (pos); // reset to position before look-ahead } } } - break; - - default: - is >> value; - break; + + if (! elem->discard) + out++; + + elem = fmt_list.next (); + char *pos = is.tellg (); + + // 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 ()) + { + if (! done) + done_after = i+1; + + // note EOF, but process others to get empty_val. + done = true; + } + + if (this_conversion_failed) + { + if (is.tellg () == pos && ! conversion_failed) + { + // done_after = first failure + done_after = i; // note fail, but parse others to get empty_val + conversion_failed = true; + } + else + this_conversion_failed = false; + } + else if (! done && ! conversion_failed) + nothing_worked = false; + } + + if (done) + is.setstate (std::ios::eofbit); + + return no_conversions + + (is.eof () ? 2 : 0) + + (conversion_failed ? 4 : 0) + + (nothing_worked ? 8 : 0); + +} + +void +textscan::parse_options (const octave_value_list& args, + textscan_format_list& fmt_list) +{ + int last = args.length (); + int n = last; + + if (n & 1) + error ("%s: %d parameters given, but only %d values", + m_who.c_str (), n-n/2, n/2); + + m_delim_len = 1; + bool have_delims = false; + for (int i = 0; i < last; i += 2) + { + std::string param = args(i).xstring_value ("%s: Invalid parameter type <%s> for parameter %d", + m_who.c_str (), + args(i).type_name ().c_str (), + i/2 + 1); + std::transform (param.begin (), param.end (), param.begin (), ::tolower); + + if (param == "delimiter") + { + bool invalid = true; + if (args(i+1).is_string ()) + { + invalid = false; + have_delims = true; + m_delims = args(i+1).string_value (); + if (args(i+1).is_sq_string ()) + m_delims = do_string_escapes (m_delims); + } + else if (args(i+1).iscell ()) + { + invalid = false; + m_delim_list = args(i+1).cell_value (); + m_delim_table = " "; // non-empty, to flag non-default delim + + // Check that all elements are strings, and find max length + for (int j = 0; j < m_delim_list.numel (); j++) + { + if (! m_delim_list(j).is_string ()) + invalid = true; + else + { + if (m_delim_list(j).is_sq_string ()) + m_delim_list(j) = do_string_escapes (m_delim_list(j) + .string_value ()); + octave_idx_type len = m_delim_list(j).string_value () + .length (); + m_delim_len = std::max (static_cast (len), + m_delim_len); + } + } + } + if (invalid) + error ("%s: Delimiters must be either a string or cell array of strings", + m_who.c_str ()); + } + else if (param == "commentstyle") + { + if (args(i+1).is_string ()) + { + // check here for names like "C++", "C", "shell", ...? + m_comment_style = Cell (args(i+1)); + } + else if (args(i+1).iscell ()) + { + m_comment_style = args(i+1).cell_value (); + int len = m_comment_style.numel (); + if ((len >= 1 && ! m_comment_style (0).is_string ()) + || (len >= 2 && ! m_comment_style (1).is_string ()) + || (len >= 3)) + error ("%s: CommentStyle must be either a string or cell array of one or two strings", + m_who.c_str ()); + } + else + error ("%s: CommentStyle must be either a string or cell array of one or two strings", + m_who.c_str ()); + + // How far ahead do we need to look to detect an open comment + // and which character do we look for? + if (m_comment_style.numel () >= 1) + { + m_comment_len = m_comment_style (0).string_value ().size (); + m_comment_char = m_comment_style (0).string_value ()[0]; + } + } + else if (param == "treatasempty") + { + bool invalid = false; + if (args(i+1).is_string ()) + { + m_treat_as_empty = Cell (args(i+1)); + m_treat_as_empty_len = args(i+1).string_value ().size (); + } + else if (args(i+1).iscell ()) + { + m_treat_as_empty = args(i+1).cell_value (); + for (int j = 0; j < m_treat_as_empty.numel (); j++) + if (! m_treat_as_empty (j).is_string ()) + invalid = true; + else + { + int k = m_treat_as_empty (j).string_value ().size (); + if (k > m_treat_as_empty_len) + m_treat_as_empty_len = k; + } + } + if (invalid) + error ("%s: TreatAsEmpty must be either a string or cell array of one or two strings", + m_who.c_str ()); + + // FIXME: Ensure none is a prefix of a later one. Sort by length? + } + else if (param == "collectoutput") + { + m_collect_output = args(i+1).xbool_value ("%s: CollectOutput must be logical or numeric", + m_who.c_str ()); + } + else if (param == "emptyvalue") + { + m_empty_value = args(i+1).xscalar_value ("%s: EmptyValue must be numeric", m_who.c_str ()); + } + else if (param == "headerlines") + { + m_header_lines = args(i+1).xscalar_value ("%s: HeaderLines must be numeric", m_who.c_str ()); + } + else if (param == "bufsize") + { + m_buffer_size = args(i+1).xscalar_value ("%s: BufSize must be numeric", m_who.c_str ()); + } + else if (param == "multipledelimsasone") + { + multiple_delims_as_one = args(i + +1).xbool_value ("%s: MultipleDelimsAsOne must be logical or numeric", m_who.c_str ()); + } + else if (param == "returnonerror") + { + m_return_on_error = args(i+1).xbool_value ("%s: ReturnOnError must be logical or numeric", + m_who.c_str ()); + } + else if (param == "whitespace") + { + m_whitespace = args(i+1).xstring_value ("%s: Whitespace must be a character string", + m_who.c_str ()); + } + else if (param == "expchars") + { + m_exp_chars = args(i+1).xstring_value ("%s: ExpChars must be a character string", m_who.c_str ()); + m_default_exp = false; + } + else if (param == "endofline") + { + bool valid = true; + std::string s = args(i+1).xstring_value (R"(%s: EndOfLine must be at most one character or '\r\n')", + m_who.c_str ()); + if (args(i+1).is_sq_string ()) + s = do_string_escapes (s); + int l = s.length (); + if (l == 0) + m_eol1 = m_eol2 = -2; + else if (l == 1) + m_eol1 = m_eol2 = s.c_str ()[0]; + else if (l == 2) + { + m_eol1 = s.c_str ()[0]; + m_eol2 = s.c_str ()[1]; + if (m_eol1 != '\r' || m_eol2 != '\n') // Why limit it? + valid = false; + } + else + valid = false; + + if (! valid) + error (R"(%s: EndOfLine must be at most one character or '\r\n')", + m_who.c_str ()); + } + else + error ("%s: unrecognized option '%s'", m_who.c_str (), param.c_str ()); + } + + // Remove any user-supplied delimiter from whitespace list + for (unsigned int j = 0; j < m_delims.length (); j++) + { + m_whitespace.erase (std::remove (m_whitespace.begin (), + m_whitespace.end (), + m_delims[j]), + m_whitespace.end ()); + } + for (int j = 0; j < m_delim_list.numel (); j++) + { + std::string delim = m_delim_list(j).string_value (); + if (delim.length () == 1) + m_whitespace.erase (std::remove (m_whitespace.begin (), + m_whitespace.end (), + delim[0]), + m_whitespace.end ()); + } + + m_whitespace_table = std::string (256, '\0'); + for (unsigned int i = 0; i < m_whitespace.length (); i++) + m_whitespace_table[m_whitespace[i]] = '1'; + + // For Matlab compatibility, add 0x20 to whitespace, unless + // whitespace is explicitly ignored. + if (! (m_whitespace.empty () && fmt_list.has_string)) + m_whitespace_table[' '] = '1'; + + // Create look-up table of delimiters, based on 'delimiter' + m_delim_table = std::string (256, '\0'); + if (m_eol1 >= 0 && m_eol1 < 256) + m_delim_table[m_eol1] = '1'; // EOL is always a delimiter + if (m_eol2 >= 0 && m_eol2 < 256) + m_delim_table[m_eol2] = '1'; // EOL is always a delimiter + if (! have_delims) + for (unsigned int i = 0; i < 256; i++) + { + if (isspace (i)) + m_delim_table[i] = '1'; } + else + for (unsigned int i = 0; i < m_delims.length (); i++) + m_delim_table[m_delims[i]] = '1'; +} + +// Skip comments, and characters specified by the "Whitespace" option. +// If EOLstop == true, don't skip end of line. + +int +textscan::skip_whitespace (delimited_stream& is, bool EOLstop) +{ + int c1 = std::istream::traits_type::eof (); + bool found_comment = false; + + do + { + found_comment = false; + int prev = -1; + while (is + && (c1 = is.get_undelim ()) != std::istream::traits_type::eof () + && ( ( (c1 == m_eol1 || c1 == m_eol2) && ++m_lines && ! EOLstop) + || isspace (c1))) + { + if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2) + m_lines--; + prev = c1; + } + + if (c1 == m_comment_char) // see if we match an open comment + { + // save stream state in case we have to restore it + char *pos = is.tellg (); + std::ios::iostate state = is.rdstate (); + + std::string tmp (m_comment_len, '\0'); + char *look = is.read (&tmp[0], m_comment_len-1, pos); // already read first char + if (is && m_comment_style.numel () > 0 + && ! strncmp (m_comment_style(0).string_value ().substr (1).c_str (), + look, m_comment_len-1)) + { + found_comment = true; + + std::string dummy; + if (m_comment_style.numel () == 1) // skip to end of line + { + std::string eol (3, '\0'); + eol[0] = m_eol1; + eol[1] = m_eol2; + + scan_caret (is, eol, dummy); + c1 = is.get_undelim (); + if (c1 == m_eol1 && m_eol1 != m_eol2 + && is.peek_undelim () == m_eol2) + is.get_undelim (); + m_lines++; + } + else // matching pair + { + std::string end_c = m_comment_style(1).string_value (); + // last char of end-comment sequence + std::string last = end_c.substr (end_c.size () - 1); + std::string may_match (""); + do + { + // find sequence ending with last char + scan_caret (is, last, dummy); + is.get_undelim (); // (read LAST itself) + + may_match = may_match + dummy + last; + if (may_match.length () > end_c.length ()) + { + std::size_t start = may_match.length () + - end_c.length (); + may_match = may_match.substr (start); + } + } + while (may_match != end_c && is && ! is.eof ()); + } + } + else // wasn't really a comment; restore state + { + is.clear (state); + is.seekg (pos); + } + } + } + while (found_comment); + + if (c1 != std::istream::traits_type::eof ()) + is.putback (c1); + + return c1; +} + +// See if the next few characters match one of the strings in target. +// For efficiency, MAX_LEN is the cached longest length of any target. +// Return -1 if none is found, or the index of the match. + +int +textscan::lookahead (delimited_stream& is, const Cell& targets, int max_len, + bool case_sensitive) const +{ + // target strings may be different sizes. + // Read ahead longest, put it all back, then re-read the string + // that matches. + + char *pos = is.tellg (); + + std::string tmp (max_len, '\0'); + char *look = is.read (&tmp[0], tmp.size (), pos); + + is.clear (); + is.seekg (pos); // reset to position before read + // FIXME: pos may be corrupted by is.read + + int i; + int (*compare)(const char *, const char *, std::size_t); + compare = (case_sensitive ? strncmp : octave_strncasecmp); + + for (i = 0; i < targets.numel (); i++) + { + std::string s = targets (i).string_value (); + if (! (*compare) (s.c_str (), look, s.size ())) + { + is.read (&tmp[0], s.size (), pos); // read just the right amount + break; + } + } + + if (i == targets.numel ()) + i = -1; + + return i; +} + +// Skip delimiters -- multiple if MultipleDelimsAsOne specified. +int +textscan::skip_delim (delimited_stream& is) +{ + int c1 = skip_whitespace (is); // Stop once EOL is read + if (m_delim_list.numel () == 0) // single character delimiter + { + if (is_delim (c1) || c1 == m_eol1 || c1 == m_eol2) + { + is.get (); + if (c1 == m_eol1 && is.peek_undelim () == m_eol2) + is.get (); // if \r\n, skip the \n too. + + if (multiple_delims_as_one) + { + int prev = -1; + // skip multiple delims. + // Increment lines for each end-of-line seen; + // Decrement for \r\n + while (is && ((c1 = is.get_undelim ()) + != std::istream::traits_type::eof ()) + && (((c1 == m_eol1 || c1 == m_eol2) && ++m_lines) + || isspace (c1) || is_delim (c1))) + { + if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2) + m_lines--; + prev = c1; + } + if (c1 != std::istream::traits_type::eof ()) + is.putback (c1); + } + } + } + else // multi-character delimiter + { + int first_match; + + if (c1 == m_eol1 || c1 == m_eol2 + || (-1 != (first_match = lookahead (is, m_delim_list, m_delim_len)))) + { + if (c1 == m_eol1) + { + is.get_undelim (); + if (is.peek_undelim () == m_eol2) + is.get_undelim (); + } + else if (c1 == m_eol2) + { + is.get_undelim (); + } + + if (multiple_delims_as_one) + { + int prev = -1; + // skip multiple delims. + // Increment lines for each end-of-line seen; + // decrement for \r\n. + while (is && ((c1 = skip_whitespace (is)) + != std::istream::traits_type::eof ()) + && (((c1 == m_eol1 || c1 == m_eol2) && ++m_lines) + || -1 != lookahead (is, m_delim_list, m_delim_len))) + { + if (prev == m_eol1 && m_eol1 != m_eol2 && c1 == m_eol2) + m_lines--; + prev = c1; + } + } + } + } + + return c1; +} + +// Read in as much of the input as coincides with the literal in the +// format string. Return "true" if the entire literal is matched, else +// false (and set failbit). + +bool +textscan::match_literal (delimited_stream& is, + const textscan_format_elt& fmt) +{ + // "false" -> treat EOL as normal space + // since a delimiter at the start of a line is a mismatch, not empty field + skip_whitespace (is, false); + + for (unsigned int i = 0; i < fmt.width; i++) + { + int ch = is.get_undelim (); + if (ch != fmt.text[i]) + { + if (ch != std::istream::traits_type::eof ()) + is.putback (ch); + is.setstate (std::ios::failbit); + return false; + } + } + return true; +} + +void +base_stream::error (const std::string& msg) +{ + m_fail = true; + m_errmsg = msg; +} + +void +base_stream::error (const std::string& who, const std::string& msg) +{ + m_fail = true; + m_errmsg = who + ": " + msg; +} + +void +base_stream::clear (void) +{ + m_fail = false; + m_errmsg = ""; +} + +void +base_stream::clearerr (void) +{ + std::istream *is = input_stream (); + std::ostream *os = preferred_output_stream (); + + if (is) + is->clear (); + + if (os) + os->clear (); +} + +// Functions that are defined for all input streams (input streams +// are those that define is). + +std::string +base_stream::do_gets (octave_idx_type max_len, bool& err, + bool strip_newline, const std::string& who) +{ + interpreter& interp = __get_interpreter__ (); + + if (interp.interactive () && file_number () == 0) + ::error ("%s: unable to read from stdin while running interactively", + who.c_str ()); + + std::string retval; + + err = false; + + std::istream *isp = input_stream (); + + if (! isp) + { + err = true; + invalid_operation (who, "reading"); + } + else + { + std::istream& is = *isp; + + std::ostringstream buf; + + int c = 0; + int char_count = 0; + + if (max_len != 0) + { + while (is && (c = is.get ()) != std::istream::traits_type::eof ()) + { + char_count++; + + // Handle CRLF, CR, or LF as line ending. + if (c == '\r') + { + if (! strip_newline) + buf << static_cast (c); + + c = is.get (); + + if (c != std::istream::traits_type::eof ()) + { + if (c == '\n') + { + char_count++; + + if (! strip_newline) + buf << static_cast (c); + } + else + is.putback (c); + } + + break; + } + else if (c == '\n') + { + if (! strip_newline) + buf << static_cast (c); + + break; + } + else + buf << static_cast (c); + + if (max_len > 0 && char_count == max_len) + break; + } + } + + if (! is.eof () && char_count > 0) + { + // GAGME. Matlab seems to check for EOF even if the last character + // in a file is a newline character. This is NOT what the + // corresponding C-library functions do. + int disgusting_compatibility_hack = is.get (); + if (! is.eof ()) + is.putback (disgusting_compatibility_hack); + } + + if (is.good () || (is.eof () && char_count > 0)) + { + retval = buf.str (); + if (encoding ().compare ("utf-8")) + retval = string::u8_from_encoding (who, retval, encoding ()); + } + else + { + err = true; + + if (is.eof () && char_count == 0) + error (who, "at end of file"); + else + error (who, "read error"); + } + } + + return retval; +} + +std::string +base_stream::getl (octave_idx_type max_len, bool& err, + const std::string& who) +{ + return do_gets (max_len, err, true, who); +} + +std::string +base_stream::gets (octave_idx_type max_len, bool& err, + const std::string& who) +{ + return do_gets (max_len, err, false, who); +} + +off_t +base_stream::skipl (off_t num, bool& err, const std::string& who) +{ + interpreter& interp = __get_interpreter__ (); + + if (interp.interactive () && file_number () == 0) + ::error ("%s: unable to read from stdin while running interactively", + who.c_str ()); + + off_t cnt = -1; + + err = false; + + std::istream *isp = input_stream (); + + if (! isp) + { + err = true; + invalid_operation (who, "reading"); + } + else + { + std::istream& is = *isp; + + int c = 0; + int lastc = -1; + cnt = 0; + + while (is && (c = is.get ()) != std::istream::traits_type::eof ()) + { + // Handle CRLF, CR, or LF as line ending. + if (c == '\r' || (c == '\n' && lastc != '\r')) + { + if (++cnt == num) + break; + } + + lastc = c; + } + + // Maybe eat the following \n if \r was just met. + if (c == '\r' && is.peek () == '\n') + is.get (); + + if (is.bad ()) + { + err = true; + error (who, "read error"); + } + + if (err) + cnt = -1; + } + + return cnt; +} + +template +static std::istream& +octave_scan_1 (std::istream& is, const scanf_format_elt& fmt, + T *valptr) +{ + T value = T (); + + is >> std::ws; // skip through whitespace and advance stream pointer + std::streampos pos = is.tellg (); + + switch (fmt.type) + { + case 'o': + is >> std::oct >> value >> std::dec; + break; + + case 'x': + case 'X': + is >> std::hex >> value >> std::dec; + break; + + case 'i': + { + int c1 = is.get (); + + if (c1 != std::istream::traits_type::eof ()) + { + if (c1 == '0') + { + int c2 = is.peek (); + + if (c2 == 'x' || c2 == 'X') + { + is.ignore (); + if (std::isxdigit (is.peek ())) + is >> std::hex >> value >> std::dec; + else + value = 0; + } + else + { + if (c2 == '0' || c2 == '1' || c2 == '2' + || c2 == '3' || c2 == '4' || c2 == '5' + || c2 == '6' || c2 == '7') + is >> std::oct >> value >> std::dec; + else if (c2 == '8' || c2 == '9') + { + // FIXME: Would like to set error state on octave + // stream. See bug #46493. But only std::istream is + // input to fcn. + // error ("internal failure to match octal format"); + value = 0; + } + else + value = 0; + } + } + else + { + is.putback (c1); + + is >> value; + } + } + } + break; + + default: + is >> value; + break; + } std::ios::iostate status = is.rdstate (); if (! (status & std::ios::failbit)) @@ -4375,78 +4381,78 @@ } } - return is; - } - - template - static std::istream& - octave_scan (std::istream& is, const scanf_format_elt& fmt, T *valptr) - { - if (fmt.width) + return is; +} + +template +static std::istream& +octave_scan (std::istream& is, const scanf_format_elt& fmt, T *valptr) +{ + if (fmt.width) + { + // Limit input to fmt.width characters by reading into a + // temporary stringstream buffer. + std::string strbuf; + + auto orig_pos = is.tellg (); + + is.width (fmt.width); + is >> strbuf; + + std::istringstream ss (strbuf); + + octave_scan_1 (ss, fmt, valptr); + + if (! ss.eof ()) + { + // If fewer characters than width were used to read a number then + // the original istream object positioning is incorrect. + // Rather than attempt to update istream state and positioning, + // just redo the '>>' operation with the correct width so that + // all flags get set correctly. + + is.clear (); // Clear EOF, FAILBIT, BADBIT + is.seekg (orig_pos, is.beg); + + int chars_read = ss.tellg (); + if (chars_read > 0) + { + is.width (chars_read); + is >> strbuf; + } + } + + // If pattern failed to match then propagate fail bit to 'is' stream. + if (ss.fail ()) + is.setstate (std::ios::failbit); + + } + else + octave_scan_1 (is, fmt, valptr); + + return is; +} + +template <> +std::istream& +octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double *valptr) +{ + double& ref = *valptr; + + switch (fmt.type) + { + case 'e': + case 'f': + case 'g': + case 'E': + case 'G': { - // Limit input to fmt.width characters by reading into a - // temporary stringstream buffer. - std::string strbuf; - - auto orig_pos = is.tellg (); - - is.width (fmt.width); - is >> strbuf; - - std::istringstream ss (strbuf); - - octave_scan_1 (ss, fmt, valptr); - - if (! ss.eof ()) - { - // If fewer characters than width were used to read a number then - // the original istream object positioning is incorrect. - // Rather than attempt to update istream state and positioning, - // just redo the '>>' operation with the correct width so that - // all flags get set correctly. - - is.clear (); // Clear EOF, FAILBIT, BADBIT - is.seekg (orig_pos, is.beg); - - int chars_read = ss.tellg (); - if (chars_read > 0) - { - is.width (chars_read); - is >> strbuf; - } - } - - // If pattern failed to match then propagate fail bit to 'is' stream. - if (ss.fail ()) - is.setstate (std::ios::failbit); - - } - else - octave_scan_1 (is, fmt, valptr); - - return is; - } - - template <> - std::istream& - octave_scan<> (std::istream& is, const scanf_format_elt& fmt, double *valptr) - { - double& ref = *valptr; - - switch (fmt.type) - { - case 'e': - case 'f': - case 'g': - case 'E': - case 'G': - { is >> std::ws; // skip through whitespace and advance stream pointer if (is.good ()) - { + { std::streampos pos = is.tellg (); - ref = read_value (is); + ref = read_value (is); std::ios::iostate status = is.rdstate (); if (status & std::ios::failbit) @@ -4455,53 +4461,53 @@ is.seekg (pos); is.setstate (status & ~std::ios_base::eofbit); } - } - } - break; - - default: - panic_impossible (); - break; + } } - - return is; - } - - template - static void - do_scanf_conv (std::istream& is, const scanf_format_elt& fmt, - T valptr, Matrix& mval, double *data, octave_idx_type& idx, - octave_idx_type& conversion_count, octave_idx_type nr, - octave_idx_type max_size, bool discard) - { - octave_scan (is, fmt, valptr); - - if (! is) - return; - - if (idx == max_size && ! discard) - { - max_size *= 2; - - if (nr > 0) - mval.resize (nr, max_size / nr, 0.0); - else - mval.resize (max_size, 1, 0.0); - - data = mval.fortran_vec (); - } - - if (! discard) - { - conversion_count++; - data[idx++] = *(valptr); - } - } - - template void - do_scanf_conv (std::istream&, const scanf_format_elt&, double *, - Matrix&, double *, octave_idx_type&, octave_idx_type&, - octave_idx_type, octave_idx_type, bool); + break; + + default: + panic_impossible (); + break; + } + + return is; +} + +template +static void +do_scanf_conv (std::istream& is, const scanf_format_elt& fmt, + T valptr, Matrix& mval, double *data, octave_idx_type& idx, + octave_idx_type& conversion_count, octave_idx_type nr, + octave_idx_type max_size, bool discard) +{ + octave_scan (is, fmt, valptr); + + if (! is) + return; + + if (idx == max_size && ! discard) + { + max_size *= 2; + + if (nr > 0) + mval.resize (nr, max_size / nr, 0.0); + else + mval.resize (max_size, 1, 0.0); + + data = mval.fortran_vec (); + } + + if (! discard) + { + conversion_count++; + data[idx++] = *(valptr); + } +} + +template void +do_scanf_conv (std::istream&, const scanf_format_elt&, double *, + Matrix&, double *, octave_idx_type&, octave_idx_type&, + octave_idx_type, octave_idx_type, bool); #define DO_WHITESPACE_CONVERSION() \ do \ @@ -4587,8 +4593,8 @@ \ tmp.resize (n) - // For a '%s' format, skip initial whitespace and then read until the - // next whitespace character or until WIDTH characters have been read. +// For a '%s' format, skip initial whitespace and then read until the +// next whitespace character or until WIDTH characters have been read. #define BEGIN_S_CONVERSION() \ int width = elt->width; \ \ @@ -4637,7 +4643,7 @@ } \ while (0) - // This format must match a nonempty sequence of characters. +// This format must match a nonempty sequence of characters. #define BEGIN_CHAR_CLASS_CONVERSION() \ int width = (elt->width ? elt->width \ : std::numeric_limits::max ()); \ @@ -4739,1796 +4745,1796 @@ } \ while (0) - octave_value - base_stream::do_scanf (scanf_format_list& fmt_list, - octave_idx_type nr, octave_idx_type nc, - bool one_elt_size_spec, - octave_idx_type& conversion_count, - const std::string& who) - { - interpreter& interp = __get_interpreter__ (); - - if (interp.interactive () && file_number () == 0) - ::error ("%s: unable to read from stdin while running interactively", - who.c_str ()); - - octave_value retval = Matrix (); - - conversion_count = 0; - - octave_idx_type m_nconv = fmt_list.num_conversions (); - - octave_idx_type data_index = 0; - - if (nr == 0 || nc == 0) - { - if (one_elt_size_spec) - nc = 0; - - return Matrix (nr, nc, 0.0); - } - - std::istream *isp = input_stream (); - - bool all_char_conv = fmt_list.all_character_conversions (); - - Matrix mval; - octave_idx_type max_size = 0; - octave_idx_type max_conv = 0; - - octave_idx_type final_nr = 0; - octave_idx_type final_nc = 0; - - if (all_char_conv) - { - // Any of these could be resized later (if we have %s conversions, - // we may read more than one element for each conversion). - if (one_elt_size_spec) - { - max_size = 512; - mval.resize (1, max_size, 0.0); - - if (nr > 0) - max_conv = nr; - } - else if (nr > 0) - { - if (nc > 0) - { - mval.resize (nr, nc, 0.0); - max_size = max_conv = nr * nc; - } - else - { - mval.resize (nr, 32, 0.0); - max_size = nr * 32; - } - } - else - panic_impossible (); - } - else if (nr > 0) - { - if (nc > 0) - { - // Will not resize later. - mval.resize (nr, nc, 0.0); - max_size = nr * nc; - max_conv = max_size; - } - else - { - // Maybe resize later. - mval.resize (nr, 32, 0.0); - max_size = nr * 32; - } - } - else - { - // Maybe resize later. - mval.resize (32, 1, 0.0); - max_size = 32; - } - - double *data = mval.fortran_vec (); - - if (isp) - { - std::istream& is = *isp; - - const scanf_format_elt *elt = fmt_list.first (); - - std::ios::fmtflags flags = is.flags (); - - octave_idx_type trips = 0; - - octave_idx_type num_fmt_elts = fmt_list.length (); - - for (;;) - { - octave_quit (); - - if (elt) - { - if (elt->type == scanf_format_elt::null - || (! (elt->type == scanf_format_elt::whitespace_conversion - || elt->type == scanf_format_elt::literal_conversion - || elt->type == '%') - && max_conv > 0 && conversion_count == max_conv)) - { - // We are done, either because we have reached the end of - // the format string and are not cycling through the format - // again or because we've converted all the values that - // have been requested and the next format element is a - // conversion. Determine final array size and exit. - if (all_char_conv && one_elt_size_spec) - { - final_nr = 1; - final_nc = data_index; - } - else - { - final_nr = nr; - final_nc = (data_index - 1) / nr + 1; - } - - break; - } - else if (data_index == max_size) - { - max_size *= 2; - - if (all_char_conv) - { - if (one_elt_size_spec) - mval.resize (1, max_size, 0.0); - else if (nr > 0) - mval.resize (nr, max_size / nr, 0.0); - else - panic_impossible (); - } - else if (nr > 0) - mval.resize (nr, max_size / nr, 0.0); - else - mval.resize (max_size, 1, 0.0); - - data = mval.fortran_vec (); - } - - std::string fmt = elt->text; - - bool discard = elt->discard; - - switch (elt->type) - { - case scanf_format_elt::whitespace_conversion: - DO_WHITESPACE_CONVERSION (); - break; - - case scanf_format_elt::literal_conversion: - DO_LITERAL_CONVERSION (); - break; - - case '%': - DO_PCT_CONVERSION (); - break; - - case 'd': case 'i': +octave_value +base_stream::do_scanf (scanf_format_list& fmt_list, + octave_idx_type nr, octave_idx_type nc, + bool one_elt_size_spec, + octave_idx_type& conversion_count, + const std::string& who) +{ + interpreter& interp = __get_interpreter__ (); + + if (interp.interactive () && file_number () == 0) + ::error ("%s: unable to read from stdin while running interactively", + who.c_str ()); + + octave_value retval = Matrix (); + + conversion_count = 0; + + octave_idx_type m_nconv = fmt_list.num_conversions (); + + octave_idx_type data_index = 0; + + if (nr == 0 || nc == 0) + { + if (one_elt_size_spec) + nc = 0; + + return Matrix (nr, nc, 0.0); + } + + std::istream *isp = input_stream (); + + bool all_char_conv = fmt_list.all_character_conversions (); + + Matrix mval; + octave_idx_type max_size = 0; + octave_idx_type max_conv = 0; + + octave_idx_type final_nr = 0; + octave_idx_type final_nc = 0; + + if (all_char_conv) + { + // Any of these could be resized later (if we have %s conversions, + // we may read more than one element for each conversion). + if (one_elt_size_spec) + { + max_size = 512; + mval.resize (1, max_size, 0.0); + + if (nr > 0) + max_conv = nr; + } + else if (nr > 0) + { + if (nc > 0) + { + mval.resize (nr, nc, 0.0); + max_size = max_conv = nr * nc; + } + else + { + mval.resize (nr, 32, 0.0); + max_size = nr * 32; + } + } + else + panic_impossible (); + } + else if (nr > 0) + { + if (nc > 0) + { + // Will not resize later. + mval.resize (nr, nc, 0.0); + max_size = nr * nc; + max_conv = max_size; + } + else + { + // Maybe resize later. + mval.resize (nr, 32, 0.0); + max_size = nr * 32; + } + } + else + { + // Maybe resize later. + mval.resize (32, 1, 0.0); + max_size = 32; + } + + double *data = mval.fortran_vec (); + + if (isp) + { + std::istream& is = *isp; + + const scanf_format_elt *elt = fmt_list.first (); + + std::ios::fmtflags flags = is.flags (); + + octave_idx_type trips = 0; + + octave_idx_type num_fmt_elts = fmt_list.length (); + + for (;;) + { + octave_quit (); + + if (elt) + { + if (elt->type == scanf_format_elt::null + || (! (elt->type == scanf_format_elt::whitespace_conversion + || elt->type == scanf_format_elt::literal_conversion + || elt->type == '%') + && max_conv > 0 && conversion_count == max_conv)) + { + // We are done, either because we have reached the end of + // the format string and are not cycling through the format + // again or because we've converted all the values that + // have been requested and the next format element is a + // conversion. Determine final array size and exit. + if (all_char_conv && one_elt_size_spec) { - switch (elt->modifier) - { - case 'h': - { - int16_t tmp; - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); - } - break; - - case 'l': - { - int64_t tmp; - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); - } - break; - - default: - { - int32_t tmp; - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); - } - break; - } - } - break; - - case 'o': case 'u': case 'x': case 'X': - { - switch (elt->modifier) - { - case 'h': - { - uint16_t tmp; - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); - } - break; - - case 'l': - { - uint64_t tmp; - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); - } - break; - - default: - { - uint32_t tmp; - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); - } - break; - } + final_nr = 1; + final_nc = data_index; } - break; - - case 'e': case 'f': case 'g': - case 'E': case 'G': + else { - double tmp; - - do_scanf_conv (is, *elt, &tmp, mval, data, - data_index, conversion_count, - nr, max_size, discard); + final_nr = nr; + final_nc = (data_index - 1) / nr + 1; } - break; - - case 'c': - { - BEGIN_C_CONVERSION (); - - FINISH_CHARACTER_CONVERSION (); - - is.setf (flags); - } - break; - - case 's': + + break; + } + else if (data_index == max_size) + { + max_size *= 2; + + if (all_char_conv) { - BEGIN_S_CONVERSION (); - - FINISH_CHARACTER_CONVERSION (); - } - break; - - case '[': case '^': - { - BEGIN_CHAR_CLASS_CONVERSION (); - - FINISH_CHARACTER_CONVERSION (); + if (one_elt_size_spec) + mval.resize (1, max_size, 0.0); + else if (nr > 0) + mval.resize (nr, max_size / nr, 0.0); + else + panic_impossible (); } - break; - - case 'p': - error (who, "unsupported format specifier"); - break; - - default: - error (who, "internal format error"); - break; - } - - if (! ok ()) - { - break; - } - else if (is.eof () || ! is) + else if (nr > 0) + mval.resize (nr, max_size / nr, 0.0); + else + mval.resize (max_size, 1, 0.0); + + data = mval.fortran_vec (); + } + + std::string fmt = elt->text; + + bool discard = elt->discard; + + switch (elt->type) + { + case scanf_format_elt::whitespace_conversion: + DO_WHITESPACE_CONVERSION (); + break; + + case scanf_format_elt::literal_conversion: + DO_LITERAL_CONVERSION (); + break; + + case '%': + DO_PCT_CONVERSION (); + break; + + case 'd': case 'i': { - if (all_char_conv) - { - if (one_elt_size_spec) - { - final_nr = 1; - final_nc = data_index; - } - else if (data_index > nr) - { - final_nr = nr; - final_nc = (data_index - 1) / nr + 1; - } - else - { - final_nr = data_index; - final_nc = 1; - } - } - else if (nr > 0) + switch (elt->modifier) { - if (data_index > nr) - { - final_nr = nr; - final_nc = (data_index - 1) / nr + 1; - } - else - { - final_nr = data_index; - final_nc = 1; - } - } - else - { - final_nr = data_index; - final_nc = 1; - } - - // If it looks like we have a matching failure, then - // reset the failbit in the stream state. - if (is.rdstate () & std::ios::failbit) - { - is.clear (is.rdstate () & (~std::ios::failbit)); - error (who, "format failed to match"); - } - - // FIXME: is this the right thing to do? - if (interp.interactive () - && ! application::forced_interactive () - && name () == "stdin") - { - is.clear (); - - // Skip to end of line. - bool err; - do_gets (-1, err, false, who); + case 'h': + { + int16_t tmp; + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); + } + break; + + case 'l': + { + int64_t tmp; + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); + } + break; + + default: + { + int32_t tmp; + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); + } + break; } - - break; - } - } - else - { - error (who, "internal format error"); - break; - } - - if (m_nconv == 0 && ++trips == num_fmt_elts) - { - if (all_char_conv && one_elt_size_spec) - { - final_nr = 1; - final_nc = data_index; - } - else - { - final_nr = nr; - final_nc = (data_index - 1) / nr + 1; - } - - break; - } - else - { - // Cycle through the format list more than once if we have some - // conversions to make and we haven't reached the limit on the - // number of values to convert (possibly because there is no - // specified limit). - elt = fmt_list.next (m_nconv > 0 - && (max_conv == 0 - || conversion_count < max_conv)); - } - } - } - - mval.resize (final_nr, final_nc, 0.0); - - retval = mval; - - if (all_char_conv) - retval = retval.convert_to_str (false, true); - - return retval; - } - - octave_value - base_stream::scanf (const std::string& fmt, const Array& size, - octave_idx_type& conversion_count, - const std::string& who) - { - octave_value retval = Matrix (); - - conversion_count = 0; - - std::istream *isp = input_stream (); - - if (! isp) - invalid_operation (who, "reading"); - else - { - scanf_format_list fmt_list (fmt); - - if (fmt_list.num_conversions () == -1) - ::error ("%s: invalid format specified", who.c_str ()); - - octave_idx_type nr = -1; - octave_idx_type nc = -1; - - bool one_elt_size_spec; - - get_size (size, nr, nc, one_elt_size_spec, who); - - retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec, - conversion_count, who); - } - - return retval; - } - - bool - base_stream::do_oscanf (const scanf_format_elt *elt, - octave_value& retval, const std::string& who) - { - std::istream *isp = input_stream (); - - if (! isp) - return false; - - bool quit = false; - - std::istream& is = *isp; - - std::ios::fmtflags flags = is.flags (); - - if (elt) - { - std::string fmt = elt->text; - - bool discard = elt->discard; - - switch (elt->type) - { - case scanf_format_elt::whitespace_conversion: - DO_WHITESPACE_CONVERSION (); - break; - - case scanf_format_elt::literal_conversion: - DO_LITERAL_CONVERSION (); - break; - - case '%': - { - DO_PCT_CONVERSION (); - - if (! is) - quit = true; - } - break; - - case 'd': case 'i': - { - switch (elt->modifier) - { - case 'h': - { - int16_t tmp; - if (octave_scan (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; } break; - case 'l': + case 'o': case 'u': case 'x': case 'X': { - int64_t tmp; - if (octave_scan (is, *elt, &tmp)) + switch (elt->modifier) { - if (! discard) - retval = tmp; + case 'h': + { + uint16_t tmp; + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); + } + break; + + case 'l': + { + uint64_t tmp; + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); + } + break; + + default: + { + uint32_t tmp; + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); + } + break; } - else - quit = true; + } + break; + + case 'e': case 'f': case 'g': + case 'E': case 'G': + { + double tmp; + + do_scanf_conv (is, *elt, &tmp, mval, data, + data_index, conversion_count, + nr, max_size, discard); } break; + case 'c': + { + BEGIN_C_CONVERSION (); + + FINISH_CHARACTER_CONVERSION (); + + is.setf (flags); + } + break; + + case 's': + { + BEGIN_S_CONVERSION (); + + FINISH_CHARACTER_CONVERSION (); + } + break; + + case '[': case '^': + { + BEGIN_CHAR_CLASS_CONVERSION (); + + FINISH_CHARACTER_CONVERSION (); + } + break; + + case 'p': + error (who, "unsupported format specifier"); + break; + default: - { - int32_t tmp; - if (octave_scan (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; - } + error (who, "internal format error"); + break; + } + + if (! ok ()) + { break; } - } - break; - - case 'o': case 'u': case 'x': case 'X': - { - switch (elt->modifier) + else if (is.eof () || ! is) { - case 'h': - { - uint16_t tmp; - if (octave_scan (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; - } - break; - - case 'l': - { - uint64_t tmp; - if (octave_scan (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; - } - break; - - default: - { - uint32_t tmp; - if (octave_scan (is, *elt, &tmp)) - { - if (! discard) - retval = tmp; - } - else - quit = true; - } + if (all_char_conv) + { + if (one_elt_size_spec) + { + final_nr = 1; + final_nc = data_index; + } + else if (data_index > nr) + { + final_nr = nr; + final_nc = (data_index - 1) / nr + 1; + } + else + { + final_nr = data_index; + final_nc = 1; + } + } + else if (nr > 0) + { + if (data_index > nr) + { + final_nr = nr; + final_nc = (data_index - 1) / nr + 1; + } + else + { + final_nr = data_index; + final_nc = 1; + } + } + else + { + final_nr = data_index; + final_nc = 1; + } + + // If it looks like we have a matching failure, then + // reset the failbit in the stream state. + if (is.rdstate () & std::ios::failbit) + { + is.clear (is.rdstate () & (~std::ios::failbit)); + error (who, "format failed to match"); + } + + // FIXME: is this the right thing to do? + if (interp.interactive () + && ! application::forced_interactive () + && name () == "stdin") + { + is.clear (); + + // Skip to end of line. + bool err; + do_gets (-1, err, false, who); + } + break; } } - break; - - case 'e': case 'f': case 'g': - case 'E': case 'G': + else { - double tmp; - - if (octave_scan (is, *elt, &tmp)) + error (who, "internal format error"); + break; + } + + if (m_nconv == 0 && ++trips == num_fmt_elts) + { + if (all_char_conv && one_elt_size_spec) { - if (! discard) - retval = tmp; + final_nr = 1; + final_nc = data_index; } else - quit = true; + { + final_nr = nr; + final_nc = (data_index - 1) / nr + 1; + } + + break; } - break; - - case 'c': - { - BEGIN_C_CONVERSION (); - - if (! discard) - retval = tmp; - - if (! is) - quit = true; - - is.setf (flags); - } - break; - - case 's': + else { - BEGIN_S_CONVERSION (); - - if (! discard) - retval = tmp; - - if (! is) - quit = true; + // Cycle through the format list more than once if we have some + // conversions to make and we haven't reached the limit on the + // number of values to convert (possibly because there is no + // specified limit). + elt = fmt_list.next (m_nconv > 0 + && (max_conv == 0 + || conversion_count < max_conv)); } - break; - - case '[': - case '^': - { - BEGIN_CHAR_CLASS_CONVERSION (); - - if (! discard) - retval = tmp; - - if (! is) - quit = true; - } - break; - - case 'p': - error (who, "unsupported format specifier"); - break; - - default: - error (who, "internal format error"); - break; + } + } + + mval.resize (final_nr, final_nc, 0.0); + + retval = mval; + + if (all_char_conv) + retval = retval.convert_to_str (false, true); + + return retval; +} + +octave_value +base_stream::scanf (const std::string& fmt, const Array& size, + octave_idx_type& conversion_count, + const std::string& who) +{ + octave_value retval = Matrix (); + + conversion_count = 0; + + std::istream *isp = input_stream (); + + if (! isp) + invalid_operation (who, "reading"); + else + { + scanf_format_list fmt_list (fmt); + + if (fmt_list.num_conversions () == -1) + ::error ("%s: invalid format specified", who.c_str ()); + + octave_idx_type nr = -1; + octave_idx_type nc = -1; + + bool one_elt_size_spec; + + get_size (size, nr, nc, one_elt_size_spec, who); + + retval = do_scanf (fmt_list, nr, nc, one_elt_size_spec, + conversion_count, who); + } + + return retval; +} + +bool +base_stream::do_oscanf (const scanf_format_elt *elt, + octave_value& retval, const std::string& who) +{ + std::istream *isp = input_stream (); + + if (! isp) + return false; + + bool quit = false; + + std::istream& is = *isp; + + std::ios::fmtflags flags = is.flags (); + + if (elt) + { + std::string fmt = elt->text; + + bool discard = elt->discard; + + switch (elt->type) + { + case scanf_format_elt::whitespace_conversion: + DO_WHITESPACE_CONVERSION (); + break; + + case scanf_format_elt::literal_conversion: + DO_LITERAL_CONVERSION (); + break; + + case '%': + { + DO_PCT_CONVERSION (); + + if (! is) + quit = true; } - } - - if (ok () && is.fail ()) - { - error ("%s: read error", who.c_str ()); - - // FIXME: is this the right thing to do? - - interpreter& interp = __get_interpreter__ (); - - if (interp.interactive () && ! application::forced_interactive () - && name () == "stdin") + break; + + case 'd': case 'i': { - // Skip to end of line. - bool err; - do_gets (-1, err, false, who); - } - } - - return quit; - } - - octave_value_list - base_stream::oscanf (const std::string& fmt, const std::string& who) - { - octave_value_list retval; - - std::istream *isp = input_stream (); - - if (! isp) - invalid_operation (who, "reading"); - else - { - std::istream& is = *isp; - - scanf_format_list fmt_list (fmt); - - octave_idx_type m_nconv = fmt_list.num_conversions (); - - if (m_nconv == -1) - ::error ("%s: invalid format specified", who.c_str ()); - - is.clear (); - - octave_idx_type len = fmt_list.length (); - - retval.resize (m_nconv+2, Matrix ()); - - const scanf_format_elt *elt = fmt_list.first (); - - int num_values = 0; - - bool quit = false; - - for (octave_idx_type i = 0; i < len; i++) - { - octave_value tmp; - - quit = do_oscanf (elt, tmp, who); - - if (quit) - break; - else + switch (elt->modifier) { - if (tmp.is_defined ()) - retval(num_values++) = tmp; - - if (! ok ()) - break; - - elt = fmt_list.next (m_nconv > 0); + case 'h': + { + int16_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + case 'l': + { + int64_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + default: + { + int32_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; } } - - retval(m_nconv) = num_values; - - int err_num; - retval(m_nconv+1) = error (false, err_num); - - if (! quit) + break; + + case 'o': case 'u': case 'x': case 'X': { - // Pick up any trailing stuff. - if (ok () && len > m_nconv) + switch (elt->modifier) { - octave_value tmp; - - elt = fmt_list.next (); - - do_oscanf (elt, tmp, who); + case 'h': + { + uint16_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + case 'l': + { + uint64_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; + + default: + { + uint32_t tmp; + if (octave_scan (is, *elt, &tmp)) + { + if (! discard) + retval = tmp; + } + else + quit = true; + } + break; } } - } - - return retval; - } - - octave_value - base_stream::do_textscan (const std::string& fmt, - octave_idx_type ntimes, - const octave_value_list& options, - const std::string& who, - octave_idx_type& read_count) - { - interpreter& interp = __get_interpreter__ (); - - if (interp.interactive () && file_number () == 0) - ::error ("%s: unable to read from stdin while running interactively", - who.c_str ()); - - octave_value retval = Cell (dim_vector (1, 1), Matrix (0, 1)); - - std::istream *isp = input_stream (); - - if (! isp) - invalid_operation (who, "reading"); - else - { - textscan scanner (who, encoding ()); - - retval = scanner.scan (*isp, fmt, ntimes, options, read_count); - } - - return retval; - } - - // Functions that are defined for all output streams - // (output streams are those that define os). - - int - base_stream::flush (void) - { - int retval = -1; - - std::ostream *os = preferred_output_stream (); - - if (! os) - invalid_operation ("fflush", "writing"); - else - { - os->flush (); - - if (os->good ()) - retval = 0; - } - - return retval; - } - - class - printf_value_cache - { - public: - - enum state { ok, conversion_error }; - - printf_value_cache (const octave_value_list& args, const std::string& who) - : m_values (args), m_val_idx (0), m_elt_idx (0), - m_n_vals (m_values.length ()), m_n_elts (0), m_have_data (false), - m_curr_state (ok) - { - for (octave_idx_type i = 0; i < m_values.length (); i++) - { - octave_value val = m_values(i); - - if (val.isstruct () || val.iscell () || val.isobject ()) - err_wrong_type_arg (who, val); - } - } - - // No copying! - - printf_value_cache (const printf_value_cache&) = delete; - - printf_value_cache& operator = (const printf_value_cache&) = delete; - - ~printf_value_cache (void) = default; - - // Get the current value as a double and advance the internal pointer. - octave_value get_next_value (char type = 0); - - // Get the current value as an int and advance the internal - // pointer. Value before conversion to int must be >= 0 and less - // than std::numeric_limits::max (). - - int int_value (void); - - operator bool () const { return (m_curr_state == ok); } - - bool exhausted (void) { return (m_val_idx >= m_n_vals); } - - private: - - // Must create value cache with values! - printf_value_cache (void); - - //-------- - - const octave_value_list m_values; - octave_idx_type m_val_idx; - octave_idx_type m_elt_idx; - octave_idx_type m_n_vals; - octave_idx_type m_n_elts; - bool m_have_data; - octave_value m_curr_val; - state m_curr_state; - }; - - octave_value - printf_value_cache::get_next_value (char type) - { - octave_value retval; - - if (exhausted ()) - m_curr_state = conversion_error; - - while (! exhausted ()) - { - if (! m_have_data) + break; + + case 'e': case 'f': case 'g': + case 'E': case 'G': { - m_curr_val = m_values (m_val_idx); - - m_elt_idx = 0; - m_n_elts = m_curr_val.numel (); - m_have_data = true; - } - - if (m_elt_idx < m_n_elts) - { - if (type == 's') + double tmp; + + if (octave_scan (is, *elt, &tmp)) { - if (m_curr_val.is_string ()) - { - dim_vector dv (1, m_curr_val.numel ()); - octave_value tmp = m_curr_val.reshape (dv); - - std::string sval = tmp.string_value (); - - retval = sval.substr (m_elt_idx); - - // We've consumed the rest of the value. - m_elt_idx = m_n_elts; - } - else - { - // Convert to character string while values are - // integers in the range [0 : char max] - const NDArray val = m_curr_val.array_value (); - - octave_idx_type idx = m_elt_idx; - - for (; idx < m_n_elts; idx++) - { - double dval = val(idx); - - if (math::x_nint (dval) != dval - || dval < 0 || dval > 255) - break; - } - - octave_idx_type n = idx - m_elt_idx; - - if (n > 0) - { - std::string sval (n, '\0'); - - for (octave_idx_type i = 0; i < n; i++) - sval[i] = val(m_elt_idx++); - - retval = sval; - } - else - retval = m_curr_val.fast_elem_extract (m_elt_idx++); - } + if (! discard) + retval = tmp; } else - { - retval = m_curr_val.fast_elem_extract (m_elt_idx++); - - if (type == 'c' && ! retval.is_string ()) - { - double dval = retval.double_value (); - - if (math::x_nint (dval) == dval && dval >= 0 && dval < 256) - retval = static_cast (dval); - } - } - - if (m_elt_idx >= m_n_elts) - { - m_elt_idx = 0; - m_val_idx++; - m_have_data = false; - } - - break; + quit = true; + } + break; + + case 'c': + { + BEGIN_C_CONVERSION (); + + if (! discard) + retval = tmp; + + if (! is) + quit = true; + + is.setf (flags); } - else + break; + + case 's': + { + BEGIN_S_CONVERSION (); + + if (! discard) + retval = tmp; + + if (! is) + quit = true; + } + break; + + case '[': + case '^': { - m_val_idx++; - m_have_data = false; - - if (m_n_elts == 0) - { - if (m_elt_idx == 0) - { - if (type == 's' || type == 'c') - retval = ""; - else - retval = Matrix (); - - break; - } - - if (exhausted ()) - m_curr_state = conversion_error; - } + BEGIN_CHAR_CLASS_CONVERSION (); + + if (! discard) + retval = tmp; + + if (! is) + quit = true; } - } - - return retval; - } - - int - printf_value_cache::int_value (void) - { - octave_value val = get_next_value (); - - double dval = val.double_value (true); - - if (dval < 0 || dval > std::numeric_limits::max () - || math::x_nint (dval) != dval) - { - m_curr_state = conversion_error; - return -1; - } - - return math::nint (dval); - } - - // Ugh again and again. - - template - static int - do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1, - int sa_2, T arg, const std::string& who) + break; + + case 'p': + error (who, "unsupported format specifier"); + break; + + default: + error (who, "internal format error"); + break; + } + } + + if (ok () && is.fail ()) + { + error ("%s: read error", who.c_str ()); + + // FIXME: is this the right thing to do? + + interpreter& interp = __get_interpreter__ (); + + if (interp.interactive () && ! application::forced_interactive () + && name () == "stdin") + { + // Skip to end of line. + bool err; + do_gets (-1, err, false, who); + } + } + + return quit; +} + +octave_value_list +base_stream::oscanf (const std::string& fmt, const std::string& who) +{ + octave_value_list retval; + + std::istream *isp = input_stream (); + + if (! isp) + invalid_operation (who, "reading"); + else + { + std::istream& is = *isp; + + scanf_format_list fmt_list (fmt); + + octave_idx_type m_nconv = fmt_list.num_conversions (); + + if (m_nconv == -1) + ::error ("%s: invalid format specified", who.c_str ()); + + is.clear (); + + octave_idx_type len = fmt_list.length (); + + retval.resize (m_nconv+2, Matrix ()); + + const scanf_format_elt *elt = fmt_list.first (); + + int num_values = 0; + + bool quit = false; + + for (octave_idx_type i = 0; i < len; i++) + { + octave_value tmp; + + quit = do_oscanf (elt, tmp, who); + + if (quit) + break; + else + { + if (tmp.is_defined ()) + retval(num_values++) = tmp; + + if (! ok ()) + break; + + elt = fmt_list.next (m_nconv > 0); + } + } + + retval(m_nconv) = num_values; + + int err_num; + retval(m_nconv+1) = error (false, err_num); + + if (! quit) + { + // Pick up any trailing stuff. + if (ok () && len > m_nconv) + { + octave_value tmp; + + elt = fmt_list.next (); + + do_oscanf (elt, tmp, who); + } + } + } + + return retval; +} + +octave_value +base_stream::do_textscan (const std::string& fmt, + octave_idx_type ntimes, + const octave_value_list& options, + const std::string& who, + octave_idx_type& read_count) +{ + interpreter& interp = __get_interpreter__ (); + + if (interp.interactive () && file_number () == 0) + ::error ("%s: unable to read from stdin while running interactively", + who.c_str ()); + + octave_value retval = Cell (dim_vector (1, 1), Matrix (0, 1)); + + std::istream *isp = input_stream (); + + if (! isp) + invalid_operation (who, "reading"); + else + { + textscan scanner (who, encoding ()); + + retval = scanner.scan (*isp, fmt, ntimes, options, read_count); + } + + return retval; +} + +// Functions that are defined for all output streams +// (output streams are those that define os). + +int +base_stream::flush (void) +{ + int retval = -1; + + std::ostream *os = preferred_output_stream (); + + if (! os) + invalid_operation ("fflush", "writing"); + else + { + os->flush (); + + if (os->good ()) + retval = 0; + } + + return retval; +} + +class +printf_value_cache +{ +public: + + enum state { ok, conversion_error }; + + printf_value_cache (const octave_value_list& args, const std::string& who) + : m_values (args), m_val_idx (0), m_elt_idx (0), + m_n_vals (m_values.length ()), m_n_elts (0), m_have_data (false), + m_curr_state (ok) { - int retval = 0; - - switch (nsa) + for (octave_idx_type i = 0; i < m_values.length (); i++) { - case 2: - retval = format (os, fmt, sa_1, sa_2, arg); - break; - - case 1: - retval = format (os, fmt, sa_1, arg); - break; - - case 0: - retval = format (os, fmt, arg); - break; - - default: - ::error ("%s: internal error handling format", who.c_str ()); - break; - } - - return retval; - } - - static std::size_t - do_printf_string (std::ostream& os, const printf_format_elt *elt, - int nsa, int sa_1, int sa_2, const std::string& arg, - const std::string& who) - { - if (nsa > 2) - ::error ("%s: internal error handling format", who.c_str ()); - - std::string flags = elt->flags; - - bool left = flags.find ('-') != std::string::npos; - - std::size_t len = arg.length (); - - std::size_t prec = (nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec)); - - std::string print_str = prec < arg.length () ? arg.substr (0, prec) : arg; - - std::size_t fw = (nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw)); - - os << std::setw (fw) << (left ? std::left : std::right) << print_str; - - return len > fw ? len : fw; - } - - static bool - is_nan_or_inf (const octave_value& val) - { - octave_value ov_isnan = val.isnan (); - octave_value ov_isinf = val.isinf (); - - return (ov_isnan.is_true () || ov_isinf.is_true ()); - } - - static bool - ok_for_signed_int_conv (const octave_value& val) - { - uint64_t limit = std::numeric_limits::max (); - - if (val.is_string ()) - return true; - else if (val.isinteger ()) - { - if (val.is_uint64_type ()) - { - octave_uint64 ival = val.uint64_scalar_value (); - - if (ival.value () <= limit) - return true; - } - else - return true; + octave_value val = m_values(i); + + if (val.isstruct () || val.iscell () || val.isobject ()) + err_wrong_type_arg (who, val); } - else - { - double dval = val.double_value (true); - - if (dval == math::fix (dval) && dval <= limit) - return true; - } - - return false; } - static bool - ok_for_unsigned_int_conv (const octave_value& val) - { - if (val.is_string ()) - return true; - else if (val.isinteger ()) - { - // Easier than dispatching here... - - octave_value ov_is_ge_zero - = binary_op (octave_value::op_ge, val, octave_value (0.0)); - - return ov_is_ge_zero.is_true (); - } - else - { - double dval = val.double_value (true); - - uint64_t limit = std::numeric_limits::max (); - - if (dval == math::fix (dval) && dval >= 0 && dval <= limit) - return true; - } - - return false; - } - - static std::string - switch_to_g_format (const printf_format_elt *elt) - { - std::string tfmt = elt->text; - - tfmt.replace (tfmt.rfind (elt->type), 1, "g"); - - return tfmt; - } - - int - base_stream::do_numeric_printf_conv (std::ostream& os, - const printf_format_elt *elt, - int nsa, int sa_1, int sa_2, - const octave_value& val, - const std::string& who) - { - int retval = 0; - - std::string tfmt = elt->text; - - if (is_nan_or_inf (val)) - { - double dval = val.double_value (); - - std::string::size_type i1, i2; - - tfmt.replace ((i1 = tfmt.rfind (elt->type)), 1, 1, 's'); - - if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1) - { - tfmt.erase (i2, i1-i2); - if (elt->prec == -2) - nsa--; - } - - const char *tval; - if (lo_ieee_isinf (dval)) - { - if (elt->flags.find ('+') != std::string::npos) - tval = (dval < 0 ? "-Inf" : "+Inf"); - else - tval = (dval < 0 ? "-Inf" : "Inf"); - } - else - { - if (elt->flags.find ('+') != std::string::npos) - tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN"); - else - tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN"); - } - - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, - who); - } - else - { - static std::string llmod - = (sizeof (long) == sizeof (int64_t) ? "l" : "ll"); - - char type = elt->type; - - switch (type) - { - case 'd': case 'i': case 'c': - if (ok_for_signed_int_conv (val)) - { - octave_int64 tval = val.int64_scalar_value (); - - // Insert "long" modifier. - tfmt.replace (tfmt.rfind (type), 1, llmod + type); - - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - tval.value (), who); - } - else - { - tfmt = switch_to_g_format (elt); - - double dval = val.double_value (true); - - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - dval, who); - } - break; - - case 'o': case 'x': case 'X': case 'u': - if (ok_for_unsigned_int_conv (val)) - { - octave_uint64 tval = val.uint64_scalar_value (); - - // Insert "long" modifier. - tfmt.replace (tfmt.rfind (type), 1, llmod + type); - - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - tval.value (), who); - } - else - { - tfmt = switch_to_g_format (elt); - - double dval = val.double_value (true); - - retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, - dval, who); - } - break; - - case 'f': case 'e': case 'E': - case 'g': case 'G': + // No copying! + + printf_value_cache (const printf_value_cache&) = delete; + + printf_value_cache& operator = (const printf_value_cache&) = delete; + + ~printf_value_cache (void) = default; + + // Get the current value as a double and advance the internal pointer. + octave_value get_next_value (char type = 0); + + // Get the current value as an int and advance the internal + // pointer. Value before conversion to int must be >= 0 and less + // than std::numeric_limits::max (). + + int int_value (void); + + operator bool () const { return (m_curr_state == ok); } + + bool exhausted (void) { return (m_val_idx >= m_n_vals); } + +private: + + // Must create value cache with values! + printf_value_cache (void); + + //-------- + + const octave_value_list m_values; + octave_idx_type m_val_idx; + octave_idx_type m_elt_idx; + octave_idx_type m_n_vals; + octave_idx_type m_n_elts; + bool m_have_data; + octave_value m_curr_val; + state m_curr_state; +}; + +octave_value +printf_value_cache::get_next_value (char type) +{ + octave_value retval; + + if (exhausted ()) + m_curr_state = conversion_error; + + while (! exhausted ()) + { + if (! m_have_data) + { + m_curr_val = m_values (m_val_idx); + + m_elt_idx = 0; + m_n_elts = m_curr_val.numel (); + m_have_data = true; + } + + if (m_elt_idx < m_n_elts) + { + if (type == 's') + { + if (m_curr_val.is_string ()) + { + dim_vector dv (1, m_curr_val.numel ()); + octave_value tmp = m_curr_val.reshape (dv); + + std::string sval = tmp.string_value (); + + retval = sval.substr (m_elt_idx); + + // We've consumed the rest of the value. + m_elt_idx = m_n_elts; + } + else + { + // Convert to character string while values are + // integers in the range [0 : char max] + const NDArray val = m_curr_val.array_value (); + + octave_idx_type idx = m_elt_idx; + + for (; idx < m_n_elts; idx++) + { + double dval = val(idx); + + if (math::x_nint (dval) != dval + || dval < 0 || dval > 255) + break; + } + + octave_idx_type n = idx - m_elt_idx; + + if (n > 0) + { + std::string sval (n, '\0'); + + for (octave_idx_type i = 0; i < n; i++) + sval[i] = val(m_elt_idx++); + + retval = sval; + } + else + retval = m_curr_val.fast_elem_extract (m_elt_idx++); + } + } + else + { + retval = m_curr_val.fast_elem_extract (m_elt_idx++); + + if (type == 'c' && ! retval.is_string ()) + { + double dval = retval.double_value (); + + if (math::x_nint (dval) == dval && dval >= 0 && dval < 256) + retval = static_cast (dval); + } + } + + if (m_elt_idx >= m_n_elts) + { + m_elt_idx = 0; + m_val_idx++; + m_have_data = false; + } + + break; + } + else + { + m_val_idx++; + m_have_data = false; + + if (m_n_elts == 0) { + if (m_elt_idx == 0) + { + if (type == 's' || type == 'c') + retval = ""; + else + retval = Matrix (); + + break; + } + + if (exhausted ()) + m_curr_state = conversion_error; + } + } + } + + return retval; +} + +int +printf_value_cache::int_value (void) +{ + octave_value val = get_next_value (); + + double dval = val.double_value (true); + + if (dval < 0 || dval > std::numeric_limits::max () + || math::x_nint (dval) != dval) + { + m_curr_state = conversion_error; + return -1; + } + + return math::nint (dval); +} + +// Ugh again and again. + +template +static int +do_printf_conv (std::ostream& os, const char *fmt, int nsa, int sa_1, + int sa_2, T arg, const std::string& who) +{ + int retval = 0; + + switch (nsa) + { + case 2: + retval = format (os, fmt, sa_1, sa_2, arg); + break; + + case 1: + retval = format (os, fmt, sa_1, arg); + break; + + case 0: + retval = format (os, fmt, arg); + break; + + default: + ::error ("%s: internal error handling format", who.c_str ()); + break; + } + + return retval; +} + +static std::size_t +do_printf_string (std::ostream& os, const printf_format_elt *elt, + int nsa, int sa_1, int sa_2, const std::string& arg, + const std::string& who) +{ + if (nsa > 2) + ::error ("%s: internal error handling format", who.c_str ()); + + std::string flags = elt->flags; + + bool left = flags.find ('-') != std::string::npos; + + std::size_t len = arg.length (); + + std::size_t prec = (nsa > 1 ? sa_2 : (elt->prec == -1 ? len : elt->prec)); + + std::string print_str = prec < arg.length () ? arg.substr (0, prec) : arg; + + std::size_t fw = (nsa > 0 ? sa_1 : (elt->fw == -1 ? len : elt->fw)); + + os << std::setw (fw) << (left ? std::left : std::right) << print_str; + + return len > fw ? len : fw; +} + +static bool +is_nan_or_inf (const octave_value& val) +{ + octave_value ov_isnan = val.isnan (); + octave_value ov_isinf = val.isinf (); + + return (ov_isnan.is_true () || ov_isinf.is_true ()); +} + +static bool +ok_for_signed_int_conv (const octave_value& val) +{ + uint64_t limit = std::numeric_limits::max (); + + if (val.is_string ()) + return true; + else if (val.isinteger ()) + { + if (val.is_uint64_type ()) + { + octave_uint64 ival = val.uint64_scalar_value (); + + if (ival.value () <= limit) + return true; + } + else + return true; + } + else + { + double dval = val.double_value (true); + + if (dval == math::fix (dval) && dval <= limit) + return true; + } + + return false; +} + +static bool +ok_for_unsigned_int_conv (const octave_value& val) +{ + if (val.is_string ()) + return true; + else if (val.isinteger ()) + { + // Easier than dispatching here... + + octave_value ov_is_ge_zero + = binary_op (octave_value::op_ge, val, octave_value (0.0)); + + return ov_is_ge_zero.is_true (); + } + else + { + double dval = val.double_value (true); + + uint64_t limit = std::numeric_limits::max (); + + if (dval == math::fix (dval) && dval >= 0 && dval <= limit) + return true; + } + + return false; +} + +static std::string +switch_to_g_format (const printf_format_elt *elt) +{ + std::string tfmt = elt->text; + + tfmt.replace (tfmt.rfind (elt->type), 1, "g"); + + return tfmt; +} + +int +base_stream::do_numeric_printf_conv (std::ostream& os, + const printf_format_elt *elt, + int nsa, int sa_1, int sa_2, + const octave_value& val, + const std::string& who) +{ + int retval = 0; + + std::string tfmt = elt->text; + + if (is_nan_or_inf (val)) + { + double dval = val.double_value (); + + std::string::size_type i1, i2; + + tfmt.replace ((i1 = tfmt.rfind (elt->type)), 1, 1, 's'); + + if ((i2 = tfmt.rfind ('.')) != std::string::npos && i2 < i1) + { + tfmt.erase (i2, i1-i2); + if (elt->prec == -2) + nsa--; + } + + const char *tval; + if (lo_ieee_isinf (dval)) + { + if (elt->flags.find ('+') != std::string::npos) + tval = (dval < 0 ? "-Inf" : "+Inf"); + else + tval = (dval < 0 ? "-Inf" : "Inf"); + } + else + { + if (elt->flags.find ('+') != std::string::npos) + tval = (lo_ieee_is_NA (dval) ? "+NA" : "+NaN"); + else + tval = (lo_ieee_is_NA (dval) ? "NA" : "NaN"); + } + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, tval, + who); + } + else + { + static std::string llmod + = (sizeof (long) == sizeof (int64_t) ? "l" : "ll"); + + char type = elt->type; + + switch (type) + { + case 'd': case 'i': case 'c': + if (ok_for_signed_int_conv (val)) + { + octave_int64 tval = val.int64_scalar_value (); + + // Insert "long" modifier. + tfmt.replace (tfmt.rfind (type), 1, llmod + type); + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, + tval.value (), who); + } + else + { + tfmt = switch_to_g_format (elt); + double dval = val.double_value (true); retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, dval, who); } - break; - - default: - // Note: error is member fcn from base_stream, not ::error. - // This error does not halt execution so "return ..." must exist. - error (who, "invalid format specifier"); - return -1; - break; - } - } - - return retval; - } - - void - base_stream::field_width_error (const std::string& who) const - { - ::error ("%s: invalid field width, must be integer >= 0 and <= INT_MAX", - who.c_str ()); - } - - int - base_stream::do_printf (printf_format_list& fmt_list, - const octave_value_list& args, - const std::string& who) - { - int retval = 0; - - octave_idx_type m_nconv = fmt_list.num_conversions (); - - std::ostream *osp = preferred_output_stream (); - - if (! osp) - invalid_operation (who, "writing"); - else - { - std::ostream& os = *osp; - - preserve_stream_state stream_state (os); - - const printf_format_elt *elt = fmt_list.first (); - - printf_value_cache val_cache (args, who); - - for (;;) + break; + + case 'o': case 'x': case 'X': case 'u': + if (ok_for_unsigned_int_conv (val)) + { + octave_uint64 tval = val.uint64_scalar_value (); + + // Insert "long" modifier. + tfmt.replace (tfmt.rfind (type), 1, llmod + type); + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, + tval.value (), who); + } + else + { + tfmt = switch_to_g_format (elt); + + double dval = val.double_value (true); + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, + dval, who); + } + break; + + case 'f': case 'e': case 'E': + case 'g': case 'G': { - octave_quit (); - - if (! elt) - ::error ("%s: internal error handling format", who.c_str ()); - - // NSA is the number of 'star' args to convert. - int nsa = (elt->fw == -2) + (elt->prec == -2); - - int sa_1 = 0; - int sa_2 = 0; - - if (nsa > 0) - { - sa_1 = val_cache.int_value (); - - if (! val_cache) - { - field_width_error (who); - break; - } - else - { - if (nsa > 1) - { - sa_2 = val_cache.int_value (); - - if (! val_cache) - { - field_width_error (who); - break; - } - } - } - } - - if (elt->type == '%') - { - os << '%'; - retval++; - } - else if (elt->args == 0 && ! elt->text.empty ()) - { - os << elt->text; - retval += (elt->text.length ()); - } - else if (elt->type == 's' || elt->type == 'c') - { - octave_value val = val_cache.get_next_value (elt->type); - - if (val_cache) - { - if (val.is_string ()) - { - std::string sval = val.string_value (); - - retval += do_printf_string (os, elt, nsa, sa_1, - sa_2, sval, who); - } - else - retval += do_numeric_printf_conv (os, elt, nsa, sa_1, - sa_2, val, who); - } - else - break; - } - else - { - octave_value val = val_cache.get_next_value (); - - if (val_cache) - { - if (! val.isempty ()) - retval += do_numeric_printf_conv (os, elt, nsa, sa_1, - sa_2, val, who); - } - else - break; - } - - if (! os) - { - error (who, "write error"); - break; - } - - elt = fmt_list.next (m_nconv > 0 && ! val_cache.exhausted ()); - - if (! elt || (val_cache.exhausted () && elt->args > 0)) - break; - } - } - - return retval; - } - - int - base_stream::printf (const std::string& fmt, - const octave_value_list& args, - const std::string& who) - { - printf_format_list fmt_list (fmt); - - if (fmt_list.num_conversions () == -1) - ::error ("%s: invalid format specified", who.c_str ()); - - return do_printf (fmt_list, args, who); - } - - int - base_stream::puts (const std::string& s, const std::string& who) - { - int retval = -1; - - std::ostream *osp = preferred_output_stream (); - - if (! osp) - invalid_operation (who, "writing"); - else - { - std::ostream& os = *osp; - - os << s; - - if (! os) - error (who, "write error"); - else - { - // FIXME: why does this seem to be necessary? - // Without it, output from a loop like - // - // for i = 1:100, fputs (stdout, "foo\n"); endfor - // - // doesn't seem to go to the pager immediately. - os.flush (); - - if (os) - retval = 0; - else - error (who, "write error"); + double dval = val.double_value (true); + + retval += do_printf_conv (os, tfmt.c_str (), nsa, sa_1, sa_2, + dval, who); } - } - - return retval; - } - - // Return current error message for this stream. - - std::string - base_stream::error (bool clear_err, int& err_num) - { - err_num = (m_fail ? -1 : 0); - - std::string tmp = m_errmsg; - - if (clear_err) - clear (); - - return tmp; - } - - void - base_stream::invalid_operation (const std::string& who, const char *rw) - { - // Note: This calls the member fcn error, not ::error from error.h. - error (who, std::string ("stream not open for ") + rw); - } - - int - stream::flush (void) - { - int retval = -1; - - if (stream_ok ()) - retval = m_rep->flush (); - - return retval; - } - - std::string - stream::getl (octave_idx_type max_len, bool& err, const std::string& who) - { - std::string retval; - - if (stream_ok ()) - retval = m_rep->getl (max_len, err, who); - - return retval; - } - - std::string - stream::getl (const octave_value& tc_max_len, bool& err, - const std::string& who) - { - err = false; - - int conv_err = 0; - - int max_len = -1; - - if (tc_max_len.is_defined ()) - { - max_len = convert_to_valid_int (tc_max_len, conv_err); - - if (conv_err || max_len < 0) - { - err = true; - ::error ("%s: invalid maximum length specified", who.c_str ()); - } - } - - return getl (max_len, err, who); - } - - std::string - stream::gets (octave_idx_type max_len, bool& err, const std::string& who) - { - std::string retval; - - if (stream_ok ()) - retval = m_rep->gets (max_len, err, who); - - return retval; - } - - std::string - stream::gets (const octave_value& tc_max_len, bool& err, - const std::string& who) - { - err = false; - - int conv_err = 0; - - int max_len = -1; - - if (tc_max_len.is_defined ()) - { - max_len = convert_to_valid_int (tc_max_len, conv_err); - - if (conv_err || max_len < 0) - { - err = true; - ::error ("%s: invalid maximum length specified", who.c_str ()); - } - } - - return gets (max_len, err, who); - } - - off_t - stream::skipl (off_t count, bool& err, const std::string& who) - { - off_t retval = -1; - - if (stream_ok ()) - retval = m_rep->skipl (count, err, who); - - return retval; - } - - off_t - stream::skipl (const octave_value& tc_count, bool& err, - const std::string& who) - { - err = false; - - int conv_err = 0; - - int count = 1; - - if (tc_count.is_defined ()) - { - if (tc_count.is_scalar_type () - && math::isinf (tc_count.scalar_value ())) - count = -1; - else - { - count = convert_to_valid_int (tc_count, conv_err); - - if (conv_err || count < 0) - { - err = true; - ::error ("%s: invalid number of lines specified", - who.c_str ()); - } - } - } - - return skipl (count, err, who); - } - - int - stream::seek (off_t offset, int origin) - { - int status = -1; - - if (stream_ok ()) - { - clearerr (); - - // Find current position so we can return to it if needed. - off_t orig_pos = m_rep->tell (); - - // Move to end of file. If successful, find the offset of the end. - status = m_rep->seek (0, SEEK_END); - - if (status == 0) - { - off_t eof_pos = m_rep->tell (); - - if (origin == SEEK_CUR) - { - // Move back to original position, otherwise we will be seeking - // from the end of file which is probably not the original - // location. - m_rep->seek (orig_pos, SEEK_SET); - } - - // Attempt to move to desired position; may be outside bounds of - // existing file. - status = m_rep->seek (offset, origin); - - if (status == 0) - { - // Where are we after moving to desired position? - off_t desired_pos = m_rep->tell (); - - // I don't think save_pos can be less than zero, - // but we'll check anyway... - if (desired_pos > eof_pos || desired_pos < 0) - { - // Seek outside bounds of file. - // Failure should leave position unchanged. - m_rep->seek (orig_pos, SEEK_SET); - - status = -1; - } - } - else - { - // Seeking to the desired position failed. - // Move back to original position and return failure status. - m_rep->seek (orig_pos, SEEK_SET); - - status = -1; - } - } - } - - return status; - } - - int - stream::seek (const octave_value& tc_offset, - const octave_value& tc_origin) - { - int retval = -1; - - // FIXME: should we have octave_value methods that handle off_t explicitly? - octave_int64 val = tc_offset.xint64_scalar_value ("fseek: invalid value for offset"); - off_t xoffset = val.value (); - - int conv_err = 0; - - int origin = SEEK_SET; - - if (tc_origin.is_string ()) - { - std::string xorigin = tc_origin.xstring_value ("fseek: invalid value for origin"); - - if (xorigin == "bof") - origin = SEEK_SET; - else if (xorigin == "cof") - origin = SEEK_CUR; - else if (xorigin == "eof") - origin = SEEK_END; - else - conv_err = -1; - } - else - { - int xorigin = convert_to_valid_int (tc_origin, conv_err); - - if (! conv_err) - { - if (xorigin == -1) - origin = SEEK_SET; - else if (xorigin == 0) - origin = SEEK_CUR; - else if (xorigin == 1) - origin = SEEK_END; - else - conv_err = -1; - } - } - - if (conv_err) - ::error ("fseek: invalid value for origin"); - - retval = seek (xoffset, origin); - - if (retval != 0) - // Note: error is member fcn from stream, not ::error. - error ("fseek: failed to seek to requested position"); - - return retval; - } - - off_t - stream::tell (void) - { - off_t retval = -1; - - if (stream_ok ()) - retval = m_rep->tell (); - - return retval; - } - - int - stream::rewind (void) - { - return seek (0, SEEK_SET); - } - - bool - stream::is_open (void) const - { - bool retval = false; - - if (stream_ok ()) - retval = m_rep->is_open (); - - return retval; - } - - void - stream::close (void) - { - if (stream_ok ()) + break; + + default: + // Note: error is member fcn from base_stream, not ::error. + // This error does not halt execution so "return ..." must exist. + error (who, "invalid format specifier"); + return -1; + break; + } + } + + return retval; +} + +void +base_stream::field_width_error (const std::string& who) const +{ + ::error ("%s: invalid field width, must be integer >= 0 and <= INT_MAX", + who.c_str ()); +} + +int +base_stream::do_printf (printf_format_list& fmt_list, + const octave_value_list& args, + const std::string& who) +{ + int retval = 0; + + octave_idx_type m_nconv = fmt_list.num_conversions (); + + std::ostream *osp = preferred_output_stream (); + + if (! osp) + invalid_operation (who, "writing"); + else + { + std::ostream& os = *osp; + + preserve_stream_state stream_state (os); + + const printf_format_elt *elt = fmt_list.first (); + + printf_value_cache val_cache (args, who); + + for (;;) + { + octave_quit (); + + if (! elt) + ::error ("%s: internal error handling format", who.c_str ()); + + // NSA is the number of 'star' args to convert. + int nsa = (elt->fw == -2) + (elt->prec == -2); + + int sa_1 = 0; + int sa_2 = 0; + + if (nsa > 0) + { + sa_1 = val_cache.int_value (); + + if (! val_cache) + { + field_width_error (who); + break; + } + else + { + if (nsa > 1) + { + sa_2 = val_cache.int_value (); + + if (! val_cache) + { + field_width_error (who); + break; + } + } + } + } + + if (elt->type == '%') + { + os << '%'; + retval++; + } + else if (elt->args == 0 && ! elt->text.empty ()) + { + os << elt->text; + retval += (elt->text.length ()); + } + else if (elt->type == 's' || elt->type == 'c') + { + octave_value val = val_cache.get_next_value (elt->type); + + if (val_cache) + { + if (val.is_string ()) + { + std::string sval = val.string_value (); + + retval += do_printf_string (os, elt, nsa, sa_1, + sa_2, sval, who); + } + else + retval += do_numeric_printf_conv (os, elt, nsa, sa_1, + sa_2, val, who); + } + else + break; + } + else + { + octave_value val = val_cache.get_next_value (); + + if (val_cache) + { + if (! val.isempty ()) + retval += do_numeric_printf_conv (os, elt, nsa, sa_1, + sa_2, val, who); + } + else + break; + } + + if (! os) + { + error (who, "write error"); + break; + } + + elt = fmt_list.next (m_nconv > 0 && ! val_cache.exhausted ()); + + if (! elt || (val_cache.exhausted () && elt->args > 0)) + break; + } + } + + return retval; +} + +int +base_stream::printf (const std::string& fmt, + const octave_value_list& args, + const std::string& who) +{ + printf_format_list fmt_list (fmt); + + if (fmt_list.num_conversions () == -1) + ::error ("%s: invalid format specified", who.c_str ()); + + return do_printf (fmt_list, args, who); +} + +int +base_stream::puts (const std::string& s, const std::string& who) +{ + int retval = -1; + + std::ostream *osp = preferred_output_stream (); + + if (! osp) + invalid_operation (who, "writing"); + else + { + std::ostream& os = *osp; + + os << s; + + if (! os) + error (who, "write error"); + else + { + // FIXME: why does this seem to be necessary? + // Without it, output from a loop like + // + // for i = 1:100, fputs (stdout, "foo\n"); endfor + // + // doesn't seem to go to the pager immediately. + os.flush (); + + if (os) + retval = 0; + else + error (who, "write error"); + } + } + + return retval; +} + +// Return current error message for this stream. + +std::string +base_stream::error (bool clear_err, int& err_num) +{ + err_num = (m_fail ? -1 : 0); + + std::string tmp = m_errmsg; + + if (clear_err) + clear (); + + return tmp; +} + +void +base_stream::invalid_operation (const std::string& who, const char *rw) +{ + // Note: This calls the member fcn error, not ::error from error.h. + error (who, std::string ("stream not open for ") + rw); +} + +int +stream::flush (void) +{ + int retval = -1; + + if (stream_ok ()) + retval = m_rep->flush (); + + return retval; +} + +std::string +stream::getl (octave_idx_type max_len, bool& err, const std::string& who) +{ + std::string retval; + + if (stream_ok ()) + retval = m_rep->getl (max_len, err, who); + + return retval; +} + +std::string +stream::getl (const octave_value& tc_max_len, bool& err, + const std::string& who) +{ + err = false; + + int conv_err = 0; + + int max_len = -1; + + if (tc_max_len.is_defined ()) + { + max_len = convert_to_valid_int (tc_max_len, conv_err); + + if (conv_err || max_len < 0) + { + err = true; + ::error ("%s: invalid maximum length specified", who.c_str ()); + } + } + + return getl (max_len, err, who); +} + +std::string +stream::gets (octave_idx_type max_len, bool& err, const std::string& who) +{ + std::string retval; + + if (stream_ok ()) + retval = m_rep->gets (max_len, err, who); + + return retval; +} + +std::string +stream::gets (const octave_value& tc_max_len, bool& err, + const std::string& who) +{ + err = false; + + int conv_err = 0; + + int max_len = -1; + + if (tc_max_len.is_defined ()) + { + max_len = convert_to_valid_int (tc_max_len, conv_err); + + if (conv_err || max_len < 0) + { + err = true; + ::error ("%s: invalid maximum length specified", who.c_str ()); + } + } + + return gets (max_len, err, who); +} + +off_t +stream::skipl (off_t count, bool& err, const std::string& who) +{ + off_t retval = -1; + + if (stream_ok ()) + retval = m_rep->skipl (count, err, who); + + return retval; +} + +off_t +stream::skipl (const octave_value& tc_count, bool& err, + const std::string& who) +{ + err = false; + + int conv_err = 0; + + int count = 1; + + if (tc_count.is_defined ()) + { + if (tc_count.is_scalar_type () + && math::isinf (tc_count.scalar_value ())) + count = -1; + else + { + count = convert_to_valid_int (tc_count, conv_err); + + if (conv_err || count < 0) + { + err = true; + ::error ("%s: invalid number of lines specified", + who.c_str ()); + } + } + } + + return skipl (count, err, who); +} + +int +stream::seek (off_t offset, int origin) +{ + int status = -1; + + if (stream_ok ()) + { + clearerr (); + + // Find current position so we can return to it if needed. + off_t orig_pos = m_rep->tell (); + + // Move to end of file. If successful, find the offset of the end. + status = m_rep->seek (0, SEEK_END); + + if (status == 0) + { + off_t eof_pos = m_rep->tell (); + + if (origin == SEEK_CUR) + { + // Move back to original position, otherwise we will be seeking + // from the end of file which is probably not the original + // location. + m_rep->seek (orig_pos, SEEK_SET); + } + + // Attempt to move to desired position; may be outside bounds of + // existing file. + status = m_rep->seek (offset, origin); + + if (status == 0) + { + // Where are we after moving to desired position? + off_t desired_pos = m_rep->tell (); + + // I don't think save_pos can be less than zero, + // but we'll check anyway... + if (desired_pos > eof_pos || desired_pos < 0) + { + // Seek outside bounds of file. + // Failure should leave position unchanged. + m_rep->seek (orig_pos, SEEK_SET); + + status = -1; + } + } + else + { + // Seeking to the desired position failed. + // Move back to original position and return failure status. + m_rep->seek (orig_pos, SEEK_SET); + + status = -1; + } + } + } + + return status; +} + +int +stream::seek (const octave_value& tc_offset, + const octave_value& tc_origin) +{ + int retval = -1; + + // FIXME: should we have octave_value methods that handle off_t explicitly? + octave_int64 val = tc_offset.xint64_scalar_value ("fseek: invalid value for offset"); + off_t xoffset = val.value (); + + int conv_err = 0; + + int origin = SEEK_SET; + + if (tc_origin.is_string ()) + { + std::string xorigin = tc_origin.xstring_value ("fseek: invalid value for origin"); + + if (xorigin == "bof") + origin = SEEK_SET; + else if (xorigin == "cof") + origin = SEEK_CUR; + else if (xorigin == "eof") + origin = SEEK_END; + else + conv_err = -1; + } + else + { + int xorigin = convert_to_valid_int (tc_origin, conv_err); + + if (! conv_err) + { + if (xorigin == -1) + origin = SEEK_SET; + else if (xorigin == 0) + origin = SEEK_CUR; + else if (xorigin == 1) + origin = SEEK_END; + else + conv_err = -1; + } + } + + if (conv_err) + ::error ("fseek: invalid value for origin"); + + retval = seek (xoffset, origin); + + if (retval != 0) + // Note: error is member fcn from stream, not ::error. + error ("fseek: failed to seek to requested position"); + + return retval; +} + +off_t +stream::tell (void) +{ + off_t retval = -1; + + if (stream_ok ()) + retval = m_rep->tell (); + + return retval; +} + +int +stream::rewind (void) +{ + return seek (0, SEEK_SET); +} + +bool +stream::is_open (void) const +{ + bool retval = false; + + if (stream_ok ()) + retval = m_rep->is_open (); + + return retval; +} + +void +stream::close (void) +{ + if (stream_ok ()) { m_rep->flush (); m_rep->close (); } - } - - template - static octave_value - convert_and_copy (std::list& input_buf_list, - octave_idx_type input_buf_elts, - octave_idx_type elts_read, - octave_idx_type nr, octave_idx_type nc, bool swap, - bool do_float_fmt_conv, bool do_NA_conv, - mach_info::float_format from_flt_fmt) - { - typedef typename DST_T::element_type dst_elt_type; - - DST_T conv (dim_vector (nr, nc)); - - dst_elt_type *conv_data = conv.fortran_vec (); - - octave_idx_type j = 0; - - for (auto it = input_buf_list.cbegin (); it != input_buf_list.cend (); it++) - { - SRC_T *data = static_cast (*it); - - if (swap || do_float_fmt_conv) - { - if (do_NA_conv) - { - for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; - i++, j++) - { - if (swap) - swap_bytes (&data[i]); - else if (do_float_fmt_conv) - do_float_format_conversion (&data[i], sizeof (SRC_T), - 1, from_flt_fmt, - mach_info::native_float_format ()); - - // FIXME: Potentially add conversion code for MIPS NA here - // Bug #59830. - // dst_elt_type tmp (data[i]); - // if (is_MIPS_NA (tmp)) - // tmp = replace_MIPS_NA (tmp); - // conv_data[j] = tmp; - - conv_data[j] = data[i]; - } - } - else - { - for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; - i++, j++) - { - if (swap) - swap_bytes (&data[i]); - else if (do_float_fmt_conv) - do_float_format_conversion (&data[i], sizeof (SRC_T), - 1, from_flt_fmt, - mach_info::native_float_format ()); - - conv_data[j] = data[i]; - } - } - } - else - { - if (do_NA_conv) - { - for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; - i++, j++) - { - // FIXME: Potentially add conversion code for MIPS NA here - conv_data[j] = data[i]; - } - } - else - { - for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; - i++, j++) +} + +template +static octave_value +convert_and_copy (std::list& input_buf_list, + octave_idx_type input_buf_elts, + octave_idx_type elts_read, + octave_idx_type nr, octave_idx_type nc, bool swap, + bool do_float_fmt_conv, bool do_NA_conv, + mach_info::float_format from_flt_fmt) +{ + typedef typename DST_T::element_type dst_elt_type; + + DST_T conv (dim_vector (nr, nc)); + + dst_elt_type *conv_data = conv.fortran_vec (); + + octave_idx_type j = 0; + + for (auto it = input_buf_list.cbegin (); it != input_buf_list.cend (); it++) + { + SRC_T *data = static_cast (*it); + + if (swap || do_float_fmt_conv) + { + if (do_NA_conv) + { + for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; + i++, j++) + { + if (swap) + swap_bytes (&data[i]); + else if (do_float_fmt_conv) + do_float_format_conversion (&data[i], sizeof (SRC_T), + 1, from_flt_fmt, + mach_info::native_float_format ()); + + // FIXME: Potentially add conversion code for MIPS NA here + // Bug #59830. + // dst_elt_type tmp (data[i]); + // if (is_MIPS_NA (tmp)) + // tmp = replace_MIPS_NA (tmp); + // conv_data[j] = tmp; + conv_data[j] = data[i]; - } - } - - delete [] data; - } - - input_buf_list.clear (); - - for (octave_idx_type i = elts_read; i < nr * nc; i++) - conv_data[i] = dst_elt_type (0); - - return conv; - } - - typedef octave_value (*conv_fptr) - (std::list& input_buf_list, octave_idx_type input_buf_elts, - octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc, - bool swap, bool do_float_fmt_conv, bool do_NA_conv, - mach_info::float_format from_flt_fmt); + } + } + else + { + for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; + i++, j++) + { + if (swap) + swap_bytes (&data[i]); + else if (do_float_fmt_conv) + do_float_format_conversion (&data[i], sizeof (SRC_T), + 1, from_flt_fmt, + mach_info::native_float_format ()); + + conv_data[j] = data[i]; + } + } + } + else + { + if (do_NA_conv) + { + for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; + i++, j++) + { + // FIXME: Potentially add conversion code for MIPS NA here + conv_data[j] = data[i]; + } + } + else + { + for (octave_idx_type i = 0; i < input_buf_elts && j < elts_read; + i++, j++) + conv_data[j] = data[i]; + } + } + + delete [] data; + } + + input_buf_list.clear (); + + for (octave_idx_type i = elts_read; i < nr * nc; i++) + conv_data[i] = dst_elt_type (0); + + return conv; +} + +typedef octave_value (*conv_fptr) + (std::list& input_buf_list, octave_idx_type input_buf_elts, + octave_idx_type elts_read, octave_idx_type nr, octave_idx_type nc, + bool swap, bool do_float_fmt_conv, bool do_NA_conv, + mach_info::float_format from_flt_fmt); #define TABLE_ELT(T, U, V, W) \ conv_fptr_table[oct_data_conv::T][oct_data_conv::U] = convert_and_copy @@ -6549,597 +6555,597 @@ TABLE_ELT (T, dt_uchar, V, charNDArray); \ TABLE_ELT (T, dt_logical, V, boolNDArray); - octave_value - stream::finalize_read (std::list& input_buf_list, - octave_idx_type input_buf_elts, - octave_idx_type elts_read, - octave_idx_type nr, octave_idx_type nc, - oct_data_conv::data_type input_type, - oct_data_conv::data_type output_type, - mach_info::float_format ffmt) - { - octave_value retval; - - static bool initialized = false; - - // Table function pointers for return types x read types. - - static conv_fptr conv_fptr_table[oct_data_conv::dt_unknown][14]; - - if (! initialized) - { - for (int i = 0; i < oct_data_conv::dt_unknown; i++) - for (int j = 0; j < 14; j++) - conv_fptr_table[i][j] = nullptr; - - FILL_TABLE_ROW (dt_int8, int8_t); - FILL_TABLE_ROW (dt_uint8, uint8_t); - FILL_TABLE_ROW (dt_int16, int16_t); - FILL_TABLE_ROW (dt_uint16, uint16_t); - FILL_TABLE_ROW (dt_int32, int32_t); - FILL_TABLE_ROW (dt_uint32, uint32_t); - FILL_TABLE_ROW (dt_int64, int64_t); - FILL_TABLE_ROW (dt_uint64, uint64_t); - FILL_TABLE_ROW (dt_single, float); - FILL_TABLE_ROW (dt_double, double); - FILL_TABLE_ROW (dt_char, char); - FILL_TABLE_ROW (dt_schar, signed char); - FILL_TABLE_ROW (dt_uchar, unsigned char); - FILL_TABLE_ROW (dt_logical, bool); - - initialized = true; - } - - bool swap = false; - - if (ffmt == mach_info::flt_fmt_unknown) - ffmt = float_format (); - - if (mach_info::words_big_endian ()) - swap = (ffmt == mach_info::flt_fmt_ieee_little_endian); - else - swap = (ffmt == mach_info::flt_fmt_ieee_big_endian); - - bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double - || input_type == oct_data_conv::dt_single) - && ffmt != float_format ()); - - bool do_NA_conv = (output_type == oct_data_conv::dt_double); - - switch (output_type) - { - case oct_data_conv::dt_int8: - case oct_data_conv::dt_uint8: - case oct_data_conv::dt_int16: - case oct_data_conv::dt_uint16: - case oct_data_conv::dt_int32: - case oct_data_conv::dt_uint32: - case oct_data_conv::dt_int64: - case oct_data_conv::dt_uint64: - case oct_data_conv::dt_single: - case oct_data_conv::dt_double: - case oct_data_conv::dt_char: - case oct_data_conv::dt_schar: - case oct_data_conv::dt_uchar: - case oct_data_conv::dt_logical: - { - conv_fptr fptr = conv_fptr_table[input_type][output_type]; - - retval = fptr (input_buf_list, input_buf_elts, elts_read, - nr, nc, swap, do_float_fmt_conv, do_NA_conv, ffmt); - } - break; - - default: - ::error ("read: invalid type specification"); - } - - return retval; - } - - octave_value - stream::read (const Array& size, octave_idx_type block_size, - oct_data_conv::data_type input_type, - oct_data_conv::data_type output_type, - octave_idx_type skip, mach_info::float_format ffmt, - octave_idx_type& count) - { - octave_value retval; - - if (! stream_ok ()) - return retval; - - octave_idx_type nr = -1; - octave_idx_type nc = -1; - - bool one_elt_size_spec = false; - - // FIXME: We may eventually want to make this extensible. - - // FIXME: We need a better way to ensure that this numbering stays - // consistent with the order of the elements in the data_type enum in the - // oct_data_conv class. - - std::ptrdiff_t tmp_count = 0; - - try - { - get_size (size, nr, nc, one_elt_size_spec, "fread"); - } - catch (const execution_exception&) - { - invalid_operation ("fread", "reading"); - - return retval; - } - - if (one_elt_size_spec) - { - // If NR == 0, Matlab returns [](0x0). - - // If NR > 0, the result will be a column vector with the given - // number of rows. - - // If NR < 0, then we have Inf and the result will be a column - // vector but we have to wait to see how big NR will be. - - if (nr == 0) - nr = nc = 0; - else - nc = 1; - } - else - { - // Matlab returns [] even if there are two elements in the size - // specification and one is nonzero. - - // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC - // should be. - - if (nr == 0 || nc == 0) - nr = nc = 0; - } - - octave_idx_type elts_to_read = nr * nc; - - bool read_to_eof = elts_to_read < 0; - - octave_idx_type input_buf_elts = -1; - - if (skip == 0) - { - if (read_to_eof) - input_buf_elts = 1024 * 1024; - else - input_buf_elts = elts_to_read; - } - else - input_buf_elts = block_size; - - octave_idx_type input_elt_size - = oct_data_conv::data_type_size (input_type); - - std::ptrdiff_t input_buf_size - = static_cast (input_buf_elts) * input_elt_size; - - error_if (input_buf_size < 0); - - // Must also work and return correct type object for 0 elements to read. - std::istream *isp = input_stream (); - - if (! isp) - error ("fread: invalid input stream"); - else +octave_value +stream::finalize_read (std::list& input_buf_list, + octave_idx_type input_buf_elts, + octave_idx_type elts_read, + octave_idx_type nr, octave_idx_type nc, + oct_data_conv::data_type input_type, + oct_data_conv::data_type output_type, + mach_info::float_format ffmt) +{ + octave_value retval; + + static bool initialized = false; + + // Table function pointers for return types x read types. + + static conv_fptr conv_fptr_table[oct_data_conv::dt_unknown][14]; + + if (! initialized) + { + for (int i = 0; i < oct_data_conv::dt_unknown; i++) + for (int j = 0; j < 14; j++) + conv_fptr_table[i][j] = nullptr; + + FILL_TABLE_ROW (dt_int8, int8_t); + FILL_TABLE_ROW (dt_uint8, uint8_t); + FILL_TABLE_ROW (dt_int16, int16_t); + FILL_TABLE_ROW (dt_uint16, uint16_t); + FILL_TABLE_ROW (dt_int32, int32_t); + FILL_TABLE_ROW (dt_uint32, uint32_t); + FILL_TABLE_ROW (dt_int64, int64_t); + FILL_TABLE_ROW (dt_uint64, uint64_t); + FILL_TABLE_ROW (dt_single, float); + FILL_TABLE_ROW (dt_double, double); + FILL_TABLE_ROW (dt_char, char); + FILL_TABLE_ROW (dt_schar, signed char); + FILL_TABLE_ROW (dt_uchar, unsigned char); + FILL_TABLE_ROW (dt_logical, bool); + + initialized = true; + } + + bool swap = false; + + if (ffmt == mach_info::flt_fmt_unknown) + ffmt = float_format (); + + if (mach_info::words_big_endian ()) + swap = (ffmt == mach_info::flt_fmt_ieee_little_endian); + else + swap = (ffmt == mach_info::flt_fmt_ieee_big_endian); + + bool do_float_fmt_conv = ((input_type == oct_data_conv::dt_double + || input_type == oct_data_conv::dt_single) + && ffmt != float_format ()); + + bool do_NA_conv = (output_type == oct_data_conv::dt_double); + + switch (output_type) + { + case oct_data_conv::dt_int8: + case oct_data_conv::dt_uint8: + case oct_data_conv::dt_int16: + case oct_data_conv::dt_uint16: + case oct_data_conv::dt_int32: + case oct_data_conv::dt_uint32: + case oct_data_conv::dt_int64: + case oct_data_conv::dt_uint64: + case oct_data_conv::dt_single: + case oct_data_conv::dt_double: + case oct_data_conv::dt_char: + case oct_data_conv::dt_schar: + case oct_data_conv::dt_uchar: + case oct_data_conv::dt_logical: { - std::istream& is = *isp; - - // Initialize eof_pos variable just once per function call - off_t eof_pos = 0; - off_t cur_pos = 0; - if (skip != 0 && is && ! is.eof ()) - { - cur_pos = is.tellg (); - is.seekg (0, is.end); - eof_pos = is.tellg (); - is.seekg (cur_pos, is.beg); - } - - std::list input_buf_list; - - while (is && ! is.eof () - && (read_to_eof || tmp_count < elts_to_read)) - { - if (! read_to_eof) - { - octave_idx_type remaining_elts = elts_to_read - tmp_count; - - if (remaining_elts < input_buf_elts) - input_buf_size = remaining_elts * input_elt_size; - } - - char *input_buf = new char [input_buf_size]; - - is.read (input_buf, input_buf_size); - - std::size_t gcount = is.gcount (); - - cur_pos += gcount; - - octave_idx_type nel = gcount / input_elt_size; - - tmp_count += nel; - - input_buf_list.push_back (input_buf); - - if (skip != 0 && nel == block_size && is) - { - // Attempt to skip. - // If skip would move past EOF, position at EOF. - off_t remaining = eof_pos - cur_pos; - - if (remaining < skip) - { - is.seekg (0, is.end); - cur_pos = eof_pos; - } - else - { - is.seekg (skip, is.cur); - cur_pos += skip; - } - } - } - - if (read_to_eof) - { - if (nc < 0) - { - nc = tmp_count / nr; - - if (tmp_count % nr != 0) - nc++; - } - else - nr = tmp_count; - } - else if (tmp_count == 0) - { - nr = 0; - nc = 0; - } - else if (tmp_count != nr * nc) - { - if (tmp_count % nr != 0) - nc = tmp_count / nr + 1; - else - nc = tmp_count / nr; - - if (tmp_count < nr) - nr = tmp_count; - } - - if (tmp_count > std::numeric_limits::max ()) - error ("fread: number of elements read exceeds max index size"); - else - count = static_cast (tmp_count); - - retval = finalize_read (input_buf_list, input_buf_elts, count, - nr, nc, input_type, output_type, ffmt); + conv_fptr fptr = conv_fptr_table[input_type][output_type]; + + retval = fptr (input_buf_list, input_buf_elts, elts_read, + nr, nc, swap, do_float_fmt_conv, do_NA_conv, ffmt); } - - return retval; - } - - octave_idx_type - stream::write (const octave_value& data, octave_idx_type block_size, - oct_data_conv::data_type output_type, - octave_idx_type skip, mach_info::float_format flt_fmt) - { - octave_idx_type retval = -1; - - if (! stream_ok ()) - invalid_operation ("fwrite", "writing"); - else - { - if (flt_fmt == mach_info::flt_fmt_unknown) - flt_fmt = float_format (); - - octave_idx_type status = data.write (*this, block_size, output_type, - skip, flt_fmt); - - if (status < 0) - error ("fwrite: write error"); - else - retval = status; - } - + break; + + default: + ::error ("read: invalid type specification"); + } + + return retval; +} + +octave_value +stream::read (const Array& size, octave_idx_type block_size, + oct_data_conv::data_type input_type, + oct_data_conv::data_type output_type, + octave_idx_type skip, mach_info::float_format ffmt, + octave_idx_type& count) +{ + octave_value retval; + + if (! stream_ok ()) return retval; - } - - template - static void - convert_chars (const void *data, void *conv_data, octave_idx_type n_elts) - { - const T *tt_data = static_cast (data); - - V *vt_data = static_cast (conv_data); - - for (octave_idx_type i = 0; i < n_elts; i++) - vt_data[i] = tt_data[i]; - } - - template - static void - convert_ints (const T *data, void *conv_data, octave_idx_type n_elts, - bool swap) - { - typedef typename V::val_type val_type; - - val_type *vt_data = static_cast (conv_data); - - for (octave_idx_type i = 0; i < n_elts; i++) - { - // Yes, we want saturation semantics when converting to an integer type. - V val (data[i]); - - vt_data[i] = val.value (); - - if (swap) - swap_bytes (&vt_data[i]); - } - } - - template - class ultimate_element_type - { - public: - typedef T type; - }; - - template - class ultimate_element_type> - { - public: - typedef T type; - }; - - template - static bool - convert_data (const T *data, void *conv_data, octave_idx_type n_elts, - oct_data_conv::data_type output_type, - mach_info::float_format flt_fmt) - { - bool retval = true; - - bool swap = false; - - if (mach_info::words_big_endian ()) - swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian); - else - swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian); - - bool do_float_conversion = flt_fmt != mach_info::float_format (); - - typedef typename ultimate_element_type::type ult_elt_type; - - switch (output_type) - { - case oct_data_conv::dt_char: - convert_chars (data, conv_data, n_elts); - break; - - case oct_data_conv::dt_schar: - convert_chars (data, conv_data, n_elts); - break; - - case oct_data_conv::dt_uchar: - convert_chars (data, conv_data, n_elts); - break; - - case oct_data_conv::dt_int8: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_uint8: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_int16: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_uint16: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_int32: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_uint32: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_int64: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_uint64: - convert_ints (data, conv_data, n_elts, swap); - break; - - case oct_data_conv::dt_single: + + octave_idx_type nr = -1; + octave_idx_type nc = -1; + + bool one_elt_size_spec = false; + + // FIXME: We may eventually want to make this extensible. + + // FIXME: We need a better way to ensure that this numbering stays + // consistent with the order of the elements in the data_type enum in the + // oct_data_conv class. + + std::ptrdiff_t tmp_count = 0; + + try + { + get_size (size, nr, nc, one_elt_size_spec, "fread"); + } + catch (const execution_exception&) + { + invalid_operation ("fread", "reading"); + + return retval; + } + + if (one_elt_size_spec) + { + // If NR == 0, Matlab returns [](0x0). + + // If NR > 0, the result will be a column vector with the given + // number of rows. + + // If NR < 0, then we have Inf and the result will be a column + // vector but we have to wait to see how big NR will be. + + if (nr == 0) + nr = nc = 0; + else + nc = 1; + } + else + { + // Matlab returns [] even if there are two elements in the size + // specification and one is nonzero. + + // If NC < 0 we have [NR, Inf] and we'll wait to decide how big NC + // should be. + + if (nr == 0 || nc == 0) + nr = nc = 0; + } + + octave_idx_type elts_to_read = nr * nc; + + bool read_to_eof = elts_to_read < 0; + + octave_idx_type input_buf_elts = -1; + + if (skip == 0) + { + if (read_to_eof) + input_buf_elts = 1024 * 1024; + else + input_buf_elts = elts_to_read; + } + else + input_buf_elts = block_size; + + octave_idx_type input_elt_size + = oct_data_conv::data_type_size (input_type); + + std::ptrdiff_t input_buf_size + = static_cast (input_buf_elts) * input_elt_size; + + error_if (input_buf_size < 0); + + // Must also work and return correct type object for 0 elements to read. + std::istream *isp = input_stream (); + + if (! isp) + error ("fread: invalid input stream"); + else + { + std::istream& is = *isp; + + // Initialize eof_pos variable just once per function call + off_t eof_pos = 0; + off_t cur_pos = 0; + if (skip != 0 && is && ! is.eof ()) { - float *vt_data = static_cast (conv_data); - - for (octave_idx_type i = 0; i < n_elts; i++) + cur_pos = is.tellg (); + is.seekg (0, is.end); + eof_pos = is.tellg (); + is.seekg (cur_pos, is.beg); + } + + std::list input_buf_list; + + while (is && ! is.eof () + && (read_to_eof || tmp_count < elts_to_read)) + { + if (! read_to_eof) { - vt_data[i] = data[i]; - - if (do_float_conversion) - do_float_format_conversion (&vt_data[i], 1, flt_fmt); + octave_idx_type remaining_elts = elts_to_read - tmp_count; + + if (remaining_elts < input_buf_elts) + input_buf_size = remaining_elts * input_elt_size; + } + + char *input_buf = new char [input_buf_size]; + + is.read (input_buf, input_buf_size); + + std::size_t gcount = is.gcount (); + + cur_pos += gcount; + + octave_idx_type nel = gcount / input_elt_size; + + tmp_count += nel; + + input_buf_list.push_back (input_buf); + + if (skip != 0 && nel == block_size && is) + { + // Attempt to skip. + // If skip would move past EOF, position at EOF. + off_t remaining = eof_pos - cur_pos; + + if (remaining < skip) + { + is.seekg (0, is.end); + cur_pos = eof_pos; + } + else + { + is.seekg (skip, is.cur); + cur_pos += skip; + } } } - break; - - case oct_data_conv::dt_double: + + if (read_to_eof) { - double *vt_data = static_cast (conv_data); - - for (octave_idx_type i = 0; i < n_elts; i++) + if (nc < 0) { - vt_data[i] = data[i]; - - if (do_float_conversion) - do_double_format_conversion (&vt_data[i], 1, flt_fmt); + nc = tmp_count / nr; + + if (tmp_count % nr != 0) + nc++; } + else + nr = tmp_count; + } + else if (tmp_count == 0) + { + nr = 0; + nc = 0; + } + else if (tmp_count != nr * nc) + { + if (tmp_count % nr != 0) + nc = tmp_count / nr + 1; + else + nc = tmp_count / nr; + + if (tmp_count < nr) + nr = tmp_count; } - break; - - default: - ::error ("write: invalid type specification"); - } - - return retval; - } - - bool - stream::write_bytes (const void *data, std::size_t nbytes) - { - bool status = false; - - std::ostream *osp = output_stream (); - - if (osp) + + if (tmp_count > std::numeric_limits::max ()) + error ("fread: number of elements read exceeds max index size"); + else + count = static_cast (tmp_count); + + retval = finalize_read (input_buf_list, input_buf_elts, count, + nr, nc, input_type, output_type, ffmt); + } + + return retval; +} + +octave_idx_type +stream::write (const octave_value& data, octave_idx_type block_size, + oct_data_conv::data_type output_type, + octave_idx_type skip, mach_info::float_format flt_fmt) +{ + octave_idx_type retval = -1; + + if (! stream_ok ()) + invalid_operation ("fwrite", "writing"); + else + { + if (flt_fmt == mach_info::flt_fmt_unknown) + flt_fmt = float_format (); + + octave_idx_type status = data.write (*this, block_size, output_type, + skip, flt_fmt); + + if (status < 0) + error ("fwrite: write error"); + else + retval = status; + } + + return retval; +} + +template +static void +convert_chars (const void *data, void *conv_data, octave_idx_type n_elts) +{ + const T *tt_data = static_cast (data); + + V *vt_data = static_cast (conv_data); + + for (octave_idx_type i = 0; i < n_elts; i++) + vt_data[i] = tt_data[i]; +} + +template +static void +convert_ints (const T *data, void *conv_data, octave_idx_type n_elts, + bool swap) +{ + typedef typename V::val_type val_type; + + val_type *vt_data = static_cast (conv_data); + + for (octave_idx_type i = 0; i < n_elts; i++) + { + // Yes, we want saturation semantics when converting to an integer type. + V val (data[i]); + + vt_data[i] = val.value (); + + if (swap) + swap_bytes (&vt_data[i]); + } +} + +template +class ultimate_element_type +{ +public: + typedef T type; +}; + +template +class ultimate_element_type> +{ +public: + typedef T type; +}; + +template +static bool +convert_data (const T *data, void *conv_data, octave_idx_type n_elts, + oct_data_conv::data_type output_type, + mach_info::float_format flt_fmt) +{ + bool retval = true; + + bool swap = false; + + if (mach_info::words_big_endian ()) + swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian); + else + swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian); + + bool do_float_conversion = flt_fmt != mach_info::float_format (); + + typedef typename ultimate_element_type::type ult_elt_type; + + switch (output_type) + { + case oct_data_conv::dt_char: + convert_chars (data, conv_data, n_elts); + break; + + case oct_data_conv::dt_schar: + convert_chars (data, conv_data, n_elts); + break; + + case oct_data_conv::dt_uchar: + convert_chars (data, conv_data, n_elts); + break; + + case oct_data_conv::dt_int8: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_uint8: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_int16: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_uint16: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_int32: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_uint32: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_int64: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_uint64: + convert_ints (data, conv_data, n_elts, swap); + break; + + case oct_data_conv::dt_single: { - std::ostream& os = *osp; - - if (os) + float *vt_data = static_cast (conv_data); + + for (octave_idx_type i = 0; i < n_elts; i++) { - os.write (static_cast (data), nbytes); - - if (os) - status = true; + vt_data[i] = data[i]; + + if (do_float_conversion) + do_float_format_conversion (&vt_data[i], 1, flt_fmt); } } - - return status; - } - - bool - stream::skip_bytes (std::size_t skip) - { - bool status = false; - - std::ostream *osp = output_stream (); - - if (! osp) - return false; - - std::ostream& os = *osp; - - // Seek to skip when inside bounds of existing file. - // Otherwise, write NUL to skip. - off_t orig_pos = tell (); - - seek (0, SEEK_END); - - off_t eof_pos = tell (); - - // Is it possible for this to fail to return us to the original position? - seek (orig_pos, SEEK_SET); - - std::size_t remaining = eof_pos - orig_pos; - - if (remaining < skip) + break; + + case oct_data_conv::dt_double: { - seek (0, SEEK_END); - - // FIXME: probably should try to write larger blocks... - unsigned char zero = 0; - for (std::size_t j = 0; j < skip - remaining; j++) - os.write (reinterpret_cast (&zero), 1); + double *vt_data = static_cast (conv_data); + + for (octave_idx_type i = 0; i < n_elts; i++) + { + vt_data[i] = data[i]; + + if (do_float_conversion) + do_double_format_conversion (&vt_data[i], 1, flt_fmt); + } } - else - seek (skip, SEEK_CUR); - - if (os) - status = true; - - return status; - } - - template - octave_idx_type - stream::write (const Array& data, octave_idx_type block_size, - oct_data_conv::data_type output_type, - octave_idx_type skip, - mach_info::float_format flt_fmt) - { - bool swap = false; - - if (mach_info::words_big_endian ()) - swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian); - else - swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian); - - bool do_data_conversion = (swap || ! is_equivalent_type (output_type) - || flt_fmt != mach_info::float_format ()); - - octave_idx_type nel = data.numel (); - - octave_idx_type chunk_size; - - if (skip != 0) - chunk_size = block_size; - else if (do_data_conversion) - chunk_size = 1024 * 1024; - else - chunk_size = nel; - - octave_idx_type i = 0; - - const T *pdata = data.data (); - - while (i < nel) - { - if (skip != 0) - { - if (! skip_bytes (skip)) - return -1; - } - - octave_idx_type remaining_nel = nel - i; - - if (chunk_size > remaining_nel) - chunk_size = remaining_nel; - - bool status = false; - - if (do_data_conversion) - { - std::size_t output_size - = chunk_size * oct_data_conv::data_type_size (output_type); - - OCTAVE_LOCAL_BUFFER (unsigned char, conv_data, output_size); - - status = convert_data (&pdata[i], conv_data, chunk_size, - output_type, flt_fmt); - - if (status) - status = write_bytes (conv_data, output_size); - } - else - status = write_bytes (pdata, sizeof (T) * chunk_size); - - if (! status) - return -1; - - i += chunk_size; - } - - return nel; - } + break; + + default: + ::error ("write: invalid type specification"); + } + + return retval; +} + +bool +stream::write_bytes (const void *data, std::size_t nbytes) +{ + bool status = false; + + std::ostream *osp = output_stream (); + + if (osp) + { + std::ostream& os = *osp; + + if (os) + { + os.write (static_cast (data), nbytes); + + if (os) + status = true; + } + } + + return status; +} + +bool +stream::skip_bytes (std::size_t skip) +{ + bool status = false; + + std::ostream *osp = output_stream (); + + if (! osp) + return false; + + std::ostream& os = *osp; + + // Seek to skip when inside bounds of existing file. + // Otherwise, write NUL to skip. + off_t orig_pos = tell (); + + seek (0, SEEK_END); + + off_t eof_pos = tell (); + + // Is it possible for this to fail to return us to the original position? + seek (orig_pos, SEEK_SET); + + std::size_t remaining = eof_pos - orig_pos; + + if (remaining < skip) + { + seek (0, SEEK_END); + + // FIXME: probably should try to write larger blocks... + unsigned char zero = 0; + for (std::size_t j = 0; j < skip - remaining; j++) + os.write (reinterpret_cast (&zero), 1); + } + else + seek (skip, SEEK_CUR); + + if (os) + status = true; + + return status; +} + +template +octave_idx_type +stream::write (const Array& data, octave_idx_type block_size, + oct_data_conv::data_type output_type, + octave_idx_type skip, + mach_info::float_format flt_fmt) +{ + bool swap = false; + + if (mach_info::words_big_endian ()) + swap = (flt_fmt == mach_info::flt_fmt_ieee_little_endian); + else + swap = (flt_fmt == mach_info::flt_fmt_ieee_big_endian); + + bool do_data_conversion = (swap || ! is_equivalent_type (output_type) + || flt_fmt != mach_info::float_format ()); + + octave_idx_type nel = data.numel (); + + octave_idx_type chunk_size; + + if (skip != 0) + chunk_size = block_size; + else if (do_data_conversion) + chunk_size = 1024 * 1024; + else + chunk_size = nel; + + octave_idx_type i = 0; + + const T *pdata = data.data (); + + while (i < nel) + { + if (skip != 0) + { + if (! skip_bytes (skip)) + return -1; + } + + octave_idx_type remaining_nel = nel - i; + + if (chunk_size > remaining_nel) + chunk_size = remaining_nel; + + bool status = false; + + if (do_data_conversion) + { + std::size_t output_size + = chunk_size * oct_data_conv::data_type_size (output_type); + + OCTAVE_LOCAL_BUFFER (unsigned char, conv_data, output_size); + + status = convert_data (&pdata[i], conv_data, chunk_size, + output_type, flt_fmt); + + if (status) + status = write_bytes (conv_data, output_size); + } + else + status = write_bytes (pdata, sizeof (T) * chunk_size); + + if (! status) + return -1; + + i += chunk_size; + } + + return nel; +} #define INSTANTIATE_WRITE(T) \ template \ @@ -7149,604 +7155,604 @@ octave_idx_type skip, \ mach_info::float_format flt_fmt) - INSTANTIATE_WRITE (octave_int8); - INSTANTIATE_WRITE (octave_uint8); - INSTANTIATE_WRITE (octave_int16); - INSTANTIATE_WRITE (octave_uint16); - INSTANTIATE_WRITE (octave_int32); - INSTANTIATE_WRITE (octave_uint32); - INSTANTIATE_WRITE (octave_int64); - INSTANTIATE_WRITE (octave_uint64); - INSTANTIATE_WRITE (int8_t); - INSTANTIATE_WRITE (uint8_t); - INSTANTIATE_WRITE (int16_t); - INSTANTIATE_WRITE (uint16_t); - INSTANTIATE_WRITE (int32_t); - INSTANTIATE_WRITE (uint32_t); - INSTANTIATE_WRITE (int64_t); - INSTANTIATE_WRITE (uint64_t); - INSTANTIATE_WRITE (bool); +INSTANTIATE_WRITE (octave_int8); +INSTANTIATE_WRITE (octave_uint8); +INSTANTIATE_WRITE (octave_int16); +INSTANTIATE_WRITE (octave_uint16); +INSTANTIATE_WRITE (octave_int32); +INSTANTIATE_WRITE (octave_uint32); +INSTANTIATE_WRITE (octave_int64); +INSTANTIATE_WRITE (octave_uint64); +INSTANTIATE_WRITE (int8_t); +INSTANTIATE_WRITE (uint8_t); +INSTANTIATE_WRITE (int16_t); +INSTANTIATE_WRITE (uint16_t); +INSTANTIATE_WRITE (int32_t); +INSTANTIATE_WRITE (uint32_t); +INSTANTIATE_WRITE (int64_t); +INSTANTIATE_WRITE (uint64_t); +INSTANTIATE_WRITE (bool); #if defined (OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES) - INSTANTIATE_WRITE (char); +INSTANTIATE_WRITE (char); #endif - INSTANTIATE_WRITE (float); - INSTANTIATE_WRITE (double); - - octave_value - stream::scanf (const std::string& fmt, const Array& size, - octave_idx_type& count, const std::string& who) - { - octave_value retval; - - if (stream_ok ()) - retval = m_rep->scanf (fmt, size, count, who); - - return retval; - } - - octave_value - stream::scanf (const octave_value& fmt, const Array& size, - octave_idx_type& count, const std::string& who) - { - octave_value retval = Matrix (); - - if (fmt.is_string ()) - { - std::string sfmt = fmt.string_value (); - - if (fmt.is_sq_string ()) - sfmt = do_string_escapes (sfmt); - - retval = scanf (sfmt, size, count, who); - } - else - { - // Note: error is member fcn from stream, not ::error. - error (who + ": format must be a string"); - } - - return retval; - } - - octave_value_list - stream::oscanf (const std::string& fmt, const std::string& who) - { - octave_value_list retval; - - if (stream_ok ()) - retval = m_rep->oscanf (fmt, who); - - return retval; - } - - octave_value_list - stream::oscanf (const octave_value& fmt, const std::string& who) - { - octave_value_list retval; - - if (fmt.is_string ()) - { - std::string sfmt = fmt.string_value (); - - if (fmt.is_sq_string ()) - sfmt = do_string_escapes (sfmt); - - retval = oscanf (sfmt, who); - } - else - { - // Note: error is member fcn from stream, not ::error. - error (who + ": format must be a string"); - } - - return retval; - } - - octave_value - stream::textscan (const std::string& fmt, octave_idx_type ntimes, - const octave_value_list& options, - const std::string& who, octave_idx_type& count) - { - return (stream_ok () - ? m_rep->do_textscan (fmt, ntimes, options, who, count) - : octave_value ()); - } - - int - stream::printf (const std::string& fmt, const octave_value_list& args, - const std::string& who) - { - int retval = -1; - - if (stream_ok ()) - retval = m_rep->printf (fmt, args, who); - - return retval; - } - - int - stream::printf (const octave_value& fmt, const octave_value_list& args, - const std::string& who) - { - int retval = 0; - - if (fmt.is_string ()) - { - std::string sfmt = fmt.string_value (); - - if (fmt.is_sq_string ()) - sfmt = do_string_escapes (sfmt); - - retval = printf (sfmt, args, who); - } - else - { - // Note: error is member fcn from stream, not ::error. - error (who + ": format must be a string"); - } - - return retval; - } - - int - stream::puts (const std::string& s, const std::string& who) - { - int retval = -1; - - if (stream_ok ()) - retval = m_rep->puts (s, who); - - return retval; - } - - // FIXME: maybe this should work for string arrays too. - - int - stream::puts (const octave_value& tc_s, const std::string& who) - { - int retval = -1; - - if (tc_s.is_string ()) - { - std::string s = tc_s.string_value (); - retval = puts (s, who); - } - else - { - // Note: error is member fcn from stream, not ::error. - error (who + ": argument must be a string"); - } - - return retval; - } - - bool - stream::eof (void) const - { - int retval = -1; - - if (stream_ok ()) - retval = m_rep->eof (); - - return retval; - } - - std::string - stream::error (bool clear, int& err_num) - { - std::string retval = "invalid stream object"; - - if (stream_ok (false)) - retval = m_rep->error (clear, err_num); - - return retval; - } - - std::string - stream::name (void) const - { - std::string retval; - - if (stream_ok ()) - retval = m_rep->name (); - - return retval; - } - - int - stream::mode (void) const - { - int retval = 0; - - if (stream_ok ()) - retval = m_rep->mode (); - - return retval; - } - - mach_info::float_format - stream::float_format (void) const - { - mach_info::float_format retval = mach_info::flt_fmt_unknown; - - if (stream_ok ()) - retval = m_rep->float_format (); - - return retval; - } - - std::string - stream::mode_as_string (int mode) - { - std::string retval = "???"; - std::ios::openmode in_mode = static_cast (mode); - - if (in_mode == std::ios::in) - retval = "r"; - else if (in_mode == std::ios::out - || in_mode == (std::ios::out | std::ios::trunc)) - retval = "w"; - else if (in_mode == (std::ios::out | std::ios::app)) - retval = "a"; - else if (in_mode == (std::ios::in | std::ios::out)) - retval = "r+"; - else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc)) - retval = "w+"; - else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate)) - retval = "a+"; - else if (in_mode == (std::ios::in | std::ios::binary)) - retval = "rb"; - else if (in_mode == (std::ios::out | std::ios::binary) - || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary)) - retval = "wb"; - else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary)) - retval = "ab"; - else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary)) - retval = "r+b"; - else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc - | std::ios::binary)) - retval = "w+b"; - else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate - | std::ios::binary)) - retval = "a+b"; - +INSTANTIATE_WRITE (float); +INSTANTIATE_WRITE (double); + +octave_value +stream::scanf (const std::string& fmt, const Array& size, + octave_idx_type& count, const std::string& who) +{ + octave_value retval; + + if (stream_ok ()) + retval = m_rep->scanf (fmt, size, count, who); + + return retval; +} + +octave_value +stream::scanf (const octave_value& fmt, const Array& size, + octave_idx_type& count, const std::string& who) +{ + octave_value retval = Matrix (); + + if (fmt.is_string ()) + { + std::string sfmt = fmt.string_value (); + + if (fmt.is_sq_string ()) + sfmt = do_string_escapes (sfmt); + + retval = scanf (sfmt, size, count, who); + } + else + { + // Note: error is member fcn from stream, not ::error. + error (who + ": format must be a string"); + } + + return retval; +} + +octave_value_list +stream::oscanf (const std::string& fmt, const std::string& who) +{ + octave_value_list retval; + + if (stream_ok ()) + retval = m_rep->oscanf (fmt, who); + + return retval; +} + +octave_value_list +stream::oscanf (const octave_value& fmt, const std::string& who) +{ + octave_value_list retval; + + if (fmt.is_string ()) + { + std::string sfmt = fmt.string_value (); + + if (fmt.is_sq_string ()) + sfmt = do_string_escapes (sfmt); + + retval = oscanf (sfmt, who); + } + else + { + // Note: error is member fcn from stream, not ::error. + error (who + ": format must be a string"); + } + + return retval; +} + +octave_value +stream::textscan (const std::string& fmt, octave_idx_type ntimes, + const octave_value_list& options, + const std::string& who, octave_idx_type& count) +{ + return (stream_ok () + ? m_rep->do_textscan (fmt, ntimes, options, who, count) + : octave_value ()); +} + +int +stream::printf (const std::string& fmt, const octave_value_list& args, + const std::string& who) +{ + int retval = -1; + + if (stream_ok ()) + retval = m_rep->printf (fmt, args, who); + + return retval; +} + +int +stream::printf (const octave_value& fmt, const octave_value_list& args, + const std::string& who) +{ + int retval = 0; + + if (fmt.is_string ()) + { + std::string sfmt = fmt.string_value (); + + if (fmt.is_sq_string ()) + sfmt = do_string_escapes (sfmt); + + retval = printf (sfmt, args, who); + } + else + { + // Note: error is member fcn from stream, not ::error. + error (who + ": format must be a string"); + } + + return retval; +} + +int +stream::puts (const std::string& s, const std::string& who) +{ + int retval = -1; + + if (stream_ok ()) + retval = m_rep->puts (s, who); + + return retval; +} + +// FIXME: maybe this should work for string arrays too. + +int +stream::puts (const octave_value& tc_s, const std::string& who) +{ + int retval = -1; + + if (tc_s.is_string ()) + { + std::string s = tc_s.string_value (); + retval = puts (s, who); + } + else + { + // Note: error is member fcn from stream, not ::error. + error (who + ": argument must be a string"); + } + + return retval; +} + +bool +stream::eof (void) const +{ + int retval = -1; + + if (stream_ok ()) + retval = m_rep->eof (); + + return retval; +} + +std::string +stream::error (bool clear, int& err_num) +{ + std::string retval = "invalid stream object"; + + if (stream_ok (false)) + retval = m_rep->error (clear, err_num); + + return retval; +} + +std::string +stream::name (void) const +{ + std::string retval; + + if (stream_ok ()) + retval = m_rep->name (); + + return retval; +} + +int +stream::mode (void) const +{ + int retval = 0; + + if (stream_ok ()) + retval = m_rep->mode (); + + return retval; +} + +mach_info::float_format +stream::float_format (void) const +{ + mach_info::float_format retval = mach_info::flt_fmt_unknown; + + if (stream_ok ()) + retval = m_rep->float_format (); + + return retval; +} + +std::string +stream::mode_as_string (int mode) +{ + std::string retval = "???"; + std::ios::openmode in_mode = static_cast (mode); + + if (in_mode == std::ios::in) + retval = "r"; + else if (in_mode == std::ios::out + || in_mode == (std::ios::out | std::ios::trunc)) + retval = "w"; + else if (in_mode == (std::ios::out | std::ios::app)) + retval = "a"; + else if (in_mode == (std::ios::in | std::ios::out)) + retval = "r+"; + else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc)) + retval = "w+"; + else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate)) + retval = "a+"; + else if (in_mode == (std::ios::in | std::ios::binary)) + retval = "rb"; + else if (in_mode == (std::ios::out | std::ios::binary) + || in_mode == (std::ios::out | std::ios::trunc | std::ios::binary)) + retval = "wb"; + else if (in_mode == (std::ios::out | std::ios::app | std::ios::binary)) + retval = "ab"; + else if (in_mode == (std::ios::in | std::ios::out | std::ios::binary)) + retval = "r+b"; + else if (in_mode == (std::ios::in | std::ios::out | std::ios::trunc + | std::ios::binary)) + retval = "w+b"; + else if (in_mode == (std::ios::in | std::ios::out | std::ios::ate + | std::ios::binary)) + retval = "a+b"; + + return retval; +} + +stream_list::stream_list (interpreter& interp) + : m_list (), m_lookup_cache (m_list.end ()), m_stdin_file (-1), + m_stdout_file (-1), m_stderr_file (-1) +{ + stream stdin_stream = istream::create (&std::cin, "stdin"); + + // This uses octave_stdout (see pager.h), not std::cout so that + // Octave's standard output stream will pass through the pager. + + // FIXME: we should be accessing octave_stdout from the interpreter. + + output_system& output_sys = interp.get_output_system (); + + stream stdout_stream + = ostream::create (&(output_sys.__stdout__ ()), "stdout"); + + stream stderr_stream = ostream::create (&std::cerr, "stderr"); + + m_stdin_file = insert (stdin_stream); + m_stdout_file = insert (stdout_stream); + m_stderr_file = insert (stderr_stream); +} + +stream_list::~stream_list (void) +{ + clear (); +} + +int stream_list::insert (stream& os) +{ + // Insert item with key corresponding to file-descriptor. + + int stream_number = os.file_number (); + + if (stream_number == -1) + return stream_number; + + // Should we test for + // + // (m_list.find (stream_number) != m_list.end () + // && m_list[stream_number].is_open ()) + // + // and respond with "error ("internal error: ...")"? It should not + // happen except for some bug or if the user has opened a stream with + // an interpreted command, but closed it directly with a system call + // in an oct-file; then the kernel knows the fd is free, but Octave + // does not know. If it happens, it should not do harm here to simply + // overwrite this entry, although the wrong entry might have done harm + // before. + + if (m_list.size () >= m_list.max_size ()) + ::error ("could not create file id"); + + m_list[stream_number] = os; + + return stream_number; +} + +OCTAVE_NORETURN static +void +err_invalid_file_id (int fid, const std::string& who) +{ + if (who.empty ()) + ::error ("invalid stream number = %d", fid); + else + ::error ("%s: invalid stream number = %d", who.c_str (), fid); +} + +stream stream_list::lookup (int fid, const std::string& who) const +{ + stream retval; + + if (fid < 0) + err_invalid_file_id (fid, who); + + if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid) + retval = m_lookup_cache->second; + else + { + ostrl_map::const_iterator iter = m_list.find (fid); + + if (iter == m_list.end ()) + err_invalid_file_id (fid, who); + + retval = iter->second; + m_lookup_cache = iter; + } + + return retval; +} + +stream stream_list::lookup (const octave_value& fid, + const std::string& who) const +{ + int i = get_file_number (fid); + + return lookup (i, who); +} + +int stream_list::remove (int fid, const std::string& who) +{ + // Can't remove stdin (std::cin), stdout (std::cout), or stderr (std::cerr). + if (fid < 3) + err_invalid_file_id (fid, who); + + auto iter = m_list.find (fid); + + if (iter == m_list.end ()) + err_invalid_file_id (fid, who); + + stream os = iter->second; + m_list.erase (iter); + m_lookup_cache = m_list.end (); + + // FIXME: is this check redundant? + if (! os.is_valid ()) + err_invalid_file_id (fid, who); + + os.close (); + + return 0; +} + +int stream_list::remove (const octave_value& fid, const std::string& who) +{ + int retval = -1; + + if (fid.is_string () && fid.string_value () == "all") + { + clear (false); + + retval = 0; + } + else + { + int i = get_file_number (fid); + + retval = remove (i, who); + } + + return retval; +} + +void stream_list::clear (bool flush) +{ + if (flush) + { + // Flush stdout and stderr. + m_list[1].flush (); + m_list[2].flush (); + } + + for (auto iter = m_list.begin (); iter != m_list.end (); ) + { + int fid = iter->first; + if (fid < 3) // Don't delete stdin, stdout, stderr + { + iter++; + continue; + } + + stream os = iter->second; + + std::string name = os.name (); + std::transform (name.begin (), name.end (), name.begin (), tolower); + + // FIXME: This test for gnuplot is hardly foolproof. + if (name.find ("gnuplot") != std::string::npos) + { + // Don't close down pipes to gnuplot + iter++; + continue; + } + + // Normal file handle. Close and delete from m_list. + if (os.is_valid ()) + os.close (); + + m_list.erase (iter++); + } + + m_lookup_cache = m_list.end (); +} + +string_vector stream_list::get_info (int fid) const +{ + string_vector retval (4); + + if (fid < 0) return retval; - } - - stream_list::stream_list (interpreter& interp) - : m_list (), m_lookup_cache (m_list.end ()), m_stdin_file (-1), - m_stdout_file (-1), m_stderr_file (-1) - { - stream stdin_stream = istream::create (&std::cin, "stdin"); - - // This uses octave_stdout (see pager.h), not std::cout so that - // Octave's standard output stream will pass through the pager. - - // FIXME: we should be accessing octave_stdout from the interpreter. - - output_system& output_sys = interp.get_output_system (); - - stream stdout_stream - = ostream::create (&(output_sys.__stdout__ ()), "stdout"); - - stream stderr_stream = ostream::create (&std::cerr, "stderr"); - - m_stdin_file = insert (stdin_stream); - m_stdout_file = insert (stdout_stream); - m_stderr_file = insert (stderr_stream); - } - - stream_list::~stream_list (void) - { - clear (); - } - - int stream_list::insert (stream& os) - { - // Insert item with key corresponding to file-descriptor. - - int stream_number = os.file_number (); - - if (stream_number == -1) - return stream_number; - - // Should we test for - // - // (m_list.find (stream_number) != m_list.end () - // && m_list[stream_number].is_open ()) - // - // and respond with "error ("internal error: ...")"? It should not - // happen except for some bug or if the user has opened a stream with - // an interpreted command, but closed it directly with a system call - // in an oct-file; then the kernel knows the fd is free, but Octave - // does not know. If it happens, it should not do harm here to simply - // overwrite this entry, although the wrong entry might have done harm - // before. - - if (m_list.size () >= m_list.max_size ()) - ::error ("could not create file id"); - - m_list[stream_number] = os; - - return stream_number; - } - - OCTAVE_NORETURN static - void - err_invalid_file_id (int fid, const std::string& who) - { - if (who.empty ()) - ::error ("invalid stream number = %d", fid); - else - ::error ("%s: invalid stream number = %d", who.c_str (), fid); - } - - stream stream_list::lookup (int fid, const std::string& who) const - { - stream retval; - - if (fid < 0) - err_invalid_file_id (fid, who); - - if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid) - retval = m_lookup_cache->second; - else - { - ostrl_map::const_iterator iter = m_list.find (fid); - - if (iter == m_list.end ()) - err_invalid_file_id (fid, who); - - retval = iter->second; - m_lookup_cache = iter; - } - - return retval; - } - - stream stream_list::lookup (const octave_value& fid, - const std::string& who) const - { - int i = get_file_number (fid); - - return lookup (i, who); - } - - int stream_list::remove (int fid, const std::string& who) - { - // Can't remove stdin (std::cin), stdout (std::cout), or stderr (std::cerr). - if (fid < 3) - err_invalid_file_id (fid, who); - - auto iter = m_list.find (fid); - - if (iter == m_list.end ()) - err_invalid_file_id (fid, who); - - stream os = iter->second; - m_list.erase (iter); - m_lookup_cache = m_list.end (); - - // FIXME: is this check redundant? - if (! os.is_valid ()) - err_invalid_file_id (fid, who); - - os.close (); - - return 0; - } - - int stream_list::remove (const octave_value& fid, const std::string& who) - { - int retval = -1; - - if (fid.is_string () && fid.string_value () == "all") - { - clear (false); - - retval = 0; - } - else - { - int i = get_file_number (fid); - - retval = remove (i, who); - } - + + stream os; + if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid) + os = m_lookup_cache->second; + else + { + ostrl_map::const_iterator iter = m_list.find (fid); + + if (iter == m_list.end ()) + return retval; + + os = iter->second; + m_lookup_cache = iter; + } + + if (! os.is_valid ()) return retval; - } - - void stream_list::clear (bool flush) - { - if (flush) - { - // Flush stdout and stderr. - m_list[1].flush (); - m_list[2].flush (); - } - - for (auto iter = m_list.begin (); iter != m_list.end (); ) - { - int fid = iter->first; - if (fid < 3) // Don't delete stdin, stdout, stderr - { - iter++; - continue; - } - - stream os = iter->second; - - std::string name = os.name (); - std::transform (name.begin (), name.end (), name.begin (), tolower); - - // FIXME: This test for gnuplot is hardly foolproof. - if (name.find ("gnuplot") != std::string::npos) - { - // Don't close down pipes to gnuplot - iter++; - continue; - } - - // Normal file handle. Close and delete from m_list. - if (os.is_valid ()) - os.close (); - - m_list.erase (iter++); - } - - m_lookup_cache = m_list.end (); - } - - string_vector stream_list::get_info (int fid) const - { - string_vector retval (4); - - if (fid < 0) - return retval; - - stream os; - if (m_lookup_cache != m_list.end () && m_lookup_cache->first == fid) - os = m_lookup_cache->second; - else - { - ostrl_map::const_iterator iter = m_list.find (fid); - - if (iter == m_list.end ()) - return retval; - - os = iter->second; - m_lookup_cache = iter; - } - - if (! os.is_valid ()) - return retval; - - retval(0) = os.name (); - retval(1) = stream::mode_as_string (os.mode ()); - retval(2) = mach_info::float_format_as_string (os.float_format ()); - retval(3) = os.encoding (); - - return retval; - } - - string_vector stream_list::get_info (const octave_value& fid) const - { - int conv_err = 0; - - if (fid.is_single_type ()) - ::error ("file id must be a file object or integer value"); - - int int_fid = convert_to_valid_int (fid, conv_err); - - if (conv_err) - ::error ("file id must be a file object or integer value"); - - return get_info (int_fid); - } - - std::string stream_list::list_open_files (void) const - { - std::ostringstream buf; - - buf << "\n" - << " number mode arch name\n" - << " ------ ---- ---- ----\n"; - - for (const auto& fid_strm : m_list) - { - stream os = fid_strm.second; - - buf << " " - << std::setiosflags (std::ios::right) - << std::setw (4) << fid_strm.first << " " + + retval(0) = os.name (); + retval(1) = stream::mode_as_string (os.mode ()); + retval(2) = mach_info::float_format_as_string (os.float_format ()); + retval(3) = os.encoding (); + + return retval; +} + +string_vector stream_list::get_info (const octave_value& fid) const +{ + int conv_err = 0; + + if (fid.is_single_type ()) + ::error ("file id must be a file object or integer value"); + + int int_fid = convert_to_valid_int (fid, conv_err); + + if (conv_err) + ::error ("file id must be a file object or integer value"); + + return get_info (int_fid); +} + +std::string stream_list::list_open_files (void) const +{ + std::ostringstream buf; + + buf << "\n" + << " number mode arch name\n" + << " ------ ---- ---- ----\n"; + + for (const auto& fid_strm : m_list) + { + stream os = fid_strm.second; + + buf << " " + << std::setiosflags (std::ios::right) + << std::setw (4) << fid_strm.first << " " // reset necessary in addition to setiosflags since this is one stmt. - << std::resetiosflags (std::ios::adjustfield) - << std::setiosflags (std::ios::left) - << std::setw (3) - << stream::mode_as_string (os.mode ()) - << " " - << std::setw (9) - << mach_info::float_format_as_string (os.float_format ()) - << " " - << os.name () << "\n"; - } - - buf << "\n"; - - return buf.str (); - } - - octave_value stream_list::open_file_numbers (void) const - { - Matrix retval (1, m_list.size (), 0.0); - - int num_open = 0; - - for (const auto& fid_strm : m_list) - { - // Skip stdin, stdout, and stderr. - if (fid_strm.first > 2 && fid_strm.second) - retval(0, num_open++) = fid_strm.first; - } - - retval.resize ((num_open > 0), num_open); - - return retval; - } - - int stream_list::get_file_number (const octave_value& fid) const - { - int retval = -1; - - if (fid.is_string ()) - { - std::string nm = fid.string_value (); - - for (const auto& fid_strm : m_list) - { - // stdin, stdout, and stderr are unnamed. - if (fid_strm.first > 2) - { - stream os = fid_strm.second; - - if (os && os.name () == nm) - { - retval = fid_strm.first; - break; - } - } - } - } - else if (fid.is_single_type ()) - ::error ("file id must be a file object, std::string, or integer value"); - else - { - int conv_err = 0; - - int int_fid = convert_to_valid_int (fid, conv_err); - - if (conv_err) - ::error ("file id must be a file object, std::string, or integer value"); - - retval = int_fid; - } - - return retval; - } - - octave_value stream_list::stdin_file (void) const - { - return octave_value (m_stdin_file); - } - - octave_value stream_list::stdout_file (void) const - { - return octave_value (m_stdout_file); - } - - octave_value stream_list::stderr_file (void) const - { - return octave_value (m_stderr_file); - } + << std::resetiosflags (std::ios::adjustfield) + << std::setiosflags (std::ios::left) + << std::setw (3) + << stream::mode_as_string (os.mode ()) + << " " + << std::setw (9) + << mach_info::float_format_as_string (os.float_format ()) + << " " + << os.name () << "\n"; + } + + buf << "\n"; + + return buf.str (); +} + +octave_value stream_list::open_file_numbers (void) const +{ + Matrix retval (1, m_list.size (), 0.0); + + int num_open = 0; + + for (const auto& fid_strm : m_list) + { + // Skip stdin, stdout, and stderr. + if (fid_strm.first > 2 && fid_strm.second) + retval(0, num_open++) = fid_strm.first; + } + + retval.resize ((num_open > 0), num_open); + + return retval; +} + +int stream_list::get_file_number (const octave_value& fid) const +{ + int retval = -1; + + if (fid.is_string ()) + { + std::string nm = fid.string_value (); + + for (const auto& fid_strm : m_list) + { + // stdin, stdout, and stderr are unnamed. + if (fid_strm.first > 2) + { + stream os = fid_strm.second; + + if (os && os.name () == nm) + { + retval = fid_strm.first; + break; + } + } + } + } + else if (fid.is_single_type ()) + ::error ("file id must be a file object, std::string, or integer value"); + else + { + int conv_err = 0; + + int int_fid = convert_to_valid_int (fid, conv_err); + + if (conv_err) + ::error ("file id must be a file object, std::string, or integer value"); + + retval = int_fid; + } + + return retval; +} + +octave_value stream_list::stdin_file (void) const +{ + return octave_value (m_stdin_file); +} + +octave_value stream_list::stdout_file (void) const +{ + return octave_value (m_stdout_file); +} + +octave_value stream_list::stderr_file (void) const +{ + return octave_value (m_stderr_file); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-stream.h --- a/libinterp/corefcn/oct-stream.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-stream.h Thu Dec 01 20:05:44 2022 -0800 @@ -50,503 +50,503 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; - // These are only needed as arguments to private functions, so they - // are also treated as private. +// These are only needed as arguments to private functions, so they +// are also treated as private. - class scanf_format_elt; - class scanf_format_list; +class scanf_format_elt; +class scanf_format_list; - class printf_format_elt; - class printf_format_list; +class printf_format_elt; +class printf_format_list; - // Provide an interface for Octave streams. +// Provide an interface for Octave streams. - class - OCTINTERP_API - base_stream - { - friend class stream; +class +OCTINTERP_API +base_stream +{ + friend class stream; - public: +public: - base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out, - mach_info::float_format ff = mach_info::native_float_format (), - const std::string& encoding = "utf-8") - : m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding), - m_conv_ostream (nullptr), m_fail (false), m_open_state (true), - m_errmsg () - { } + base_stream (std::ios::openmode arg_md = std::ios::in | std::ios::out, + mach_info::float_format ff = mach_info::native_float_format (), + const std::string& encoding = "utf-8") + : m_mode (arg_md), m_flt_fmt (ff), m_encoding (encoding), + m_conv_ostream (nullptr), m_fail (false), m_open_state (true), + m_errmsg () + { } - // No copying! + // No copying! - base_stream (const base_stream&) = delete; + base_stream (const base_stream&) = delete; - base_stream& operator = (const base_stream&) = delete; + base_stream& operator = (const base_stream&) = delete; - virtual ~base_stream (void) = default; + virtual ~base_stream (void) = default; - // The remaining functions are not specific to input or output only, - // and must be provided by the derived classes. + // The remaining functions are not specific to input or output only, + // and must be provided by the derived classes. - // Position a stream at OFFSET relative to ORIGIN. + // Position a stream at OFFSET relative to ORIGIN. - virtual int seek (off_t offset, int origin) = 0; + virtual int seek (off_t offset, int origin) = 0; - // Return current stream position. + // Return current stream position. - virtual off_t tell (void) = 0; + virtual off_t tell (void) = 0; - // Return TRUE if EOF has been reached on this stream. + // Return TRUE if EOF has been reached on this stream. - virtual bool eof (void) const = 0; + virtual bool eof (void) const = 0; - // The name of the file. + // The name of the file. - virtual std::string name (void) const = 0; + virtual std::string name (void) const = 0; - // If the derived class provides this function and it returns a - // pointer to a valid istream, scanf(), read(), getl(), and gets() - // will automatically work for this stream. + // If the derived class provides this function and it returns a + // pointer to a valid istream, scanf(), read(), getl(), and gets() + // will automatically work for this stream. - virtual std::istream * input_stream (void) { return nullptr; } + virtual std::istream * input_stream (void) { return nullptr; } - // If the derived class provides this function and it returns a - // pointer to a valid ostream, flush(), write(), and printf() will - // automatically work for this stream. + // If the derived class provides this function and it returns a + // pointer to a valid ostream, flush(), write(), and printf() will + // automatically work for this stream. - virtual std::ostream * output_stream (void) { return nullptr; } + virtual std::ostream * output_stream (void) { return nullptr; } - // Return either the original output stream or one wrapped with the - // encoding facet. + // Return either the original output stream or one wrapped with the + // encoding facet. - std::ostream * preferred_output_stream (void) - { - if (! m_encoding.compare ("utf-8")) - return output_stream (); + std::ostream * preferred_output_stream (void) + { + if (! m_encoding.compare ("utf-8")) + return output_stream (); - if (m_conv_ostream) - return m_conv_ostream; + if (m_conv_ostream) + return m_conv_ostream; - // wrap the output stream with encoding conversion facet - std::ostream *os = output_stream (); - if (os && *os) + // wrap the output stream with encoding conversion facet + std::ostream *os = output_stream (); + if (os && *os) { convfacet_u8 *facet = new convfacet_u8 (m_encoding); std::wbuffer_convert *converter = new std::wbuffer_convert (os->rdbuf (), - facet); + facet); m_conv_ostream = new std::ostream (converter); } - return (m_conv_ostream ? m_conv_ostream : output_stream ()); - } + return (m_conv_ostream ? m_conv_ostream : output_stream ()); + } - // Return TRUE if this stream is open. + // Return TRUE if this stream is open. - bool is_open (void) const { return m_open_state; } + bool is_open (void) const { return m_open_state; } - virtual void do_close (void) { } + virtual void do_close (void) { } - void close (void) - { - if (is_open ()) - { - m_open_state = false; - do_close (); - } - } + void close (void) + { + if (is_open ()) + { + m_open_state = false; + do_close (); + } + } - virtual int file_number (void) const - { - // Kluge alert! + virtual int file_number (void) const + { + // Kluge alert! - if (name () == "stdin") - return 0; - else if (name () == "stdout") - return 1; - else if (name () == "stderr") - return 2; - else - return -1; - } + if (name () == "stdin") + return 0; + else if (name () == "stdout") + return 1; + else if (name () == "stderr") + return 2; + else + return -1; + } - bool ok (void) const { return ! m_fail; } + bool ok (void) const { return ! m_fail; } - // Return current error message for this stream. + // Return current error message for this stream. - std::string error (bool clear, int& err_num); + std::string error (bool clear, int& err_num); - protected: +protected: - int mode (void) const { return m_mode; } + int mode (void) const { return m_mode; } - mach_info::float_format float_format (void) const { return m_flt_fmt; } + mach_info::float_format float_format (void) const { return m_flt_fmt; } - std::string encoding (void) const { return m_encoding; } + std::string encoding (void) const { return m_encoding; } - // Set current error state and set fail to TRUE. + // Set current error state and set fail to TRUE. - OCTINTERP_API void error (const std::string& msg); - OCTINTERP_API void error (const std::string& who, const std::string& msg); + OCTINTERP_API void error (const std::string& msg); + OCTINTERP_API void error (const std::string& who, const std::string& msg); - // Clear any error message and set fail to FALSE. + // Clear any error message and set fail to FALSE. - OCTINTERP_API void clear (void); + OCTINTERP_API void clear (void); - // Clear stream state. + // Clear stream state. - OCTINTERP_API void clearerr (void); + OCTINTERP_API void clearerr (void); - private: +private: - // The permission bits for the file. Should be some combination of - // std::ios::open_mode bits. - int m_mode; + // The permission bits for the file. Should be some combination of + // std::ios::open_mode bits. + int m_mode; - // Data format. - mach_info::float_format m_flt_fmt; + // Data format. + mach_info::float_format m_flt_fmt; - // Code page - std::string m_encoding; + // Code page + std::string m_encoding; - // encoding conversion facet - typedef string::deletable_facet convfacet_u8; + // encoding conversion facet + typedef string::deletable_facet convfacet_u8; - // FIXME: Identified by compiler as unused private field. - // Commented out 10/29/2022. - // If there are no repercussions, delete entirely. - // std::wbuffer_convert *m_converter; + // FIXME: Identified by compiler as unused private field. + // Commented out 10/29/2022. + // If there are no repercussions, delete entirely. + // std::wbuffer_convert *m_converter; - // wrappers for encoding conversion - // std::istream *m_conv_istream; + // wrappers for encoding conversion + // std::istream *m_conv_istream; - std::ostream *m_conv_ostream; + std::ostream *m_conv_ostream; - // TRUE if an error has occurred. - bool m_fail; + // TRUE if an error has occurred. + bool m_fail; - // TRUE if this stream is open. - bool m_open_state; + // TRUE if this stream is open. + bool m_open_state; - // Should contain error message if fail is TRUE. - std::string m_errmsg; + // Should contain error message if fail is TRUE. + std::string m_errmsg; - // Functions that are defined for all input streams (input streams - // are those that define is). + // Functions that are defined for all input streams (input streams + // are those that define is). - OCTINTERP_API std::string - do_gets (octave_idx_type max_len, bool& err, bool strip_newline, - const std::string& who /* = "gets" */); + OCTINTERP_API std::string + do_gets (octave_idx_type max_len, bool& err, bool strip_newline, + const std::string& who /* = "gets" */); - OCTINTERP_API std::string - getl (octave_idx_type max_len, bool& err, - const std::string& who /* = "getl" */); - OCTINTERP_API std::string - gets (octave_idx_type max_len, bool& err, - const std::string& who /* = "gets" */); - OCTINTERP_API off_t - skipl (off_t count, bool& err, const std::string& who /* = "skipl" */); + OCTINTERP_API std::string + getl (octave_idx_type max_len, bool& err, + const std::string& who /* = "getl" */); + OCTINTERP_API std::string + gets (octave_idx_type max_len, bool& err, + const std::string& who /* = "gets" */); + OCTINTERP_API off_t + skipl (off_t count, bool& err, const std::string& who /* = "skipl" */); - OCTINTERP_API octave_value - do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, - octave_idx_type nc, bool one_elt_size_spec, - octave_idx_type& count, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value + do_scanf (scanf_format_list& fmt_list, octave_idx_type nr, + octave_idx_type nc, bool one_elt_size_spec, + octave_idx_type& count, const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value - scanf (const std::string& fmt, const Array& size, - octave_idx_type& count, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value + scanf (const std::string& fmt, const Array& size, + octave_idx_type& count, const std::string& who /* = "scanf" */); - OCTINTERP_API bool - do_oscanf (const scanf_format_elt *elt, octave_value&, - const std::string& who /* = "scanf" */); + OCTINTERP_API bool + do_oscanf (const scanf_format_elt *elt, octave_value&, + const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value_list - oscanf (const std::string& fmt, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value_list + oscanf (const std::string& fmt, const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value - do_textscan (const std::string& fmt, octave_idx_type ntimes, - const octave_value_list& options, - const std::string& who, octave_idx_type& count); + OCTINTERP_API octave_value + do_textscan (const std::string& fmt, octave_idx_type ntimes, + const octave_value_list& options, + const std::string& who, octave_idx_type& count); - // Functions that are defined for all output streams (output streams - // are those that define os). + // Functions that are defined for all output streams (output streams + // are those that define os). - OCTINTERP_API int flush (void); + OCTINTERP_API int flush (void); - OCTINTERP_API int - do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt, - int nsa, int sa_1, int sa_2, - const octave_value& val, - const std::string& who); + OCTINTERP_API int + do_numeric_printf_conv (std::ostream& os, const printf_format_elt *elt, + int nsa, int sa_1, int sa_2, + const octave_value& val, + const std::string& who); - OCTINTERP_API void field_width_error (const std::string& who) const; + OCTINTERP_API void field_width_error (const std::string& who) const; - OCTINTERP_API int - do_printf (printf_format_list& fmt_list, const octave_value_list& args, - const std::string& who /* = "printf" */); + OCTINTERP_API int + do_printf (printf_format_list& fmt_list, const octave_value_list& args, + const std::string& who /* = "printf" */); - OCTINTERP_API int - printf (const std::string& fmt, const octave_value_list& args, - const std::string& who /* = "printf" */); + OCTINTERP_API int + printf (const std::string& fmt, const octave_value_list& args, + const std::string& who /* = "printf" */); - OCTINTERP_API int - puts (const std::string& s, const std::string& who /* = "puts" */); + OCTINTERP_API int + puts (const std::string& s, const std::string& who /* = "puts" */); - // We can always do this in terms of seek(), so the derived class - // only has to provide that. + // We can always do this in terms of seek(), so the derived class + // only has to provide that. - OCTINTERP_API void - invalid_operation (const std::string& who, const char *rw); - }; + OCTINTERP_API void + invalid_operation (const std::string& who, const char *rw); +}; - class - OCTINTERP_API - stream - { - public: +class +OCTINTERP_API +stream +{ +public: - // BS must be allocated with new or nullptr. - stream (base_stream *bs = nullptr) : m_rep (bs) { } + // BS must be allocated with new or nullptr. + stream (base_stream *bs = nullptr) : m_rep (bs) { } - stream (const stream&) = default; + stream (const stream&) = default; - stream& operator = (const stream&) = default; + stream& operator = (const stream&) = default; - ~stream (void) = default; + ~stream (void) = default; - OCTINTERP_API int flush (void); + OCTINTERP_API int flush (void); - OCTINTERP_API std::string - getl (octave_idx_type max_len, bool& err, - const std::string& who /* = "getl" */); + OCTINTERP_API std::string + getl (octave_idx_type max_len, bool& err, + const std::string& who /* = "getl" */); - OCTINTERP_API std::string - getl (const octave_value& max_len, bool& err, - const std::string& who /* = "getl" */); + OCTINTERP_API std::string + getl (const octave_value& max_len, bool& err, + const std::string& who /* = "getl" */); - OCTINTERP_API std::string - gets (octave_idx_type max_len, bool& err, - const std::string& who /* = "gets" */); + OCTINTERP_API std::string + gets (octave_idx_type max_len, bool& err, + const std::string& who /* = "gets" */); - OCTINTERP_API std::string - gets (const octave_value& max_len, bool& err, - const std::string& who /* = "gets" */); + OCTINTERP_API std::string + gets (const octave_value& max_len, bool& err, + const std::string& who /* = "gets" */); - OCTINTERP_API off_t - skipl (off_t count, bool& err, const std::string& who /* = "skipl" */); + OCTINTERP_API off_t + skipl (off_t count, bool& err, const std::string& who /* = "skipl" */); - OCTINTERP_API off_t - skipl (const octave_value& count, bool& err, - const std::string& who /* = "skipl" */); + OCTINTERP_API off_t + skipl (const octave_value& count, bool& err, + const std::string& who /* = "skipl" */); - OCTINTERP_API int seek (off_t offset, int origin); + OCTINTERP_API int seek (off_t offset, int origin); - OCTINTERP_API int - seek (const octave_value& offset, const octave_value& origin); + OCTINTERP_API int + seek (const octave_value& offset, const octave_value& origin); - OCTINTERP_API off_t tell (void); + OCTINTERP_API off_t tell (void); - OCTINTERP_API int rewind (void); + OCTINTERP_API int rewind (void); - OCTINTERP_API bool is_open (void) const; + OCTINTERP_API bool is_open (void) const; - OCTINTERP_API void close (void); + OCTINTERP_API void close (void); - OCTINTERP_API octave_value - read (const Array& size, octave_idx_type block_size, - oct_data_conv::data_type input_type, - oct_data_conv::data_type output_type, - octave_idx_type skip, mach_info::float_format flt_fmt, - octave_idx_type& count); + OCTINTERP_API octave_value + read (const Array& size, octave_idx_type block_size, + oct_data_conv::data_type input_type, + oct_data_conv::data_type output_type, + octave_idx_type skip, mach_info::float_format flt_fmt, + octave_idx_type& count); - OCTINTERP_API octave_idx_type - write (const octave_value& data, octave_idx_type block_size, - oct_data_conv::data_type output_type, - octave_idx_type skip, mach_info::float_format flt_fmt); + OCTINTERP_API octave_idx_type + write (const octave_value& data, octave_idx_type block_size, + oct_data_conv::data_type output_type, + octave_idx_type skip, mach_info::float_format flt_fmt); - OCTINTERP_API bool write_bytes (const void *data, std::size_t n_elts); + OCTINTERP_API bool write_bytes (const void *data, std::size_t n_elts); - OCTINTERP_API bool skip_bytes (std::size_t n_elts); + OCTINTERP_API bool skip_bytes (std::size_t n_elts); - template - OCTINTERP_API octave_idx_type - write (const Array& data, octave_idx_type block_size, - oct_data_conv::data_type output_type, - octave_idx_type skip, mach_info::float_format flt_fmt); + template + OCTINTERP_API octave_idx_type + write (const Array& data, octave_idx_type block_size, + oct_data_conv::data_type output_type, + octave_idx_type skip, mach_info::float_format flt_fmt); - OCTINTERP_API octave_value - scanf (const std::string& fmt, const Array& size, - octave_idx_type& count, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value + scanf (const std::string& fmt, const Array& size, + octave_idx_type& count, const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value - scanf (const octave_value& fmt, const Array& size, - octave_idx_type& count, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value + scanf (const octave_value& fmt, const Array& size, + octave_idx_type& count, const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value_list - oscanf (const std::string& fmt, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value_list + oscanf (const std::string& fmt, const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value_list - oscanf (const octave_value& fmt, const std::string& who /* = "scanf" */); + OCTINTERP_API octave_value_list + oscanf (const octave_value& fmt, const std::string& who /* = "scanf" */); - OCTINTERP_API octave_value - textscan (const std::string& fmt, octave_idx_type ntimes, - const octave_value_list& options, - const std::string& who, octave_idx_type& count); + OCTINTERP_API octave_value + textscan (const std::string& fmt, octave_idx_type ntimes, + const octave_value_list& options, + const std::string& who, octave_idx_type& count); - OCTINTERP_API int - printf (const std::string& fmt, const octave_value_list& args, - const std::string& who /* = "printf" */); + OCTINTERP_API int + printf (const std::string& fmt, const octave_value_list& args, + const std::string& who /* = "printf" */); - OCTINTERP_API int - printf (const octave_value& fmt, const octave_value_list& args, - const std::string& who /* = "printf" */); + OCTINTERP_API int + printf (const octave_value& fmt, const octave_value_list& args, + const std::string& who /* = "printf" */); - OCTINTERP_API int - puts (const std::string& s, const std::string& who /* = "puts" */); - OCTINTERP_API int - puts (const octave_value& s, const std::string& who /* = "puts" */); + OCTINTERP_API int + puts (const std::string& s, const std::string& who /* = "puts" */); + OCTINTERP_API int + puts (const octave_value& s, const std::string& who /* = "puts" */); - OCTINTERP_API bool eof (void) const; + OCTINTERP_API bool eof (void) const; - OCTINTERP_API std::string error (bool clear, int& err_num); + OCTINTERP_API std::string error (bool clear, int& err_num); - std::string error (bool clear = false) - { - int err_num; - return error (clear, err_num); - } + std::string error (bool clear = false) + { + int err_num; + return error (clear, err_num); + } - // Set the error message and state. + // Set the error message and state. - void error (const std::string& msg) - { - if (m_rep) - m_rep->error (msg); - } + void error (const std::string& msg) + { + if (m_rep) + m_rep->error (msg); + } - void error (const char *msg) { error (std::string (msg)); } + void error (const char *msg) { error (std::string (msg)); } - int file_number (void) { return m_rep ? m_rep->file_number () : -1; } + int file_number (void) { return m_rep ? m_rep->file_number () : -1; } - bool is_valid (void) const { return bool (m_rep); } + bool is_valid (void) const { return bool (m_rep); } - bool ok (void) const { return m_rep && m_rep->ok (); } + bool ok (void) const { return m_rep && m_rep->ok (); } - operator bool () const { return ok (); } + operator bool () const { return ok (); } - OCTINTERP_API std::string name (void) const; + OCTINTERP_API std::string name (void) const; - OCTINTERP_API int mode (void) const; + OCTINTERP_API int mode (void) const; - OCTINTERP_API mach_info::float_format float_format (void) const; + OCTINTERP_API mach_info::float_format float_format (void) const; - OCTINTERP_API static std::string mode_as_string (int mode); + OCTINTERP_API static std::string mode_as_string (int mode); - std::string encoding (void) - { - return m_rep ? m_rep->encoding () : std::string (); - } + std::string encoding (void) + { + return m_rep ? m_rep->encoding () : std::string (); + } - std::istream * input_stream (void) - { - return m_rep ? m_rep->input_stream () : nullptr; - } + std::istream * input_stream (void) + { + return m_rep ? m_rep->input_stream () : nullptr; + } - std::ostream * output_stream (void) - { - return (m_rep ? m_rep->preferred_output_stream () : nullptr); - } + std::ostream * output_stream (void) + { + return (m_rep ? m_rep->preferred_output_stream () : nullptr); + } - void clearerr (void) { if (m_rep) m_rep->clearerr (); } + void clearerr (void) { if (m_rep) m_rep->clearerr (); } - private: +private: - // The actual representation of this stream. - std::shared_ptr m_rep; + // The actual representation of this stream. + std::shared_ptr m_rep; - bool stream_ok (bool clear = true) const - { - bool retval = true; + bool stream_ok (bool clear = true) const + { + bool retval = true; - if (m_rep) - { - if (clear) - m_rep->clear (); - } - else - retval = false; + if (m_rep) + { + if (clear) + m_rep->clear (); + } + else + retval = false; - return retval; - } + return retval; + } - void invalid_operation (const std::string& who, const char *rw) - { - if (m_rep) - m_rep->invalid_operation (who, rw); - } + void invalid_operation (const std::string& who, const char *rw) + { + if (m_rep) + m_rep->invalid_operation (who, rw); + } - OCTINTERP_API octave_value - finalize_read (std::list& input_buf_list, - octave_idx_type input_buf_elts, - octave_idx_type elts_read, - octave_idx_type nr, octave_idx_type nc, - oct_data_conv::data_type input_type, - oct_data_conv::data_type output_type, - mach_info::float_format ffmt); - }; + OCTINTERP_API octave_value + finalize_read (std::list& input_buf_list, + octave_idx_type input_buf_elts, + octave_idx_type elts_read, + octave_idx_type nr, octave_idx_type nc, + oct_data_conv::data_type input_type, + oct_data_conv::data_type output_type, + mach_info::float_format ffmt); +}; - class - OCTINTERP_API - stream_list - { - public: +class +OCTINTERP_API +stream_list +{ +public: - OCTINTERP_API stream_list (interpreter& interp); + OCTINTERP_API stream_list (interpreter& interp); - stream_list (const stream_list&) = delete; - stream_list& operator = (const stream_list&) = delete; + stream_list (const stream_list&) = delete; + stream_list& operator = (const stream_list&) = delete; - OCTINTERP_API ~stream_list (void); + OCTINTERP_API ~stream_list (void); - OCTINTERP_API int insert (stream& os); + OCTINTERP_API int insert (stream& os); - OCTINTERP_API stream lookup (int fid, const std::string& who = "") const; - OCTINTERP_API stream - lookup (const octave_value& fid, const std::string& who = "") const; + OCTINTERP_API stream lookup (int fid, const std::string& who = "") const; + OCTINTERP_API stream + lookup (const octave_value& fid, const std::string& who = "") const; - OCTINTERP_API int remove (int fid, const std::string& who = ""); - OCTINTERP_API int remove (const octave_value& fid, - const std::string& who = ""); + OCTINTERP_API int remove (int fid, const std::string& who = ""); + OCTINTERP_API int remove (const octave_value& fid, + const std::string& who = ""); - OCTINTERP_API void clear (bool flush = true); + OCTINTERP_API void clear (bool flush = true); - OCTINTERP_API string_vector get_info (int fid) const; - OCTINTERP_API string_vector get_info (const octave_value& fid) const; + OCTINTERP_API string_vector get_info (int fid) const; + OCTINTERP_API string_vector get_info (const octave_value& fid) const; - OCTINTERP_API std::string list_open_files (void) const; + OCTINTERP_API std::string list_open_files (void) const; - OCTINTERP_API octave_value open_file_numbers (void) const; + OCTINTERP_API octave_value open_file_numbers (void) const; - OCTINTERP_API int get_file_number (const octave_value& fid) const; + OCTINTERP_API int get_file_number (const octave_value& fid) const; - OCTINTERP_API octave_value stdin_file (void) const; - OCTINTERP_API octave_value stdout_file (void) const; - OCTINTERP_API octave_value stderr_file (void) const; + OCTINTERP_API octave_value stdin_file (void) const; + OCTINTERP_API octave_value stdout_file (void) const; + OCTINTERP_API octave_value stderr_file (void) const; - private: +private: - typedef std::map ostrl_map; + typedef std::map ostrl_map; - ostrl_map m_list; + ostrl_map m_list; - mutable ostrl_map::const_iterator m_lookup_cache; + mutable ostrl_map::const_iterator m_lookup_cache; - int m_stdin_file; - int m_stdout_file; - int m_stderr_file; - }; + int m_stdin_file; + int m_stdout_file; + int m_stderr_file; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/oct-strstrm.h --- a/libinterp/corefcn/oct-strstrm.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/oct-strstrm.h Thu Dec 01 20:05:44 2022 -0800 @@ -42,7 +42,7 @@ base_strstream (std::ios::openmode m = std::ios::out, mach_info::float_format ff - = mach_info::native_float_format (), + = mach_info::native_float_format (), const std::string& encoding = "utf-8") : base_stream (m, ff, encoding) { } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/octave-default-image.h --- a/libinterp/corefcn/octave-default-image.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/octave-default-image.h Thu Dec 01 20:05:44 2022 -0800 @@ -30,234 +30,234 @@ static char default_im_data[] = { - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,40,47,50,50,46,30,26,26,38,50,47,26,26,26,50, - 46,26,50,46,26,26,26,50,46,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,43,55,54,50,51,55, - 51,26,26,40,55,55,41,26,26,55,50,26,55,50,26,26,26,55, - 50,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,30,54,52,30,26,26,46,55,43,26,40,55,55,52,30, - 26,55,50,26,55,50,26,26,26,55,50,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,43,55,44,26,26, - 26,26,26,26,26,40,55,47,55,46,26,55,50,26,55,50,26,26, - 26,55,50,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,46,55,40,26,26,50,50,50,43,26,40,55,46, - 46,54,34,55,50,26,55,50,26,26,26,55,50,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,44,55,43, - 26,26,50,50,55,46,26,40,55,46,30,52,48,55,50,26,55,50, - 26,26,26,55,50,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,38,55,50,26,26,26,40,55,46,26,40, - 55,46,26,43,55,55,50,26,55,50,26,26,26,55,50,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 48,55,48,40,43,54,55,46,26,40,55,46,26,26,50,55,50,26, - 52,55,43,40,47,55,46,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,30,48,55,55,55,47,48,46, - 26,40,55,46,26,26,38,55,50,26,38,52,55,55,55,50,30,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,34,40,38,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,38,40,34,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,62,62,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 59,62,62,59,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,59,55,59,59,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,59,55,55,53,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,53,52,55,55,52,52,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,53,48,55,48,52,52,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,45,48,55,48,52, - 53,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,44,48,48,48,52,45,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,44,44,48,44, - 48,44,45,52,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,45,44,41,44,48,41,45,44,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,45,44, - 37,44,37,41,45,44,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,37,41,37,44,37,41,36,36,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,44, - 36,32,37,44,37,41,36,36,41,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,36,36,32,37,37,37,32,36,37, - 41,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,20, - 20,36,36,32,37,37,37,32,36,37,32,18,20,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,20,18,18,16,17,17,27,36,32,37,31,37,32, - 36,37,32,17,17,18,18,18,20,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,20,18,18,18,16,16, - 16,15,15,27,26,28,31,31,28,32,36,27,36,15,16,17,16,17, - 17,18,18,20,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,18,20,17,17,16,16,16,16,15,15,32,27,24,28,24,31, - 28,28,24,27,26,24,16,15,16,17,16,16,18,18,20,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,20,20,18,18,17,17,16, - 16,14,14,15,24,27,24,28,24,31,28,28,24,27,26,28,12,14, - 15,15,16,16,16,16,18,18,20,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,20,18,18,18,17,16,15,14,14,14,14,12,26,26,24,22, - 24,24,28,22,24,26,26,22,12,12,12,12,14,14,16,16,16,18, - 18,20,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,20,20,18,18,17,16,12, - 15,12,10,10,10,12,26,18,24,22,24,24,24,22,24,26,26,22, - 10,10,12,12,10,14,14,15,17,18,18,20,20,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,17,20,20,20,17,16,15,14,12,12,10,10,10,18,18,18, - 16,17,24,24,24,22,16,18,18,24,18,6,9,10,10,14,14,15, - 16,18,20,18,20,18,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,16,18,20,20,18,17,16, - 15,10,10,7,6,6,6,15,18,18,15,17,18,24,17,22,16,18, - 18,24,24,6,7,6,10,10,10,12,16,17,18,20,20,18,16,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,12,15,17,18,18,20,18,16,15,10,10,7,6,6,6,16, - 18,16,15,17,18,18,17,22,16,18,18,16,17,5,4,6,6,10, - 7,14,15,17,20,20,20,18,17,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,9,10,16,17,18,18,18, - 18,15,10,10,6,5,4,4,4,10,12,16,15,17,12,18,17,12, - 15,18,18,18,12,4,4,4,6,6,9,12,15,18,20,18,18,17, - 16,12,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,9,9,12,15,16,17,18,18,20,15,10,10,4,5,4,4, - 12,12,12,10,15,17,12,18,17,12,15,10,12,18,15,3,1,4, - 4,4,5,10,16,20,18,18,17,17,16,12,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,7,7,9,9,12,15,26,26, - 26,18,18,18,20,5,4,4,3,1,6,12,12,10,12,7,12,12, - 12,12,9,10,12,12,9,12,1,1,4,4,6,20,18,18,18,17, - 16,16,15,12,10,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,18,18,18,4,1, - 1,1,9,12,12,9,12,7,9,12,12,12,9,10,12,12,9,12, - 1,1,3,4,18,18,18,18,17,16,16,16,14,10,9,9,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,18,18,18,18,18,4,10,5,5,9,6,7, - 9,7,12,6,9,10,5,5,10,6,5,18,18,18,18,18,26,26, - 26,26,16,15,12,10,9,9,9,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,14, - 17,17,16,18,18,20,18,20,6,7,9,9,7,6,9,5,20,18, - 18,18,18,18,18,15,14,26,26,26,26,26,26,26,12,10,9,9, - 7,7,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,10,16,16,16,16,17,18,17, - 18,17,17,18,18,17,18,17,17,17,17,17,14,14,14,12,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,1,10,15,16,15,16,15,15,16,15,16,15,16,16,16,15, - 16,16,17,14,14,10,12,1,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,1,10,15,15,14, - 15,15,15,15,15,15,15,14,15,15,15,12,12,10,10,10,1,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,6,12,12,12,12,15,12,12,12,12,12,12, - 12,15,10,9,7,6,6,1,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 12,12,12,12,12,12,12,12,12,10,12,7,10,7,6,1,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,10,10,12,10,10,10,10, - 12,10,1,1,1,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,10,9,9,9,9,9,9,10,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,9,9,9,9, - 9,9,9,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,7,7,7,7,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,40,48,50,50,44,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,43,55,54,50,52,55, - 48,26,26,26,26,26,26,26,26,26,55,50,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,30,54,52,30,26,26,47,55,43,26,30,44,46,43,26, - 26,38,55,51,34,26,34,46,46,43,26,43,46,26,26,40,46,34, - 26,30,44,46,40,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,43,55,44,26,26, - 26,34,55,48,30,51,55,50,55,48,26,46,55,54,43,34,55,54, - 51,55,46,46,55,38,26,47,55,30,30,54,54,51,55,46,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,46,55,40,26,26,26,26,55,50,43,55,43,26, - 46,55,34,26,55,50,26,43,50,34,26,51,50,34,55,46,26,52, - 48,26,46,55,34,26,48,55,30,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,46,55,41, - 26,26,26,26,55,50,46,55,30,26,26,26,26,26,55,50,26,26, - 44,50,54,55,50,26,51,51,38,55,43,26,50,55,50,50,52,55, - 40,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,38,55,48,26,26,26,43,55,46,46,55, - 34,26,34,40,30,26,55,50,26,46,55,44,38,50,50,26,44,55, - 46,55,30,26,50,55,40,40,40,40,30,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 50,55,47,40,43,54,54,34,41,55,47,30,48,55,30,26,55,50, - 26,48,55,38,40,55,50,26,34,55,55,48,26,26,44,55,41,26, - 46,48,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,30,50,55,55,55,52,38,26, - 26,47,55,55,55,43,26,26,52,55,46,41,55,55,52,52,54,30, - 26,50,55,43,26,26,30,50,55,55,54,43,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,34,40,40,26,26,26,26,26,38,40,34,26,26,26, - 30,40,34,26,34,40,26,26,26,26,26,26,26,26,26,26,26,26, - 38,40,30,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26, - 26,26,26,26,26,26,26,26,26,26 + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 40, 47, 50, 50, 46, 30, 26, 26, 38, 50, 47, 26, 26, 26, 50, + 46, 26, 50, 46, 26, 26, 26, 50, 46, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 54, 50, 51, 55, + 51, 26, 26, 40, 55, 55, 41, 26, 26, 55, 50, 26, 55, 50, 26, 26, 26, 55, + 50, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 30, 54, 52, 30, 26, 26, 46, 55, 43, 26, 40, 55, 55, 52, 30, + 26, 55, 50, 26, 55, 50, 26, 26, 26, 55, 50, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 44, 26, 26, + 26, 26, 26, 26, 26, 40, 55, 47, 55, 46, 26, 55, 50, 26, 55, 50, 26, 26, + 26, 55, 50, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 46, 55, 40, 26, 26, 50, 50, 50, 43, 26, 40, 55, 46, + 46, 54, 34, 55, 50, 26, 55, 50, 26, 26, 26, 55, 50, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 44, 55, 43, + 26, 26, 50, 50, 55, 46, 26, 40, 55, 46, 30, 52, 48, 55, 50, 26, 55, 50, + 26, 26, 26, 55, 50, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 38, 55, 50, 26, 26, 26, 40, 55, 46, 26, 40, + 55, 46, 26, 43, 55, 55, 50, 26, 55, 50, 26, 26, 26, 55, 50, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 48, 55, 48, 40, 43, 54, 55, 46, 26, 40, 55, 46, 26, 26, 50, 55, 50, 26, + 52, 55, 43, 40, 47, 55, 46, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 30, 48, 55, 55, 55, 47, 48, 46, + 26, 40, 55, 46, 26, 26, 38, 55, 50, 26, 38, 52, 55, 55, 55, 50, 30, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 34, 40, 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 38, 40, 34, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 62, 62, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 59, 62, 62, 59, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 59, 55, 59, 59, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 59, 55, 55, 53, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 53, 52, 55, 55, 52, 52, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 53, 48, 55, 48, 52, 52, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 45, 48, 55, 48, 52, + 53, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 44, 48, 48, 48, 52, 45, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 44, 44, 48, 44, + 48, 44, 45, 52, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 45, 44, 41, 44, 48, 41, 45, 44, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 45, 44, + 37, 44, 37, 41, 45, 44, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 37, 41, 37, 44, 37, 41, 36, 36, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 44, + 36, 32, 37, 44, 37, 41, 36, 36, 41, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 36, 36, 32, 37, 37, 37, 32, 36, 37, + 41, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, + 20, 36, 36, 32, 37, 37, 37, 32, 36, 37, 32, 18, 20, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 20, 18, 18, 16, 17, 17, 27, 36, 32, 37, 31, 37, 32, + 36, 37, 32, 17, 17, 18, 18, 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, 18, 18, 18, 16, 16, + 16, 15, 15, 27, 26, 28, 31, 31, 28, 32, 36, 27, 36, 15, 16, 17, 16, 17, + 17, 18, 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 18, 20, 17, 17, 16, 16, 16, 16, 15, 15, 32, 27, 24, 28, 24, 31, + 28, 28, 24, 27, 26, 24, 16, 15, 16, 17, 16, 16, 18, 18, 20, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, 20, 18, 18, 17, 17, 16, + 16, 14, 14, 15, 24, 27, 24, 28, 24, 31, 28, 28, 24, 27, 26, 28, 12, 14, + 15, 15, 16, 16, 16, 16, 18, 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 20, 18, 18, 18, 17, 16, 15, 14, 14, 14, 14, 12, 26, 26, 24, 22, + 24, 24, 28, 22, 24, 26, 26, 22, 12, 12, 12, 12, 14, 14, 16, 16, 16, 18, + 18, 20, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 20, 20, 18, 18, 17, 16, 12, + 15, 12, 10, 10, 10, 12, 26, 18, 24, 22, 24, 24, 24, 22, 24, 26, 26, 22, + 10, 10, 12, 12, 10, 14, 14, 15, 17, 18, 18, 20, 20, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 17, 20, 20, 20, 17, 16, 15, 14, 12, 12, 10, 10, 10, 18, 18, 18, + 16, 17, 24, 24, 24, 22, 16, 18, 18, 24, 18, 6, 9, 10, 10, 14, 14, 15, + 16, 18, 20, 18, 20, 18, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 16, 18, 20, 20, 18, 17, 16, + 15, 10, 10, 7, 6, 6, 6, 15, 18, 18, 15, 17, 18, 24, 17, 22, 16, 18, + 18, 24, 24, 6, 7, 6, 10, 10, 10, 12, 16, 17, 18, 20, 20, 18, 16, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 12, 15, 17, 18, 18, 20, 18, 16, 15, 10, 10, 7, 6, 6, 6, 16, + 18, 16, 15, 17, 18, 18, 17, 22, 16, 18, 18, 16, 17, 5, 4, 6, 6, 10, + 7, 14, 15, 17, 20, 20, 20, 18, 17, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 9, 10, 16, 17, 18, 18, 18, + 18, 15, 10, 10, 6, 5, 4, 4, 4, 10, 12, 16, 15, 17, 12, 18, 17, 12, + 15, 18, 18, 18, 12, 4, 4, 4, 6, 6, 9, 12, 15, 18, 20, 18, 18, 17, + 16, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 9, 9, 12, 15, 16, 17, 18, 18, 20, 15, 10, 10, 4, 5, 4, 4, + 12, 12, 12, 10, 15, 17, 12, 18, 17, 12, 15, 10, 12, 18, 15, 3, 1, 4, + 4, 4, 5, 10, 16, 20, 18, 18, 17, 17, 16, 12, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 7, 7, 9, 9, 12, 15, 26, 26, + 26, 18, 18, 18, 20, 5, 4, 4, 3, 1, 6, 12, 12, 10, 12, 7, 12, 12, + 12, 12, 9, 10, 12, 12, 9, 12, 1, 1, 4, 4, 6, 20, 18, 18, 18, 17, + 16, 16, 15, 12, 10, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 18, 18, 18, 4, 1, + 1, 1, 9, 12, 12, 9, 12, 7, 9, 12, 12, 12, 9, 10, 12, 12, 9, 12, + 1, 1, 3, 4, 18, 18, 18, 18, 17, 16, 16, 16, 14, 10, 9, 9, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 18, 18, 18, 18, 18, 4, 10, 5, 5, 9, 6, 7, + 9, 7, 12, 6, 9, 10, 5, 5, 10, 6, 5, 18, 18, 18, 18, 18, 26, 26, + 26, 26, 16, 15, 12, 10, 9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 14, + 17, 17, 16, 18, 18, 20, 18, 20, 6, 7, 9, 9, 7, 6, 9, 5, 20, 18, + 18, 18, 18, 18, 18, 15, 14, 26, 26, 26, 26, 26, 26, 26, 12, 10, 9, 9, + 7, 7, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 10, 16, 16, 16, 16, 17, 18, 17, + 18, 17, 17, 18, 18, 17, 18, 17, 17, 17, 17, 17, 14, 14, 14, 12, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 1, 10, 15, 16, 15, 16, 15, 15, 16, 15, 16, 15, 16, 16, 16, 15, + 16, 16, 17, 14, 14, 10, 12, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 1, 10, 15, 15, 14, + 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 12, 12, 10, 10, 10, 1, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 6, 12, 12, 12, 12, 15, 12, 12, 12, 12, 12, 12, + 12, 15, 10, 9, 7, 6, 6, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 7, 10, 7, 6, 1, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 10, 10, 12, 10, 10, 10, 10, + 12, 10, 1, 1, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 10, 9, 9, 9, 9, 9, 9, 10, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 9, 9, 9, 9, + 9, 9, 9, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 7, 7, 7, 7, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 40, 48, 50, 50, 44, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 54, 50, 52, 55, + 48, 26, 26, 26, 26, 26, 26, 26, 26, 26, 55, 50, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 30, 54, 52, 30, 26, 26, 47, 55, 43, 26, 30, 44, 46, 43, 26, + 26, 38, 55, 51, 34, 26, 34, 46, 46, 43, 26, 43, 46, 26, 26, 40, 46, 34, + 26, 30, 44, 46, 40, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 43, 55, 44, 26, 26, + 26, 34, 55, 48, 30, 51, 55, 50, 55, 48, 26, 46, 55, 54, 43, 34, 55, 54, + 51, 55, 46, 46, 55, 38, 26, 47, 55, 30, 30, 54, 54, 51, 55, 46, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 46, 55, 40, 26, 26, 26, 26, 55, 50, 43, 55, 43, 26, + 46, 55, 34, 26, 55, 50, 26, 43, 50, 34, 26, 51, 50, 34, 55, 46, 26, 52, + 48, 26, 46, 55, 34, 26, 48, 55, 30, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 46, 55, 41, + 26, 26, 26, 26, 55, 50, 46, 55, 30, 26, 26, 26, 26, 26, 55, 50, 26, 26, + 44, 50, 54, 55, 50, 26, 51, 51, 38, 55, 43, 26, 50, 55, 50, 50, 52, 55, + 40, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 38, 55, 48, 26, 26, 26, 43, 55, 46, 46, 55, + 34, 26, 34, 40, 30, 26, 55, 50, 26, 46, 55, 44, 38, 50, 50, 26, 44, 55, + 46, 55, 30, 26, 50, 55, 40, 40, 40, 40, 30, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 50, 55, 47, 40, 43, 54, 54, 34, 41, 55, 47, 30, 48, 55, 30, 26, 55, 50, + 26, 48, 55, 38, 40, 55, 50, 26, 34, 55, 55, 48, 26, 26, 44, 55, 41, 26, + 46, 48, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 30, 50, 55, 55, 55, 52, 38, 26, + 26, 47, 55, 55, 55, 43, 26, 26, 52, 55, 46, 41, 55, 55, 52, 52, 54, 30, + 26, 50, 55, 43, 26, 26, 30, 50, 55, 55, 54, 43, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 34, 40, 40, 26, 26, 26, 26, 26, 38, 40, 34, 26, 26, 26, + 30, 40, 34, 26, 34, 40, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 38, 40, 30, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }; #endif diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ordqz.cc --- a/libinterp/corefcn/ordqz.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ordqz.cc Thu Dec 01 20:05:44 2022 -0800 @@ -163,7 +163,7 @@ { std::string opts = args(4).string_value (); std::for_each (opts.begin (), opts.end (), - [] (char & c) { c = std::tolower (c); }); + [] (char& c) { c = std::tolower (c); }); if (opts == "lhp" || opts == "-") select_mode = LHP; else if (opts == "rhp" || opts == "+") @@ -395,8 +395,8 @@ F77_INT ihi = 2; F77_INT lwork = 4; F77_INT info = 0; - double * aa_vec = aa.fortran_vec (); - double * bb_vec = bb.fortran_vec (); + double *aa_vec = aa.fortran_vec (); + double *bb_vec = bb.fortran_vec (); F77_XFCN (dhgeqz, DHGEQZ, (F77_CONST_CHAR_ARG2 (&qz_job, 1), diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/ordschur.cc --- a/libinterp/corefcn/ordschur.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/ordschur.cc Thu Dec 01 20:05:44 2022 -0800 @@ -82,7 +82,8 @@ if (args.length () != 3) print_usage (); - const Array sel_arg = args(2).xoctave_idx_type_vector_value ("ordschur: SELECT must be an array of integers"); + const Array sel_arg = args( + 2).xoctave_idx_type_vector_value ("ordschur: SELECT must be an array of integers"); const octave_idx_type sel_n = sel_arg.numel (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/pager.cc --- a/libinterp/corefcn/pager.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/pager.cc Thu Dec 01 20:05:44 2022 -0800 @@ -54,454 +54,454 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static bool - pager_event_handler (pid_t pid, int status) - { - bool retval = false; +static bool +pager_event_handler (pid_t pid, int status) +{ + bool retval = false; - if (pid > 0) - { - if (sys::wifexited (status) || sys::wifsignaled (status)) - { - // Avoid warning() since that will put us back in the pager, - // which would be bad news. + if (pid > 0) + { + if (sys::wifexited (status) || sys::wifsignaled (status)) + { + // Avoid warning() since that will put us back in the pager, + // which would be bad news. - std::cerr << "warning: connection to external pager lost (pid = " - << pid << ')' << std::endl; - std::cerr << "warning: flushing pending output (please wait)" - << std::endl; + std::cerr << "warning: connection to external pager lost (pid = " + << pid << ')' << std::endl; + std::cerr << "warning: flushing pending output (please wait)" + << std::endl; - // Request removal of this PID from the list of child - // processes. + // Request removal of this PID from the list of child + // processes. - retval = true; - } - } + retval = true; + } + } - return retval; - } + return retval; +} - // Assume our terminal wraps long lines. +// Assume our terminal wraps long lines. - static bool - more_than_a_screenful (const char *s, int len) - { - if (s) - { - int available_rows = command_editor::terminal_rows () - 2; +static bool +more_than_a_screenful (const char *s, int len) +{ + if (s) + { + int available_rows = command_editor::terminal_rows () - 2; - int cols = command_editor::terminal_cols (); + int cols = command_editor::terminal_cols (); - int count = 0; + int count = 0; - int chars_this_line = 0; + int chars_this_line = 0; - for (int i = 0; i < len; i++) - { - if (*s++ == '\n') - { - count += chars_this_line / cols + 1; - chars_this_line = 0; - } - else - chars_this_line++; - } + for (int i = 0; i < len; i++) + { + if (*s++ == '\n') + { + count += chars_this_line / cols + 1; + chars_this_line = 0; + } + else + chars_this_line++; + } - if (count > available_rows) - return true; - } + if (count > available_rows) + return true; + } - return false; - } + return false; +} - static std::string default_pager (void) - { - std::string pager_binary = sys::env::getenv ("PAGER"); +static std::string default_pager (void) +{ + std::string pager_binary = sys::env::getenv ("PAGER"); - if (pager_binary.empty ()) - pager_binary = config::default_pager (); + if (pager_binary.empty ()) + pager_binary = config::default_pager (); - return pager_binary; - } + return pager_binary; +} - int - pager_buf::sync (void) - { - output_system& output_sys = __get_output_system__ (); +int +pager_buf::sync (void) +{ + output_system& output_sys = __get_output_system__ (); - char *buf = pbase (); + char *buf = pbase (); - int len = pptr () - buf; + int len = pptr () - buf; - if (output_sys.sync (buf, len)) - { - flush_current_contents_to_diary (); + if (output_sys.sync (buf, len)) + { + flush_current_contents_to_diary (); - seekoff (0, std::ios::beg); - } + seekoff (0, std::ios::beg); + } - return 0; - } + return 0; +} - void - pager_buf::flush_current_contents_to_diary (void) - { - char *buf = pbase () + m_diary_skip; +void +pager_buf::flush_current_contents_to_diary (void) +{ + char *buf = pbase () + m_diary_skip; - std::size_t len = pptr () - buf; + std::size_t len = pptr () - buf; - octave_diary.write (buf, len); + octave_diary.write (buf, len); - m_diary_skip = 0; - } + m_diary_skip = 0; +} - void - pager_buf::set_diary_skip (void) - { - m_diary_skip = pptr () - pbase (); - } +void +pager_buf::set_diary_skip (void) +{ + m_diary_skip = pptr () - pbase (); +} - int - diary_buf::sync (void) - { - output_system& output_sys = __get_output_system__ (); +int +diary_buf::sync (void) +{ + output_system& output_sys = __get_output_system__ (); - std::ofstream& external_diary_file = output_sys.external_diary_file (); + std::ofstream& external_diary_file = output_sys.external_diary_file (); - if (output_sys.write_to_diary_file () && external_diary_file) - { - char *buf = pbase (); + if (output_sys.write_to_diary_file () && external_diary_file) + { + char *buf = pbase (); - int len = pptr () - buf; + int len = pptr () - buf; - if (len > 0) - external_diary_file.write (buf, len); - } + if (len > 0) + external_diary_file.write (buf, len); + } - seekoff (0, std::ios::beg); + seekoff (0, std::ios::beg); - return 0; - } + return 0; +} - pager_stream::pager_stream (void) : std::ostream (nullptr), m_pb (nullptr) - { - m_pb = new pager_buf (); - rdbuf (m_pb); - setf (unitbuf); - } +pager_stream::pager_stream (void) : std::ostream (nullptr), m_pb (nullptr) +{ + m_pb = new pager_buf (); + rdbuf (m_pb); + setf (unitbuf); +} - pager_stream::~pager_stream (void) - { - flush (); - delete m_pb; - } +pager_stream::~pager_stream (void) +{ + flush (); + delete m_pb; +} - std::ostream& pager_stream::stream (void) - { - return *this; - } +std::ostream& pager_stream::stream (void) +{ + return *this; +} - void pager_stream::flush_current_contents_to_diary (void) - { - if (m_pb) - m_pb->flush_current_contents_to_diary (); - } +void pager_stream::flush_current_contents_to_diary (void) +{ + if (m_pb) + m_pb->flush_current_contents_to_diary (); +} - void pager_stream::set_diary_skip (void) - { - if (m_pb) - m_pb->set_diary_skip (); - } +void pager_stream::set_diary_skip (void) +{ + if (m_pb) + m_pb->set_diary_skip (); +} - // Reinitialize the pager buffer to avoid hanging on to large internal - // buffers when they might not be needed. This function should only be - // called when the pager is not in use. For example, just before - // getting command-line input. +// Reinitialize the pager buffer to avoid hanging on to large internal +// buffers when they might not be needed. This function should only be +// called when the pager is not in use. For example, just before +// getting command-line input. - void pager_stream::reset (void) - { - delete m_pb; - m_pb = new pager_buf (); - rdbuf (m_pb); - setf (unitbuf); - } +void pager_stream::reset (void) +{ + delete m_pb; + m_pb = new pager_buf (); + rdbuf (m_pb); + setf (unitbuf); +} - diary_stream::diary_stream (void) : std::ostream (nullptr), m_db (nullptr) - { - m_db = new diary_buf (); - rdbuf (m_db); - setf (unitbuf); - } +diary_stream::diary_stream (void) : std::ostream (nullptr), m_db (nullptr) +{ + m_db = new diary_buf (); + rdbuf (m_db); + setf (unitbuf); +} - diary_stream::~diary_stream (void) - { - flush (); - delete m_db; - } +diary_stream::~diary_stream (void) +{ + flush (); + delete m_db; +} - std::ostream& diary_stream::stream (void) - { - return *this; - } +std::ostream& diary_stream::stream (void) +{ + return *this; +} - // Reinitialize the diary buffer to avoid hanging on to large internal - // buffers when they might not be needed. This function should only be - // called when the pager is not in use. For example, just before - // getting command-line input. +// Reinitialize the diary buffer to avoid hanging on to large internal +// buffers when they might not be needed. This function should only be +// called when the pager is not in use. For example, just before +// getting command-line input. - void diary_stream::reset (void) - { - delete m_db; - m_db = new diary_buf (); - rdbuf (m_db); - setf (unitbuf); - } +void diary_stream::reset (void) +{ + delete m_db; + m_db = new diary_buf (); + rdbuf (m_db); + setf (unitbuf); +} - void flush_stdout (void) - { - output_system& output_sys = __get_output_system__ (); +void flush_stdout (void) +{ + output_system& output_sys = __get_output_system__ (); - output_sys.flush_stdout (); - } + output_sys.flush_stdout (); +} - output_system::output_system (interpreter& interp) - : m_interpreter (interp), m_pager_stream (), m_diary_stream (), - m_external_pager (nullptr), m_external_diary_file (), - m_diary_file_name ("diary"), m_PAGER (default_pager ()), - m_PAGER_FLAGS (), m_page_output_immediately (false), - m_page_screen_output (false), m_write_to_diary_file (false), - m_really_flush_to_pager (false), m_flushing_output_to_pager (false) - { } +output_system::output_system (interpreter& interp) + : m_interpreter (interp), m_pager_stream (), m_diary_stream (), + m_external_pager (nullptr), m_external_diary_file (), + m_diary_file_name ("diary"), m_PAGER (default_pager ()), + m_PAGER_FLAGS (), m_page_output_immediately (false), + m_page_screen_output (false), m_write_to_diary_file (false), + m_really_flush_to_pager (false), m_flushing_output_to_pager (false) +{ } - octave_value output_system::PAGER (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_PAGER, args, nargout, "PAGER", false); - } +octave_value output_system::PAGER (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_PAGER, args, nargout, "PAGER", false); +} - octave_value output_system::PAGER_FLAGS (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_PAGER_FLAGS, args, nargout, - "PAGER_FLAGS", false); - } +octave_value output_system::PAGER_FLAGS (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_PAGER_FLAGS, args, nargout, + "PAGER_FLAGS", false); +} - octave_value - output_system::page_output_immediately (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_page_output_immediately, args, nargout, - "page_output_immediately"); - } +octave_value +output_system::page_output_immediately (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_page_output_immediately, args, nargout, + "page_output_immediately"); +} - octave_value - output_system::page_screen_output (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_page_screen_output, args, nargout, - "page_screen_output"); - } +octave_value +output_system::page_screen_output (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_page_screen_output, args, nargout, + "page_screen_output"); +} - std::string output_system::pager_command (void) const - { - std::string cmd = m_PAGER; +std::string output_system::pager_command (void) const +{ + std::string cmd = m_PAGER; - if (! (cmd.empty () || m_PAGER_FLAGS.empty ())) - cmd += ' ' + m_PAGER_FLAGS; + if (! (cmd.empty () || m_PAGER_FLAGS.empty ())) + cmd += ' ' + m_PAGER_FLAGS; - return cmd; - } + return cmd; +} - void output_system::reset (void) - { - flush_stdout (); +void output_system::reset (void) +{ + flush_stdout (); - m_pager_stream.reset (); - m_diary_stream.reset (); - } + m_pager_stream.reset (); + m_diary_stream.reset (); +} - void output_system::flush_stdout (void) - { - if (! m_flushing_output_to_pager) - { - unwind_protect_var restore_var1 (m_really_flush_to_pager); - unwind_protect_var restore_var2 (m_flushing_output_to_pager); +void output_system::flush_stdout (void) +{ + if (! m_flushing_output_to_pager) + { + unwind_protect_var restore_var1 (m_really_flush_to_pager); + unwind_protect_var restore_var2 (m_flushing_output_to_pager); - m_really_flush_to_pager = true; - m_flushing_output_to_pager = true; + m_really_flush_to_pager = true; + m_flushing_output_to_pager = true; - std::ostream& pager_ostream = m_pager_stream.stream (); + std::ostream& pager_ostream = m_pager_stream.stream (); - pager_ostream.flush (); + pager_ostream.flush (); - clear_external_pager (); - } - } + clear_external_pager (); + } +} - void output_system::close_diary (void) - { - // Try to flush the current buffer to the diary now, so that things - // like - // - // function foo () - // diary on; - // ... - // diary off; - // endfunction - // - // will do the right thing. +void output_system::close_diary (void) +{ + // Try to flush the current buffer to the diary now, so that things + // like + // + // function foo () + // diary on; + // ... + // diary off; + // endfunction + // + // will do the right thing. - m_pager_stream.flush_current_contents_to_diary (); + m_pager_stream.flush_current_contents_to_diary (); - if (m_external_diary_file.is_open ()) - { - octave_diary.flush (); - m_external_diary_file.close (); - } - } + if (m_external_diary_file.is_open ()) + { + octave_diary.flush (); + m_external_diary_file.close (); + } +} - void output_system::open_diary (void) - { - close_diary (); +void output_system::open_diary (void) +{ + close_diary (); - // If there is pending output in the pager buf, it should not go - // into the diary file. + // If there is pending output in the pager buf, it should not go + // into the diary file. - m_pager_stream.set_diary_skip (); + m_pager_stream.set_diary_skip (); - m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app); + m_external_diary_file.open (m_diary_file_name.c_str (), std::ios::app); - if (! m_external_diary_file) - error ("diary: can't open diary file '%s'", m_diary_file_name.c_str ()); - } + if (! m_external_diary_file) + error ("diary: can't open diary file '%s'", m_diary_file_name.c_str ()); +} - bool output_system::sync (const char *buf, int len) - { - // FIXME: The following seems to be a bit of a mess. +bool output_system::sync (const char *buf, int len) +{ + // FIXME: The following seems to be a bit of a mess. - if (m_interpreter.server_mode () - || ! m_interpreter.interactive () - || application::forced_interactive () - || m_really_flush_to_pager - || (m_page_screen_output && m_page_output_immediately) - || ! m_page_screen_output) - { - bool bypass_pager = (m_interpreter.server_mode () - || ! m_interpreter.interactive () - || application::forced_interactive () - || ! m_page_screen_output - || (m_really_flush_to_pager - && m_page_screen_output - && ! m_page_output_immediately - && ! more_than_a_screenful (buf, len))); + if (m_interpreter.server_mode () + || ! m_interpreter.interactive () + || application::forced_interactive () + || m_really_flush_to_pager + || (m_page_screen_output && m_page_output_immediately) + || ! m_page_screen_output) + { + bool bypass_pager = (m_interpreter.server_mode () + || ! m_interpreter.interactive () + || application::forced_interactive () + || ! m_page_screen_output + || (m_really_flush_to_pager + && m_page_screen_output + && ! m_page_output_immediately + && ! more_than_a_screenful (buf, len))); - if (len > 0) - { - do_sync (buf, len, bypass_pager); + if (len > 0) + { + do_sync (buf, len, bypass_pager); - return true; - } - } + return true; + } + } - return false; - } + return false; +} - void output_system::clear_external_pager (void) - { - if (m_external_pager) - { - child_list& kids = m_interpreter.get_child_list (); +void output_system::clear_external_pager (void) +{ + if (m_external_pager) + { + child_list& kids = m_interpreter.get_child_list (); - kids.remove (m_external_pager->pid ()); + kids.remove (m_external_pager->pid ()); - delete m_external_pager; - m_external_pager = nullptr; - } - } + delete m_external_pager; + m_external_pager = nullptr; + } +} - void output_system::start_external_pager (void) - { - if (m_external_pager) - return; +void output_system::start_external_pager (void) +{ + if (m_external_pager) + return; - std::string pgr = pager_command (); + std::string pgr = pager_command (); - if (! pgr.empty ()) - { - m_external_pager = new oprocstream (pgr.c_str ()); + if (! pgr.empty ()) + { + m_external_pager = new oprocstream (pgr.c_str ()); - child_list& kids = m_interpreter.get_child_list (); + child_list& kids = m_interpreter.get_child_list (); - kids.insert (m_external_pager->pid (), - pager_event_handler); - } - } + kids.insert (m_external_pager->pid (), + pager_event_handler); + } +} - void output_system::do_sync (const char *msg, int len, bool bypass_pager) - { - if (msg && len > 0) - { - if (bypass_pager) - { - if (m_interpreter.server_mode ()) - { - event_manager& evmgr = m_interpreter.get_event_manager (); +void output_system::do_sync (const char *msg, int len, bool bypass_pager) +{ + if (msg && len > 0) + { + if (bypass_pager) + { + if (m_interpreter.server_mode ()) + { + event_manager& evmgr = m_interpreter.get_event_manager (); - evmgr.interpreter_output (std::string (msg, len)); - } - else - { - std::cout.write (msg, len); - std::cout.flush (); - } - } - else - { - start_external_pager (); + evmgr.interpreter_output (std::string (msg, len)); + } + else + { + std::cout.write (msg, len); + std::cout.flush (); + } + } + else + { + start_external_pager (); - if (m_external_pager) - { - if (m_external_pager->good ()) - { - m_external_pager->write (msg, len); + if (m_external_pager) + { + if (m_external_pager->good ()) + { + m_external_pager->write (msg, len); - m_external_pager->flush (); + m_external_pager->flush (); #if defined (EPIPE) - if (errno == EPIPE) - m_external_pager->setstate (std::ios::failbit); + if (errno == EPIPE) + m_external_pager->setstate (std::ios::failbit); #endif - } - else - { - // FIXME: something is not right with the - // pager. If it died then we should receive a - // signal for that. If there is some other problem, - // then what? - } - } - else - { - std::cout.write (msg, len); - std::cout.flush (); - } - } - } - } + } + else + { + // FIXME: something is not right with the + // pager. If it died then we should receive a + // signal for that. If there is some other problem, + // then what? + } + } + else + { + std::cout.write (msg, len); + std::cout.flush (); + } + } + } +} - std::ostream& __stdout__ (void) - { - output_system& output_sys = __get_output_system__ (); +std::ostream& __stdout__ (void) +{ + output_system& output_sys = __get_output_system__ (); - return output_sys.__stdout__ (); - } + return output_sys.__stdout__ (); +} - std::ostream& __diary__ (void) - { - output_system& output_sys = __get_output_system__ (); +std::ostream& __diary__ (void) +{ + output_system& output_sys = __get_output_system__ (); - return output_sys.__diary__ (); - } + return output_sys.__diary__ (); +} DEFMETHOD (diary, interp, args, nargout, doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/pager.h --- a/libinterp/corefcn/pager.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/pager.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,276 +38,276 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; - class oprocstream; +class interpreter; +class oprocstream; - class - OCTINTERP_API - pager_buf : public std::stringbuf - { - public: +class +OCTINTERP_API +pager_buf : public std::stringbuf +{ +public: - pager_buf (void) : std::stringbuf (), m_diary_skip (0) { } + pager_buf (void) : std::stringbuf (), m_diary_skip (0) { } - void flush_current_contents_to_diary (void); + void flush_current_contents_to_diary (void); - void set_diary_skip (void); + void set_diary_skip (void); - protected: +protected: - int sync (void); + int sync (void); - private: +private: - std::size_t m_diary_skip; - }; + std::size_t m_diary_skip; +}; - class - OCTINTERP_API - pager_stream : public std::ostream - { - public: +class +OCTINTERP_API +pager_stream : public std::ostream +{ +public: - pager_stream (void); + pager_stream (void); - // No copying! + // No copying! - pager_stream (const pager_stream&) = delete; + pager_stream (const pager_stream&) = delete; - pager_stream& operator = (const pager_stream&) = delete; + pager_stream& operator = (const pager_stream&) = delete; - ~pager_stream (void); + ~pager_stream (void); - void flush_current_contents_to_diary (void); + void flush_current_contents_to_diary (void); - void set_diary_skip (void); + void set_diary_skip (void); - std::ostream& stream (void); + std::ostream& stream (void); - void reset (void); + void reset (void); - private: +private: - pager_buf *m_pb; - }; + pager_buf *m_pb; +}; - class - OCTINTERP_API - diary_buf : public std::stringbuf - { - public: +class +OCTINTERP_API +diary_buf : public std::stringbuf +{ +public: - diary_buf (void) : std::stringbuf () { } + diary_buf (void) : std::stringbuf () { } - protected: +protected: - int sync (void); - }; + int sync (void); +}; - class - OCTINTERP_API - diary_stream : public std::ostream - { - public: +class +OCTINTERP_API +diary_stream : public std::ostream +{ +public: - diary_stream (void); + diary_stream (void); - // No copying! + // No copying! - diary_stream (const diary_stream&) = delete; + diary_stream (const diary_stream&) = delete; - diary_stream& operator = (const diary_stream&) = delete; + diary_stream& operator = (const diary_stream&) = delete; - ~diary_stream (void); + ~diary_stream (void); - std::ostream& stream (void); + std::ostream& stream (void); - void reset (void); + void reset (void); - private: +private: - diary_buf *m_db; - }; + diary_buf *m_db; +}; - extern OCTINTERP_API void flush_stdout (void); +extern OCTINTERP_API void flush_stdout (void); - class output_system - { - public: +class output_system +{ +public: - output_system (interpreter& interp); + output_system (interpreter& interp); - output_system (const output_system&) = delete; + output_system (const output_system&) = delete; - output_system& operator = (const output_system&) = delete; + output_system& operator = (const output_system&) = delete; - ~output_system (void) = default; + ~output_system (void) = default; - pager_stream& pager (void) { return m_pager_stream; } + pager_stream& pager (void) { return m_pager_stream; } - diary_stream& diary (void) { return m_diary_stream; } + diary_stream& diary (void) { return m_diary_stream; } - std::string diary_file_name (void) const { return m_diary_file_name; } + std::string diary_file_name (void) const { return m_diary_file_name; } - std::string diary_file_name (const std::string& nm) - { - std::string val = m_diary_file_name; - m_diary_file_name = nm.empty () ? "diary" : nm; - return val; - } + std::string diary_file_name (const std::string& nm) + { + std::string val = m_diary_file_name; + m_diary_file_name = nm.empty () ? "diary" : nm; + return val; + } - octave_value PAGER (const octave_value_list& args, int nargout); + octave_value PAGER (const octave_value_list& args, int nargout); - std::string PAGER (void) const { return m_PAGER; } + std::string PAGER (void) const { return m_PAGER; } - std::string PAGER (const std::string& s) - { - std::string val = m_PAGER; - m_PAGER = s; - return val; - } + std::string PAGER (const std::string& s) + { + std::string val = m_PAGER; + m_PAGER = s; + return val; + } - octave_value PAGER_FLAGS (const octave_value_list& args, int nargout); + octave_value PAGER_FLAGS (const octave_value_list& args, int nargout); - std::string PAGER_FLAGS (void) const { return m_PAGER_FLAGS; } + std::string PAGER_FLAGS (void) const { return m_PAGER_FLAGS; } - std::string PAGER_FLAGS (const std::string& s) - { - std::string val = m_PAGER_FLAGS; - m_PAGER_FLAGS = s; - return val; - } + std::string PAGER_FLAGS (const std::string& s) + { + std::string val = m_PAGER_FLAGS; + m_PAGER_FLAGS = s; + return val; + } - octave_value page_output_immediately (const octave_value_list& args, - int nargout); + octave_value page_output_immediately (const octave_value_list& args, + int nargout); - bool page_output_immediately (void) const - { - return m_page_output_immediately; - } + bool page_output_immediately (void) const + { + return m_page_output_immediately; + } - bool page_output_immediately (bool flag) - { - bool val = m_page_output_immediately; - m_page_output_immediately = flag; - return val; - } + bool page_output_immediately (bool flag) + { + bool val = m_page_output_immediately; + m_page_output_immediately = flag; + return val; + } - octave_value page_screen_output (const octave_value_list& args, - int nargout); + octave_value page_screen_output (const octave_value_list& args, + int nargout); - bool page_screen_output (void) const { return m_page_screen_output; } + bool page_screen_output (void) const { return m_page_screen_output; } - bool page_screen_output (bool flag) - { - bool val = m_page_screen_output; - m_page_screen_output = flag; - return val; - } + bool page_screen_output (bool flag) + { + bool val = m_page_screen_output; + m_page_screen_output = flag; + return val; + } - bool write_to_diary_file (void) const - { - return m_write_to_diary_file; - } + bool write_to_diary_file (void) const + { + return m_write_to_diary_file; + } - bool write_to_diary_file (bool flag) - { - bool val = m_write_to_diary_file; - m_write_to_diary_file = flag; - return val; - } + bool write_to_diary_file (bool flag) + { + bool val = m_write_to_diary_file; + m_write_to_diary_file = flag; + return val; + } - bool really_flush_to_pager (void) const - { - return m_really_flush_to_pager; - } + bool really_flush_to_pager (void) const + { + return m_really_flush_to_pager; + } - bool really_flush_to_pager (bool flag) - { - bool val = m_really_flush_to_pager; - m_really_flush_to_pager = flag; - return val; - } + bool really_flush_to_pager (bool flag) + { + bool val = m_really_flush_to_pager; + m_really_flush_to_pager = flag; + return val; + } - bool flushing_output_to_pager (void) const - { - return m_flushing_output_to_pager; - } + bool flushing_output_to_pager (void) const + { + return m_flushing_output_to_pager; + } - bool flushing_output_to_pager (bool flag) - { - bool val = m_flushing_output_to_pager; - m_flushing_output_to_pager = flag; - return val; - } + bool flushing_output_to_pager (bool flag) + { + bool val = m_flushing_output_to_pager; + m_flushing_output_to_pager = flag; + return val; + } - std::string pager_command (void) const; + std::string pager_command (void) const; - std::ofstream& external_diary_file (void) { return m_external_diary_file; } + std::ofstream& external_diary_file (void) { return m_external_diary_file; } - void reset (void); + void reset (void); - void flush_stdout (void); + void flush_stdout (void); - bool sync (const char *msg, int len); + bool sync (const char *msg, int len); - void clear_external_pager (void); + void clear_external_pager (void); - void open_diary (void); + void open_diary (void); - void close_diary (void); + void close_diary (void); - std::ostream& __stdout__ (void) { return m_pager_stream.stream (); } + std::ostream& __stdout__ (void) { return m_pager_stream.stream (); } - std::ostream& __diary__ (void) { return m_diary_stream.stream (); } + std::ostream& __diary__ (void) { return m_diary_stream.stream (); } - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - pager_stream m_pager_stream; + pager_stream m_pager_stream; - diary_stream m_diary_stream; + diary_stream m_diary_stream; - // Our actual connection to the external pager. - oprocstream *m_external_pager = nullptr; + // Our actual connection to the external pager. + oprocstream *m_external_pager = nullptr; - // The diary file. - std::ofstream m_external_diary_file; + // The diary file. + std::ofstream m_external_diary_file; - // The name of the current diary file. - std::string m_diary_file_name; + // The name of the current diary file. + std::string m_diary_file_name; - // The shell command to run as the pager. - std::string m_PAGER; + // The shell command to run as the pager. + std::string m_PAGER; - // The options to pass to the pager. - std::string m_PAGER_FLAGS; + // The options to pass to the pager. + std::string m_PAGER_FLAGS; - // TRUE means that if output is going to the pager, it is sent as soon - // as it is available. Otherwise, it is buffered and only sent to the - // pager when it is time to print another prompt. - bool m_page_output_immediately; + // TRUE means that if output is going to the pager, it is sent as soon + // as it is available. Otherwise, it is buffered and only sent to the + // pager when it is time to print another prompt. + bool m_page_output_immediately; - // TRUE means all output intended for the screen should be passed - // through the pager. - bool m_page_screen_output; + // TRUE means all output intended for the screen should be passed + // through the pager. + bool m_page_screen_output; - // TRUE means we write to the diary file. - bool m_write_to_diary_file; + // TRUE means we write to the diary file. + bool m_write_to_diary_file; - bool m_really_flush_to_pager; + bool m_really_flush_to_pager; - bool m_flushing_output_to_pager; + bool m_flushing_output_to_pager; - void start_external_pager (void); + void start_external_pager (void); - void do_sync (const char *msg, int len, bool bypass_pager); - }; + void do_sync (const char *msg, int len, bool bypass_pager); +}; - extern OCTINTERP_API std::ostream& __stdout__ (void); +extern OCTINTERP_API std::ostream& __stdout__ (void); - extern OCTINTERP_API std::ostream& __diary__ (void); +extern OCTINTERP_API std::ostream& __diary__ (void); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/pinv.cc --- a/libinterp/corefcn/pinv.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/pinv.cc Thu Dec 01 20:05:44 2022 -0800 @@ -169,7 +169,7 @@ %! a = reshape (rand*[1:16], 4, 4); # Rank 2 matrix %! b = pinv (a); %! tol = 4e-14; -%! hitol = 40*sqrt (eps); +%! hitol = 40* sqrt (eps); %! d = diag ([rand, rand, hitol, hitol]); %! u = rand (4); # Could be singular by freak accident %! x = inv (u)*d*u; diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/pow2.cc --- a/libinterp/corefcn/pow2.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/pow2.cc Thu Dec 01 20:05:44 2022 -0800 @@ -60,7 +60,7 @@ void map_2_xldexp_sparse (SparseMatrix& y, const SparseMatrix& f, - const SparseMatrix& e) + const SparseMatrix& e) { if (e.numel () == 1) { @@ -126,7 +126,7 @@ // The C++ standard does not define exp2 for complex arguments. // Therefore call `2.^x`. octave_value retval = octave::binary_op (octave_value::op_el_pow, - 2, args(0)); + 2, args(0)); // Preserve sparse datatype, but even for sparse input fill-up // is unavoidable `2^0 == 1` thus cast only. diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/pr-output.cc --- a/libinterp/corefcn/pr-output.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/pr-output.cc Thu Dec 01 20:05:44 2022 -0800 @@ -1162,7 +1162,7 @@ int x_min = (r_x_min > i_x_min ? r_x_min : i_x_min); return make_complex_matrix_format (x_max, x_min, r_x_max, r_x_min, - inf_or_nan, int_or_inf_or_nan); + inf_or_nan, int_or_inf_or_nan); } template <> @@ -2405,7 +2405,7 @@ default: print_nd_array - (os, nda, pr_as_read_syntax); + (os, nda, pr_as_read_syntax); break; } } @@ -2424,7 +2424,7 @@ default: print_nd_array - (os, nda, pr_as_read_syntax); + (os, nda, pr_as_read_syntax); break; } } @@ -2559,7 +2559,7 @@ while (col < num_elem) { octave_idx_type lim = (col + inc < num_elem ? col + inc - : num_elem); + : num_elem); pr_col_num_header (os, total_width, max_width, lim, col, extra_indent); @@ -2681,7 +2681,7 @@ default: print_nd_array (os, nda, - pr_as_read_syntax); + pr_as_read_syntax); break; } } @@ -3118,7 +3118,7 @@ { octave_quit (); os << " "; - os << typename octave_print_conv::print_conv_type (page(ii,jj)); + os << typename octave_print_conv::print_conv_type (page(ii, jj)); } os << "\n"; } @@ -3136,7 +3136,7 @@ for (octave_idx_type col = 0; col < n_cols; col += inc) { octave_idx_type lim = (col + inc < n_cols ? col + inc - : n_cols); + : n_cols); pr_col_num_header (os, total_width, max_width, lim, col, extra_indent); @@ -3368,7 +3368,7 @@ DEFMETHOD (fdisp, interp, args, , classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64 - doc: /* -*- texinfo -*- + doc: /* -*- texinfo -*- @deftypefn {} {} fdisp (@var{fid}, @var{x}) Display the value of @var{x} on the stream @var{fid}. diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/psi.cc --- a/libinterp/corefcn/psi.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/psi.cc Thu Dec 01 20:05:44 2022 -0800 @@ -105,15 +105,15 @@ { FLOAT_BRANCH(double, Complex, complex_, Complex) else FLOAT_BRANCH(single, FloatComplex, float_complex_, FloatComplex) - else - error ("psi: Z must be a floating point"); + else + error ("psi: Z must be a floating point"); } else { - FLOAT_BRANCH(double, , , double) + FLOAT_BRANCH(double,,, double) else FLOAT_BRANCH(single, Float, float_, float) - else - error ("psi: Z must be a floating point"); + else + error ("psi: Z must be a floating point"); } #undef FLOAT_BRANCH @@ -142,10 +142,10 @@ retval = psi_z; \ } - FLOAT_BRANCH(double, , , double) + FLOAT_BRANCH(double,,, double) else FLOAT_BRANCH(single, Float, float_, float) - else - error ("psi: Z must be a floating point for polygamma (K > 0)"); + else + error ("psi: Z must be a floating point for polygamma (K > 0)"); #undef FLOAT_BRANCH } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/qr.cc --- a/libinterp/corefcn/qr.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/qr.cc Thu Dec 01 20:05:44 2022 -0800 @@ -377,28 +377,28 @@ if (! args(1).issparse () && args(1).iscomplex ()) retval = ovl - (math::sparse_qr::solve - , ComplexMatrix> - (arg.sparse_complex_matrix_value (), - args(1).complex_matrix_value (), info)); + (math::sparse_qr::solve + , ComplexMatrix> + (arg.sparse_complex_matrix_value (), + args(1).complex_matrix_value (), info)); else if (args(1).issparse () && args(1).iscomplex ()) retval = ovl - (math::sparse_qr::solve - - (arg.sparse_complex_matrix_value (), - args(1).sparse_complex_matrix_value (), info)); + (math::sparse_qr::solve + + (arg.sparse_complex_matrix_value (), + args(1).sparse_complex_matrix_value (), info)); else if (! args(1).issparse () && ! args(1).iscomplex ()) retval = ovl - (math::sparse_qr::solve - , ComplexMatrix> - (arg.sparse_complex_matrix_value (), - args(1).matrix_value (), info)); + (math::sparse_qr::solve + , ComplexMatrix> + (arg.sparse_complex_matrix_value (), + args(1).matrix_value (), info)); else if (args(1).issparse () && ! args(1).iscomplex ()) retval = ovl - (math::sparse_qr::solve - - (arg.sparse_complex_matrix_value (), - args(1).sparse_matrix_value (), info)); + (math::sparse_qr::solve + + (arg.sparse_complex_matrix_value (), + args(1).sparse_matrix_value (), info)); else error ("qr: b is not valid"); } @@ -453,25 +453,25 @@ octave_idx_type info; if (args(1).issparse () && ! args(1).iscomplex ()) retval = ovl (math::sparse_qr::solve - - (arg.sparse_matrix_value (), - args (1).sparse_matrix_value (), info)); + + (arg.sparse_matrix_value (), + args (1).sparse_matrix_value (), info)); else if (! args(1).issparse () && args(1).iscomplex ()) retval = ovl (math::sparse_qr::solve - , ComplexMatrix> - (arg.sparse_matrix_value (), - args (1).complex_matrix_value (), info)); + , ComplexMatrix> + (arg.sparse_matrix_value (), + args (1).complex_matrix_value (), info)); else if (! args(1).issparse () && ! args(1).iscomplex ()) retval = ovl (math::sparse_qr::solve - , Matrix> - (arg.sparse_matrix_value (), - args (1).matrix_value (), info)); + , Matrix> + (arg.sparse_matrix_value (), + args (1).matrix_value (), info)); else if (args(1).issparse () && args(1).iscomplex ()) retval = ovl (math::sparse_qr::solve - - (arg.sparse_matrix_value (), - args(1).sparse_complex_matrix_value (), - info)); + + (arg.sparse_matrix_value (), + args(1).sparse_complex_matrix_value (), + info)); else error ("qr: b is not valid"); } @@ -821,7 +821,7 @@ %! [q, r, p] = qr (rand (3, 2), rand (3, 1), 0); %!function retval = __testqr (q, r, a, p) -%! tol = 100*eps (class (q)); +%! tol = 100* eps (class (q)); %! retval = 0; %! if (nargin == 3) %! n1 = norm (q*r - a); @@ -981,7 +981,7 @@ %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p); %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p); %! -%! a = a+1i*eps ("single"); +%! a = a+1i* eps ("single"); %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a); %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a'); %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p); @@ -994,7 +994,7 @@ %! [q,r,p] = qr (a); t(j++) = __testqr (q, r, a, p); %! [q,r,p] = qr (a'); t(j++) = __testqr (q, r, a', p); %! -%! a = a+1i*eps ("single"); +%! a = a+1i* eps ("single"); %! [q,r] = qr (a); t(j++) = __testqr (q, r, a); %! [q,r] = qr (a'); t(j++) = __testqr (q, r, a'); %! [q,r,p] = qr (a); t(j++) = __testqr (q, r, a, p); @@ -1006,7 +1006,7 @@ %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p); %! [q,r,p] = qr (a',0); t(j++) = __testqr (q, r, a', p); %! -%! a = a+1i*eps ("single"); +%! a = a+1i* eps ("single"); %! [q,r] = qr (a, 0); t(j++) = __testqr (q, r, a); %! [q,r] = qr (a',0); t(j++) = __testqr (q, r, a'); %! [q,r,p] = qr (a, 0); t(j++) = __testqr (q, r, a, p); @@ -1022,7 +1022,7 @@ %! 29 -44 52 -23 208 208 -911 99 ]; %! [q,r] = qr (a); %! -%! assert (all (t) && norm (q*r-a) < 5000*eps ("single")); +%! assert (all (t) && norm (q*r-a) < 5000* eps ("single")); ## The deactivated tests below can't be tested till rectangular back-subs is ## implemented for sparse matrices. @@ -1082,7 +1082,7 @@ %! ## initialize generators to make behavior reproducible %! rand ("state", 42); %! randn ("state", 42); -%! a = 1i*sprandn (n,n,d) + speye (n,n); +%! a = 1i* sprandn (n,n,d) + speye (n,n); %! r = qr (a); %! assert (r'*r,a'*a,1e-10); @@ -1091,7 +1091,7 @@ %! ## initialize generators to make behavior reproducible %! rand ("state", 42); %! randn ("state", 42); -%! a = 1i*sprandn (n,n,d) + speye (n,n); +%! a = 1i* sprandn (n,n,d) + speye (n,n); %! q = symamd (a); %! a = a(q,q); %! r = qr (a); @@ -1102,7 +1102,7 @@ %! ## initialize generators to make behavior reproducible %! rand ("state", 42); %! randn ("state", 42); -%! a = 1i*sprandn (n,n,d) + speye (n,n); +%! a = 1i* sprandn (n,n,d) + speye (n,n); %! [c,r] = qr (a, ones (n,1)); %! assert (r\c, full (a)\ones (n,1), 10e-10); @@ -1111,7 +1111,7 @@ %! ## initialize generators to make behavior reproducible %! rand ("state", 42); %! randn ("state", 42); -%! a = 1i*sprandn (n,n,d) + speye (n,n); +%! a = 1i* sprandn (n,n,d) + speye (n,n); %! b = randn (n,2); %! [c,r] = qr (a, b); %! assert (r\c, full (a)\b, 10e-10); @@ -1122,7 +1122,7 @@ %! ## initialize generators to make behavior reproducible %! rand ("state", 42); %! randn ("state", 42); -%! a = 1i*sprandn (n,n+1,d) + speye (n,n+1); +%! a = 1i* sprandn (n,n+1,d) + speye (n,n+1); %! b = randn (n, 2); %! [c, r] = qr (a, b); %! assert (r\c, full (a)\b, 10e-10); @@ -1439,18 +1439,18 @@ %!test %! [Q,R] = qr (single (A)); %! [Q,R] = qrupdate (Q, R, single (u), single (v)); -%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R)-R), Inf) == 0); -%! assert (norm (vec (Q*R - single (A) - single (u)*single (v)'), Inf) -%! < norm (single (A))*1e1*eps ("single")); +%! assert (norm (vec (Q*R - single (A) - single (u)* single (v)'), Inf) +%! < norm (single (A))*1e1* eps ("single")); %! %!test %! [Q,R] = qr (single (Ac)); %! [Q,R] = qrupdate (Q, R, single (uc), single (vc)); -%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R)-R), Inf) == 0); -%! assert (norm (vec (Q*R - single (Ac) - single (uc)*single (vc)'), Inf) -%! < norm (single (Ac))*1e1*eps ("single")); +%! assert (norm (vec (Q*R - single (Ac) - single (uc)* single (vc)'), Inf) +%! < norm (single (Ac))*1e1* eps ("single")); */ DEFUN (qrinsert, args, , @@ -1623,35 +1623,35 @@ %!test %! [Q,R] = qr (single (A)); %! [Q,R] = qrinsert (Q, R, 3, single (u)); -%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - single ([A(:,1:2) u A(:,3)])), Inf) -%! < norm (single (A))*1e1*eps ("single")); +%! < norm (single (A))*1e1* eps ("single")); %!test %! [Q,R] = qr (single (Ac)); %! [Q,R] = qrinsert (Q, R, 3, single (uc)); -%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - single ([Ac(:,1:2) uc Ac(:,3)])), Inf) -%! < norm (single (Ac))*1e1*eps ("single")); +%! < norm (single (Ac))*1e1* eps ("single")); %!test %! x = single ([0.85082 0.76426 0.42883 ]); %! %! [Q,R] = qr (single (A)); %! [Q,R] = qrinsert (Q, R, 3, x, "row"); -%! assert (norm (vec (Q'*Q - eye (6,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (6,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - single ([A(1:2,:);x;A(3:5,:)])), Inf) -%! < norm (single (A))*1e1*eps ("single")); +%! < norm (single (A))*1e1* eps ("single")); %!test %! x = single ([0.20351 + 0.05401i 0.13141 + 0.43708i 0.29808 + 0.08789i ]); %! %! [Q,R] = qr (single (Ac)); %! [Q,R] = qrinsert (Q, R, 3, x, "row"); -%! assert (norm (vec (Q'*Q - eye (6,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (6,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - single ([Ac(1:2,:);x;Ac(3:5,:)])), Inf) -%! < norm (single (Ac))*1e1*eps ("single")); +%! < norm (single (Ac))*1e1* eps ("single")); */ DEFUN (qrdelete, args, , @@ -1843,10 +1843,10 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrdelete (Q, R, 3); -%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) -%! < norm (AA)*1e1*eps ("single")); +%! < norm (AA)*1e1* eps ("single")); %! %!test %! AA = single ([0.364554 + 0.993117i 0.669818 + 0.510234i 0.426568 + 0.041337i 0.847051 + 0.233291i; @@ -1857,10 +1857,10 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrdelete (Q, R, 3); -%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (5,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - [AA(:,1:2) AA(:,4)]), Inf) -%! < norm (AA)*1e1*eps ("single")); +%! < norm (AA)*1e1* eps ("single")); %!test %! AA = single ([0.091364 0.613038 0.027504 0.999083; @@ -1871,10 +1871,10 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrdelete (Q, R, 3, "row"); -%! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1.5e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1.5e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) -%! < norm (AA)*1e1*eps ("single")); +%! < norm (AA)*1e1* eps ("single")); %!testif HAVE_QRUPDATE %! ## Same test as above but with more precicision %! AA = single ([0.091364 0.613038 0.027504 0.999083; @@ -1885,10 +1885,10 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrdelete (Q, R, 3, "row"); -%! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) -%! < norm (AA)*1e1*eps ("single")); +%! < norm (AA)*1e1* eps ("single")); %! %!test %! AA = single ([0.364554 + 0.993117i 0.669818 + 0.510234i 0.426568 + 0.041337i 0.847051 + 0.233291i; @@ -1899,10 +1899,10 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrdelete (Q, R, 3, "row"); -%! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (4,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); %! assert (norm (vec (Q*R - [AA(1:2,:);AA(4:5,:)]), Inf) -%! < norm (AA)*1e1*eps ("single")); +%! < norm (AA)*1e1* eps ("single")); */ DEFUN (qrshift, args, , @@ -2041,17 +2041,17 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrshift (Q, R, i, j); -%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); -%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single")); +%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1* eps ("single")); %! %! j = 2; i = 4; p = [1:j-1, shift(j:i,+1), i+1:5]; %! %! [Q,R] = qr (AA); %! [Q,R] = qrshift (Q, R, i, j); -%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); -%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single")); +%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1* eps ("single")); %! %!test %! AA = single (Ac).'; @@ -2059,17 +2059,17 @@ %! %! [Q,R] = qr (AA); %! [Q,R] = qrshift (Q, R, i, j); -%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); -%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single")); +%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1* eps ("single")); %! %! j = 2; i = 4; p = [1:j-1, shift(j:i,+1), i+1:5]; %! %! [Q,R] = qr (AA); %! [Q,R] = qrshift (Q, R, i, j); -%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1*eps ("single")); +%! assert (norm (vec (Q'*Q - eye (3,"single")), Inf) < 1e1* eps ("single")); %! assert (norm (vec (triu (R) - R), Inf) == 0); -%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1*eps ("single")); +%! assert (norm (vec (Q*R - AA(:,p)), Inf) < norm (AA)*1e1* eps ("single")); */ OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/quadcc.cc --- a/libinterp/corefcn/quadcc.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/quadcc.cc Thu Dec 01 20:05:44 2022 -0800 @@ -68,19 +68,19 @@ static const double xi[33] = { -1., -0.99518472667219688624, -0.98078528040323044912, - -0.95694033573220886493, -0.92387953251128675612, - -0.88192126434835502970, -0.83146961230254523708, - -0.77301045336273696082, -0.70710678118654752440, - -0.63439328416364549822, -0.55557023301960222475, - -0.47139673682599764857, -0.38268343236508977173, - -0.29028467725446236764, -0.19509032201612826785, - -0.098017140329560601995, 0., 0.098017140329560601995, - 0.19509032201612826785, 0.29028467725446236764, 0.38268343236508977173, - 0.47139673682599764857, 0.55557023301960222475, 0.63439328416364549822, - 0.70710678118654752440, 0.77301045336273696082, 0.83146961230254523708, - 0.88192126434835502970, 0.92387953251128675612, 0.95694033573220886493, - 0.98078528040323044912, 0.99518472667219688624, 1. -}; + -0.95694033573220886493, -0.92387953251128675612, + -0.88192126434835502970, -0.83146961230254523708, + -0.77301045336273696082, -0.70710678118654752440, + -0.63439328416364549822, -0.55557023301960222475, + -0.47139673682599764857, -0.38268343236508977173, + -0.29028467725446236764, -0.19509032201612826785, + -0.098017140329560601995, 0., 0.098017140329560601995, + 0.19509032201612826785, 0.29028467725446236764, 0.38268343236508977173, + 0.47139673682599764857, 0.55557023301960222475, 0.63439328416364549822, + 0.70710678118654752440, 0.77301045336273696082, 0.83146961230254523708, + 0.88192126434835502970, 0.92387953251128675612, 0.95694033573220886493, + 0.98078528040323044912, 0.99518472667219688624, 1. + }; static const double bee[68] = { @@ -1657,7 +1657,7 @@ nivals = 1 + args(4).numel (); int cquad_heapsize = (nivals >= MIN_CQUAD_HEAPSIZE ? nivals + 1 - : MIN_CQUAD_HEAPSIZE); + : MIN_CQUAD_HEAPSIZE); // The interval heap. OCTAVE_LOCAL_BUFFER (cquad_ival, ivals, cquad_heapsize); OCTAVE_LOCAL_BUFFER (double, iivals, cquad_heapsize); @@ -2208,7 +2208,7 @@ } #endif - if (nargout < 2 && err > std::max (abstol, reltol * std::abs (igral))) + if (nargout < 2 && err > std::max (abstol, reltol * std::abs (igral))) warning ("quadcc: Error tolerance not met. Estimated error: %g\n", err); if (issingle) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/rand.cc --- a/libinterp/corefcn/rand.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/rand.cc Thu Dec 01 20:05:44 2022 -0800 @@ -120,10 +120,10 @@ // Restore current distribution on any exit. unwind_action restore_distribution - ([] (const std::string& old_distribution) - { - rand::distribution (old_distribution); - }, rand::distribution ()); + ([] (const std::string& old_distribution) + { + rand::distribution (old_distribution); + }, rand::distribution ()); rand::distribution (distribution); @@ -1069,7 +1069,7 @@ %! ## statistical tests may fail occasionally. %! randp ("state", 12); %! for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03] -%! x = randp (a(1)*ones (100_000, 1), 100_000, 1); +%! x = randp (a(1)* ones (100_000, 1), 100_000, 1); %! assert (min (x) >= 0); # *** Please report this!!! *** %! assert (mean (x), a(1), a(2)); %! assert (var (x), a(1), 0.02*a(1)); @@ -1098,7 +1098,7 @@ %! ## statistical tests may fail occasionally. %! randp ("seed", 12); %! for a = [5, 15, 1e9; 0.03, 0.03, -5e-3; 0.03, 0.03, 0.03] -%! x = randp (a(1)*ones (100_000, 1), 100_000, 1); +%! x = randp (a(1)* ones (100_000, 1), 100_000, 1); %! assert (min (x) >= 0); # *** Please report this!!! *** %! assert (mean (x), a(1), a(2)); %! assert (var (x), a(1), 0.02*a(1)); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/regexp.cc --- a/libinterp/corefcn/regexp.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/regexp.cc Thu Dec 01 20:05:44 2022 -0800 @@ -91,35 +91,35 @@ break; case 'o': // octal input - { - bool bad_esc_seq = (j+1 >= len); + { + bool bad_esc_seq = (j+1 >= len); - bool brace = false; - if (! bad_esc_seq && s[++j] == '{') - { - brace = true; - j++; - } + bool brace = false; + if (! bad_esc_seq && s[++j] == '{') + { + brace = true; + j++; + } - int tmpi = 0; - std::size_t k; - for (k = j; k < std::min (j+3+brace, len); k++) - { - int digit = s[k] - '0'; - if (digit < 0 || digit > 7) - break; - tmpi <<= 3; - tmpi += digit; - } - if (bad_esc_seq || (brace && s[k++] != '}')) - { - tmpi = 0; - warning (R"(malformed octal escape sequence '\o' -- converting to '\0')"); - } - retval[i] = tmpi; - j = k - 1; - break; - } + int tmpi = 0; + std::size_t k; + for (k = j; k < std::min (j+3+brace, len); k++) + { + int digit = s[k] - '0'; + if (digit < 0 || digit > 7) + break; + tmpi <<= 3; + tmpi += digit; + } + if (bad_esc_seq || (brace && s[k++] != '}')) + { + tmpi = 0; + warning (R"(malformed octal escape sequence '\o' -- converting to '\0')"); + } + retval[i] = tmpi; + j = k - 1; + break; + } default: // pass escape sequence through retval[i] = '\\'; @@ -194,89 +194,89 @@ case '5': case '6': case '7': // octal input - { - std::size_t k; - int tmpi = s[j] - '0'; - for (k = j+1; k < std::min (j+3, len); k++) - { - int digit = s[k] - '0'; - if (digit < 0 || digit > 7) - break; - tmpi <<= 3; - tmpi += digit; - } - retval[i] = tmpi; - j = k - 1; - break; - } + { + std::size_t k; + int tmpi = s[j] - '0'; + for (k = j+1; k < std::min (j+3, len); k++) + { + int digit = s[k] - '0'; + if (digit < 0 || digit > 7) + break; + tmpi <<= 3; + tmpi += digit; + } + retval[i] = tmpi; + j = k - 1; + break; + } case 'o': // octal input - { - bool bad_esc_seq = (j+1 >= len); + { + bool bad_esc_seq = (j+1 >= len); - bool brace = false; - if (! bad_esc_seq && s[++j] == '{') - { - brace = true; - j++; - } + bool brace = false; + if (! bad_esc_seq && s[++j] == '{') + { + brace = true; + j++; + } - int tmpi = 0; - std::size_t k; - for (k = j; k < std::min (j+3+brace, len); k++) - { - int digit = s[k] - '0'; - if (digit < 0 || digit > 7) - break; - tmpi <<= 3; - tmpi += digit; - } - if (bad_esc_seq || (brace && s[k++] != '}')) - { - warning (R"(malformed octal escape sequence '\o' -- converting to '\0')"); - tmpi = 0; - } - retval[i] = tmpi; - j = k - 1; - break; - } + int tmpi = 0; + std::size_t k; + for (k = j; k < std::min (j+3+brace, len); k++) + { + int digit = s[k] - '0'; + if (digit < 0 || digit > 7) + break; + tmpi <<= 3; + tmpi += digit; + } + if (bad_esc_seq || (brace && s[k++] != '}')) + { + warning (R"(malformed octal escape sequence '\o' -- converting to '\0')"); + tmpi = 0; + } + retval[i] = tmpi; + j = k - 1; + break; + } case 'x': // hex input - { - bool bad_esc_seq = (j+1 >= len); + { + bool bad_esc_seq = (j+1 >= len); - bool brace = false; - if (! bad_esc_seq && s[++j] == '{') - { - brace = true; - j++; - } + bool brace = false; + if (! bad_esc_seq && s[++j] == '{') + { + brace = true; + j++; + } - int tmpi = 0; - std::size_t k; - for (k = j; k < std::min (j+2+brace, len); k++) - { - if (! isxdigit (s[k])) - break; + int tmpi = 0; + std::size_t k; + for (k = j; k < std::min (j+2+brace, len); k++) + { + if (! isxdigit (s[k])) + break; - tmpi <<= 4; - int digit = s[k]; - if (digit >= 'a') - tmpi += digit - 'a' + 10; - else if (digit >= 'A') - tmpi += digit - 'A' + 10; - else - tmpi += digit - '0'; - } - if (bad_esc_seq || (brace && s[k++] != '}')) - { - warning (R"(malformed hex escape sequence '\x' -- converting to '\0')"); - tmpi = 0; - } - retval[i] = tmpi; - j = k - 1; - break; - } + tmpi <<= 4; + int digit = s[k]; + if (digit >= 'a') + tmpi += digit - 'a' + 10; + else if (digit >= 'A') + tmpi += digit - 'A' + 10; + else + tmpi += digit - '0'; + } + if (bad_esc_seq || (brace && s[k++] != '}')) + { + warning (R"(malformed hex escape sequence '\x' -- converting to '\0')"); + tmpi = 0; + } + retval[i] = tmpi; + j = k - 1; + break; + } // Both dollar sign (for capture buffer) and backslash are // passed through with their escape backslash. The processing diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/settings.cc --- a/libinterp/corefcn/settings.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/settings.cc Thu Dec 01 20:05:44 2022 -0800 @@ -36,24 +36,24 @@ OCTAVE_BEGIN_NAMESPACE(octave) - settings::settings (void) - : m_display_tokens (false), m_token_count (0), - m_lexer_debug_flag (false) - { } +settings::settings (void) + : m_display_tokens (false), m_token_count (0), + m_lexer_debug_flag (false) +{ } - octave_value settings::display_tokens (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_display_tokens, args, nargout, - "__display_tokens__"); - } +octave_value settings::display_tokens (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_display_tokens, args, nargout, + "__display_tokens__"); +} - octave_value settings::lexer_debug_flag (const octave_value_list& args, - int nargout) - { - return set_internal_variable (m_lexer_debug_flag, args, nargout, - "__lexer_debug_flag__"); - } +octave_value settings::lexer_debug_flag (const octave_value_list& args, + int nargout) +{ + return set_internal_variable (m_lexer_debug_flag, args, nargout, + "__lexer_debug_flag__"); +} DEFMETHOD (__display_tokens__, interp, args, nargout, doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/settings.h --- a/libinterp/corefcn/settings.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/settings.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,62 +35,62 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Most settings for the interpreter are stored in the classes which - // they affect (intput_system, output_system, load_path, etc. Some - // don't really fit anywhere else. For example, there is no single - // lexer or parser object, so we store settings for those things - // here. +// Most settings for the interpreter are stored in the classes which +// they affect (intput_system, output_system, load_path, etc. Some +// don't really fit anywhere else. For example, there is no single +// lexer or parser object, so we store settings for those things +// here. - class settings - { - public: +class settings +{ +public: - settings (void); + settings (void); - settings (const settings&) = delete; + settings (const settings&) = delete; - settings& operator = (const settings&) = delete; + settings& operator = (const settings&) = delete; - ~settings (void) = default; + ~settings (void) = default; - octave_value display_tokens (const octave_value_list& args, int nargout); + octave_value display_tokens (const octave_value_list& args, int nargout); - bool display_tokens (void) const { return m_display_tokens; } + bool display_tokens (void) const { return m_display_tokens; } - bool display_tokens (bool flag) - { - bool val = m_display_tokens; - m_display_tokens = flag; - return val; - } + bool display_tokens (bool flag) + { + bool val = m_display_tokens; + m_display_tokens = flag; + return val; + } - // Read only. - std::size_t token_count (void) const { return m_token_count; } + // Read only. + std::size_t token_count (void) const { return m_token_count; } - void increment_token_count (void) { ++m_token_count; } + void increment_token_count (void) { ++m_token_count; } - octave_value lexer_debug_flag (const octave_value_list& args, int nargout); + octave_value lexer_debug_flag (const octave_value_list& args, int nargout); - bool lexer_debug_flag (void) const { return m_lexer_debug_flag; } + bool lexer_debug_flag (void) const { return m_lexer_debug_flag; } - bool lexer_debug_flag (bool flag) - { - bool val = m_lexer_debug_flag; - m_lexer_debug_flag = flag; - return val; - } + bool lexer_debug_flag (bool flag) + { + bool val = m_lexer_debug_flag; + m_lexer_debug_flag = flag; + return val; + } - private: +private: - // Display tokens as they are processed, for debugging. - bool m_display_tokens = false; + // Display tokens as they are processed, for debugging. + bool m_display_tokens = false; - // Number of tokens processed since interpreter startup. - std::size_t m_token_count = 0; + // Number of tokens processed since interpreter startup. + std::size_t m_token_count = 0; - // Internal variable for lexer debugging state. - bool m_lexer_debug_flag = false; - }; + // Internal variable for lexer debugging state. + bool m_lexer_debug_flag = false; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/sighandlers.cc --- a/libinterp/corefcn/sighandlers.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/sighandlers.cc Thu Dec 01 20:05:44 2022 -0800 @@ -60,436 +60,436 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Nonzero means we have already printed a message for this series of - // SIGPIPES. We assume that the writer will eventually give up. - int pipe_handler_error_count = 0; +// Nonzero means we have already printed a message for this series of +// SIGPIPES. We assume that the writer will eventually give up. +int pipe_handler_error_count = 0; - // TRUE means we can be interrupted. - bool can_interrupt = false; +// TRUE means we can be interrupted. +bool can_interrupt = false; - // TRUE means we should try to enter the debugger on SIGINT. - bool Vdebug_on_interrupt = false; +// TRUE means we should try to enter the debugger on SIGINT. +bool Vdebug_on_interrupt = false; - // Allow users to avoid writing octave-workspace for SIGHUP (sent by - // closing gnome-terminal, for example). Note that this variable has - // no effect if Vcrash_dumps_octave_core is FALSE. - static bool Vsighup_dumps_octave_core = true; +// Allow users to avoid writing octave-workspace for SIGHUP (sent by +// closing gnome-terminal, for example). Note that this variable has +// no effect if Vcrash_dumps_octave_core is FALSE. +static bool Vsighup_dumps_octave_core = true; - // Similar to Vsighup_dumps_octave_core, but for SIGQUIT signal. - static bool Vsigquit_dumps_octave_core = true; +// Similar to Vsighup_dumps_octave_core, but for SIGQUIT signal. +static bool Vsigquit_dumps_octave_core = true; - // Similar to Vsighup_dumps_octave_core, but for SIGTERM signal. - static bool Vsigterm_dumps_octave_core = true; +// Similar to Vsighup_dumps_octave_core, but for SIGTERM signal. +static bool Vsigterm_dumps_octave_core = true; - // List of signals we have caught since last call to signal_handler. - static bool *signals_caught = nullptr; +// List of signals we have caught since last call to signal_handler. +static bool *signals_caught = nullptr; - static void - my_friendly_exit (int sig, bool save_vars = true) - { - std::cerr << "fatal: caught signal " - << octave_strsignal_wrapper (sig) - << " -- stopping myself..." << std::endl; +static void +my_friendly_exit (int sig, bool save_vars = true) +{ + std::cerr << "fatal: caught signal " + << octave_strsignal_wrapper (sig) + << " -- stopping myself..." << std::endl; - if (save_vars) - { - load_save_system& load_save_sys = __get_load_save_system__ (); + if (save_vars) + { + load_save_system& load_save_sys = __get_load_save_system__ (); - load_save_sys.dump_octave_core (); - } + load_save_sys.dump_octave_core (); + } - sysdep_cleanup (); + sysdep_cleanup (); - throw exit_exception (1); - } + throw exit_exception (1); +} - // Called from octave_quit () to actually do something about the signals - // we have caught. +// Called from octave_quit () to actually do something about the signals +// we have caught. - void - respond_to_pending_signals (void) - { - // The list of signals is relatively short, so we will just go - // linearly through the list. +void +respond_to_pending_signals (void) +{ + // The list of signals is relatively short, so we will just go + // linearly through the list. - // Interrupt signals are currently handled separately. + // Interrupt signals are currently handled separately. - static int sigint; - static const bool have_sigint - = octave_get_sig_number ("SIGINT", &sigint); + static int sigint; + static const bool have_sigint + = octave_get_sig_number ("SIGINT", &sigint); - static int sigbreak; - static const bool have_sigbreak - = octave_get_sig_number ("SIGBREAK", &sigbreak); + static int sigbreak; + static const bool have_sigbreak + = octave_get_sig_number ("SIGBREAK", &sigbreak); - // Termination signals. + // Termination signals. - static int sighup; - static const bool have_sighup - = octave_get_sig_number ("SIGHUP", &sighup); + static int sighup; + static const bool have_sighup + = octave_get_sig_number ("SIGHUP", &sighup); - static int sigquit; - static const bool have_sigquit - = octave_get_sig_number ("SIGQUIT", &sigquit); + static int sigquit; + static const bool have_sigquit + = octave_get_sig_number ("SIGQUIT", &sigquit); - static int sigterm; - static const bool have_sigterm - = octave_get_sig_number ("SIGTERM", &sigterm); + static int sigterm; + static const bool have_sigterm + = octave_get_sig_number ("SIGTERM", &sigterm); - // Alarm signals. + // Alarm signals. - static int sigalrm; - static const bool have_sigalrm - = octave_get_sig_number ("SIGALRM", &sigalrm); + static int sigalrm; + static const bool have_sigalrm + = octave_get_sig_number ("SIGALRM", &sigalrm); - static int sigvtalrm; - static const bool have_sigvtalrm - = octave_get_sig_number ("SIGVTALRM", &sigvtalrm); + static int sigvtalrm; + static const bool have_sigvtalrm + = octave_get_sig_number ("SIGVTALRM", &sigvtalrm); - // I/O signals. + // I/O signals. - static int sigio; - static const bool have_sigio - = octave_get_sig_number ("SIGIO", &sigio); + static int sigio; + static const bool have_sigio + = octave_get_sig_number ("SIGIO", &sigio); - static int siglost; - static const bool have_siglost - = octave_get_sig_number ("SIGLOST", &siglost); + static int siglost; + static const bool have_siglost + = octave_get_sig_number ("SIGLOST", &siglost); - static int sigpipe; - static const bool have_sigpipe - = octave_get_sig_number ("SIGPIPE", &sigpipe); + static int sigpipe; + static const bool have_sigpipe + = octave_get_sig_number ("SIGPIPE", &sigpipe); - // Job control signals. + // Job control signals. - static int sigchld; - static const bool have_sigchld - = octave_get_sig_number ("SIGCHLD", &sigchld); + static int sigchld; + static const bool have_sigchld + = octave_get_sig_number ("SIGCHLD", &sigchld); - static int sigcld; - static const bool have_sigcld - = octave_get_sig_number ("SIGCLD", &sigcld); + static int sigcld; + static const bool have_sigcld + = octave_get_sig_number ("SIGCLD", &sigcld); - // Resource limit signals. + // Resource limit signals. - static int sigxcpu; - static const bool have_sigxcpu - = octave_get_sig_number ("SIGXCPU", &sigxcpu); + static int sigxcpu; + static const bool have_sigxcpu + = octave_get_sig_number ("SIGXCPU", &sigxcpu); - static int sigxfsz; - static const bool have_sigxfsz - = octave_get_sig_number ("SIGXFSZ", &sigxfsz); + static int sigxfsz; + static const bool have_sigxfsz + = octave_get_sig_number ("SIGXFSZ", &sigxfsz); - // User signals. + // User signals. - static int sigusr1; - static const bool have_sigusr1 - = octave_get_sig_number ("SIGUSR1", &sigusr1); + static int sigusr1; + static const bool have_sigusr1 + = octave_get_sig_number ("SIGUSR1", &sigusr1); - static int sigusr2; - static const bool have_sigusr2 - = octave_get_sig_number ("SIGUSR2", &sigusr2); + static int sigusr2; + static const bool have_sigusr2 + = octave_get_sig_number ("SIGUSR2", &sigusr2); - child_list& kids = __get_child_list__ (); + child_list& kids = __get_child_list__ (); - for (int sig = 0; sig < octave_num_signals (); sig++) - { - if (signals_caught[sig]) - { - signals_caught[sig] = false; + for (int sig = 0; sig < octave_num_signals (); sig++) + { + if (signals_caught[sig]) + { + signals_caught[sig] = false; - if ((have_sigchld && sig == sigchld) - || (have_sigcld && sig == sigcld)) - { - // FIXME: should we block or ignore? - volatile interrupt_handler saved_interrupt_handler - = ignore_interrupts (); + if ((have_sigchld && sig == sigchld) + || (have_sigcld && sig == sigcld)) + { + // FIXME: should we block or ignore? + volatile interrupt_handler saved_interrupt_handler + = ignore_interrupts (); - void *context = octave_block_child (); + void *context = octave_block_child (); - kids.wait (); + kids.wait (); - set_interrupt_handler (saved_interrupt_handler); + set_interrupt_handler (saved_interrupt_handler); - octave_unblock_child (context); + octave_unblock_child (context); - kids.reap (); - } - else if (have_sigpipe && sig == sigpipe) - { - std::cerr << "warning: broken pipe" << std::endl; + kids.reap (); + } + else if (have_sigpipe && sig == sigpipe) + { + std::cerr << "warning: broken pipe" << std::endl; - // Don't loop forever on account of this. - // FIXME: is this really needed? Does it do anything - // useful now? + // Don't loop forever on account of this. + // FIXME: is this really needed? Does it do anything + // useful now? - if (pipe_handler_error_count++ > 100 - && octave_interrupt_state >= 0) - octave_interrupt_state++; - } - else if (have_sighup && sig == sighup) - my_friendly_exit (sighup, Vsighup_dumps_octave_core); - else if (have_sigquit && sig == sigquit) - my_friendly_exit (sigquit, Vsigquit_dumps_octave_core); - else if (have_sigterm && sig == sigterm) - my_friendly_exit (sigterm, Vsigterm_dumps_octave_core); - else if ((have_sigalrm && sig == sigalrm) - || (have_sigvtalrm && sig == sigvtalrm) - || (have_sigio && sig == sigio) - || (have_siglost && sig == siglost) - || (have_sigxcpu && sig == sigxcpu) - || (have_sigxfsz && sig == sigxfsz) - || (have_sigusr1 && sig == sigusr1) - || (have_sigusr2 && sig == sigusr2)) - std::cerr << "warning: ignoring signal: " - << octave_strsignal_wrapper (sig) - << std::endl; - else if ((have_sigint && sig == sigint) - || (have_sigbreak && sig == sigbreak)) - ; // Handled separately; do nothing. - else - std::cerr << "warning: ignoring unexpected signal: " - << octave_strsignal_wrapper (sig) - << std::endl; - } - } - } + if (pipe_handler_error_count++ > 100 + && octave_interrupt_state >= 0) + octave_interrupt_state++; + } + else if (have_sighup && sig == sighup) + my_friendly_exit (sighup, Vsighup_dumps_octave_core); + else if (have_sigquit && sig == sigquit) + my_friendly_exit (sigquit, Vsigquit_dumps_octave_core); + else if (have_sigterm && sig == sigterm) + my_friendly_exit (sigterm, Vsigterm_dumps_octave_core); + else if ((have_sigalrm && sig == sigalrm) + || (have_sigvtalrm && sig == sigvtalrm) + || (have_sigio && sig == sigio) + || (have_siglost && sig == siglost) + || (have_sigxcpu && sig == sigxcpu) + || (have_sigxfsz && sig == sigxfsz) + || (have_sigusr1 && sig == sigusr1) + || (have_sigusr2 && sig == sigusr2)) + std::cerr << "warning: ignoring signal: " + << octave_strsignal_wrapper (sig) + << std::endl; + else if ((have_sigint && sig == sigint) + || (have_sigbreak && sig == sigbreak)) + ; // Handled separately; do nothing. + else + std::cerr << "warning: ignoring unexpected signal: " + << octave_strsignal_wrapper (sig) + << std::endl; + } + } +} - sig_handler * - set_signal_handler (int sig, sig_handler *handler, bool restart_syscalls) - { - return octave_set_signal_handler_internal (sig, handler, restart_syscalls); - } +sig_handler * +set_signal_handler (int sig, sig_handler *handler, bool restart_syscalls) +{ + return octave_set_signal_handler_internal (sig, handler, restart_syscalls); +} - sig_handler * - set_signal_handler (const char *signame, sig_handler *handler, - bool restart_syscalls) - { - return octave_set_signal_handler_by_name (signame, handler, - restart_syscalls); - } +sig_handler * +set_signal_handler (const char *signame, sig_handler *handler, + bool restart_syscalls) +{ + return octave_set_signal_handler_by_name (signame, handler, + restart_syscalls); +} - static void - generic_sig_handler (int sig) - { - // FIXME: this function may execute in a separate signal handler or - // signal watcher thread so it should probably be more careful about - // how it accesses global objects. +static void +generic_sig_handler (int sig) +{ + // FIXME: this function may execute in a separate signal handler or + // signal watcher thread so it should probably be more careful about + // how it accesses global objects. - octave_signal_caught = 1; + octave_signal_caught = 1; - signals_caught[sig] = true; + signals_caught[sig] = true; - static int sigint; - static const bool have_sigint - = octave_get_sig_number ("SIGINT", &sigint); + static int sigint; + static const bool have_sigint + = octave_get_sig_number ("SIGINT", &sigint); - static int sigbreak; - static const bool have_sigbreak - = octave_get_sig_number ("SIGBREAK", &sigbreak); + static int sigbreak; + static const bool have_sigbreak + = octave_get_sig_number ("SIGBREAK", &sigbreak); - if ((have_sigint && sig == sigint) - || (have_sigbreak && sig == sigbreak)) - { - if (! octave_initialized) - exit (1); + if ((have_sigint && sig == sigint) + || (have_sigbreak && sig == sigbreak)) + { + if (! octave_initialized) + exit (1); - if (can_interrupt) - { - octave_signal_caught = 1; - octave_interrupt_state++; - } - } - } + if (can_interrupt) + { + octave_signal_caught = 1; + octave_interrupt_state++; + } + } +} - static void - deadly_sig_handler (int sig) - { - std::cerr << "fatal: caught signal " - << octave_strsignal_wrapper (sig) - << " -- stopping myself..." << std::endl; +static void +deadly_sig_handler (int sig) +{ + std::cerr << "fatal: caught signal " + << octave_strsignal_wrapper (sig) + << " -- stopping myself..." << std::endl; - octave_set_default_signal_handler (sig); + octave_set_default_signal_handler (sig); - octave_raise_wrapper (sig); - } + octave_raise_wrapper (sig); +} - static void - fpe_sig_handler (int) - { - // FIXME: is there something better we can do? +static void +fpe_sig_handler (int) +{ + // FIXME: is there something better we can do? - std::cerr << "warning: floating point exception" << std::endl; - } + std::cerr << "warning: floating point exception" << std::endl; +} - interrupt_handler - catch_interrupts (void) - { - interrupt_handler retval; +interrupt_handler +catch_interrupts (void) +{ + interrupt_handler retval; - retval.int_handler = set_signal_handler ("SIGINT", generic_sig_handler); - retval.brk_handler = set_signal_handler ("SIGBREAK", generic_sig_handler); + retval.int_handler = set_signal_handler ("SIGINT", generic_sig_handler); + retval.brk_handler = set_signal_handler ("SIGBREAK", generic_sig_handler); - return retval; - } + return retval; +} - interrupt_handler - ignore_interrupts (void) - { - interrupt_handler retval; +interrupt_handler +ignore_interrupts (void) +{ + interrupt_handler retval; - retval.int_handler = set_signal_handler ("SIGINT", SIG_IGN); - retval.brk_handler = set_signal_handler ("SIGBREAK", SIG_IGN); + retval.int_handler = set_signal_handler ("SIGINT", SIG_IGN); + retval.brk_handler = set_signal_handler ("SIGBREAK", SIG_IGN); - return retval; - } + return retval; +} - interrupt_handler - set_interrupt_handler (const volatile interrupt_handler& h, - bool restart_syscalls) - { - interrupt_handler retval; +interrupt_handler +set_interrupt_handler (const volatile interrupt_handler& h, + bool restart_syscalls) +{ + interrupt_handler retval; - retval.int_handler = set_signal_handler ("SIGINT", h.int_handler, - restart_syscalls); + retval.int_handler = set_signal_handler ("SIGINT", h.int_handler, + restart_syscalls); - retval.brk_handler = set_signal_handler ("SIGBREAK", h.brk_handler, - restart_syscalls); + retval.brk_handler = set_signal_handler ("SIGBREAK", h.brk_handler, + restart_syscalls); - return retval; - } + return retval; +} - // Install all the handlers for the signals we might care about. +// Install all the handlers for the signals we might care about. - void - install_signal_handlers (void) - { - if (! signals_caught) - signals_caught = new bool [octave_num_signals ()]; +void +install_signal_handlers (void) +{ + if (! signals_caught) + signals_caught = new bool [octave_num_signals ()]; - for (int i = 0; i < octave_num_signals (); i++) - signals_caught[i] = false; + for (int i = 0; i < octave_num_signals (); i++) + signals_caught[i] = false; - // Interrupt signals. + // Interrupt signals. - catch_interrupts (); + catch_interrupts (); - // Program Error signals. These are most likely unrecoverable for - // us. + // Program Error signals. These are most likely unrecoverable for + // us. - set_signal_handler ("SIGABRT", deadly_sig_handler); - set_signal_handler ("SIGBUS", deadly_sig_handler); - set_signal_handler ("SIGEMT", deadly_sig_handler); - set_signal_handler ("SIGILL", deadly_sig_handler); - // SIGIOT is normally another name for SIGABRT. - set_signal_handler ("SIGIOT", deadly_sig_handler); - set_signal_handler ("SIGSEGV", deadly_sig_handler); - set_signal_handler ("SIGSYS", deadly_sig_handler); - set_signal_handler ("SIGTRAP", deadly_sig_handler); + set_signal_handler ("SIGABRT", deadly_sig_handler); + set_signal_handler ("SIGBUS", deadly_sig_handler); + set_signal_handler ("SIGEMT", deadly_sig_handler); + set_signal_handler ("SIGILL", deadly_sig_handler); + // SIGIOT is normally another name for SIGABRT. + set_signal_handler ("SIGIOT", deadly_sig_handler); + set_signal_handler ("SIGSEGV", deadly_sig_handler); + set_signal_handler ("SIGSYS", deadly_sig_handler); + set_signal_handler ("SIGTRAP", deadly_sig_handler); - // Handle SIGFPE separately. + // Handle SIGFPE separately. - set_signal_handler ("SIGFPE", fpe_sig_handler); + set_signal_handler ("SIGFPE", fpe_sig_handler); - // Handle other signals for which the default action is to terminate - // the program. + // Handle other signals for which the default action is to terminate + // the program. - // Termination signals. + // Termination signals. - set_signal_handler ("SIGHUP", generic_sig_handler); - set_signal_handler ("SIGQUIT", generic_sig_handler); - set_signal_handler ("SIGTERM", generic_sig_handler); + set_signal_handler ("SIGHUP", generic_sig_handler); + set_signal_handler ("SIGQUIT", generic_sig_handler); + set_signal_handler ("SIGTERM", generic_sig_handler); - // Alarm signals. + // Alarm signals. - set_signal_handler ("SIGALRM", generic_sig_handler); - set_signal_handler ("SIGVTALRM", generic_sig_handler); + set_signal_handler ("SIGALRM", generic_sig_handler); + set_signal_handler ("SIGVTALRM", generic_sig_handler); - // I/O signals. + // I/O signals. - set_signal_handler ("SIGLOST", generic_sig_handler); - set_signal_handler ("SIGPIPE", generic_sig_handler); + set_signal_handler ("SIGLOST", generic_sig_handler); + set_signal_handler ("SIGPIPE", generic_sig_handler); - // Job control signals. We only recognize signals about child - // processes. + // Job control signals. We only recognize signals about child + // processes. - set_signal_handler ("SIGCHLD", generic_sig_handler); - set_signal_handler ("SIGCLD", generic_sig_handler); + set_signal_handler ("SIGCHLD", generic_sig_handler); + set_signal_handler ("SIGCLD", generic_sig_handler); - // Resource limit signals. + // Resource limit signals. - // FIXME: does it really make sense to try to handle the CPU limit - // signal? + // FIXME: does it really make sense to try to handle the CPU limit + // signal? - set_signal_handler ("SIGXCPU", generic_sig_handler); - set_signal_handler ("SIGXFSZ", generic_sig_handler); + set_signal_handler ("SIGXCPU", generic_sig_handler); + set_signal_handler ("SIGXFSZ", generic_sig_handler); - // User signals. + // User signals. - set_signal_handler ("SIGUSR1", generic_sig_handler); - set_signal_handler ("SIGUSR2", generic_sig_handler); + set_signal_handler ("SIGUSR1", generic_sig_handler); + set_signal_handler ("SIGUSR2", generic_sig_handler); - // This does nothing on Windows systems. - octave_create_interrupt_watcher_thread (generic_sig_handler); - } + // This does nothing on Windows systems. + octave_create_interrupt_watcher_thread (generic_sig_handler); +} - static void - set_sig_struct_field (octave_scalar_map& m, const char *signame) - { - int signum; +static void +set_sig_struct_field (octave_scalar_map& m, const char *signame) +{ + int signum; - // The names in the struct do not include the leading "SIG" prefix. + // The names in the struct do not include the leading "SIG" prefix. - if (octave_get_sig_number (signame, &signum)) - m.assign (&signame[3], signum); - } + if (octave_get_sig_number (signame, &signum)) + m.assign (&signame[3], signum); +} - static octave_scalar_map - make_sig_struct (void) - { - octave_scalar_map m; +static octave_scalar_map +make_sig_struct (void) +{ + octave_scalar_map m; - set_sig_struct_field (m, "SIGABRT"); - set_sig_struct_field (m, "SIGALRM"); - set_sig_struct_field (m, "SIGBUS"); - set_sig_struct_field (m, "SIGCHLD"); - set_sig_struct_field (m, "SIGCLD"); - set_sig_struct_field (m, "SIGCONT"); - set_sig_struct_field (m, "SIGEMT"); - set_sig_struct_field (m, "SIGFPE"); - set_sig_struct_field (m, "SIGHUP"); - set_sig_struct_field (m, "SIGILL"); - set_sig_struct_field (m, "SIGINFO"); - set_sig_struct_field (m, "SIGINT"); - set_sig_struct_field (m, "SIGIO"); - set_sig_struct_field (m, "SIGIOT"); - set_sig_struct_field (m, "SIGKILL"); - set_sig_struct_field (m, "SIGLOST"); - set_sig_struct_field (m, "SIGPIPE"); - set_sig_struct_field (m, "SIGPOLL"); - set_sig_struct_field (m, "SIGPROF"); - set_sig_struct_field (m, "SIGPWR"); - set_sig_struct_field (m, "SIGQUIT"); - set_sig_struct_field (m, "SIGSEGV"); - set_sig_struct_field (m, "SIGSTKFLT"); - set_sig_struct_field (m, "SIGSTOP"); - set_sig_struct_field (m, "SIGSYS"); - set_sig_struct_field (m, "SIGTERM"); - set_sig_struct_field (m, "SIGTRAP"); - set_sig_struct_field (m, "SIGTSTP"); - set_sig_struct_field (m, "SIGTTIN"); - set_sig_struct_field (m, "SIGTTOU"); - set_sig_struct_field (m, "SIGUNUSED"); - set_sig_struct_field (m, "SIGURG"); - set_sig_struct_field (m, "SIGUSR1"); - set_sig_struct_field (m, "SIGUSR2"); - set_sig_struct_field (m, "SIGVTALRM"); - set_sig_struct_field (m, "SIGWINCH"); - set_sig_struct_field (m, "SIGXCPU"); - set_sig_struct_field (m, "SIGXFSZ"); + set_sig_struct_field (m, "SIGABRT"); + set_sig_struct_field (m, "SIGALRM"); + set_sig_struct_field (m, "SIGBUS"); + set_sig_struct_field (m, "SIGCHLD"); + set_sig_struct_field (m, "SIGCLD"); + set_sig_struct_field (m, "SIGCONT"); + set_sig_struct_field (m, "SIGEMT"); + set_sig_struct_field (m, "SIGFPE"); + set_sig_struct_field (m, "SIGHUP"); + set_sig_struct_field (m, "SIGILL"); + set_sig_struct_field (m, "SIGINFO"); + set_sig_struct_field (m, "SIGINT"); + set_sig_struct_field (m, "SIGIO"); + set_sig_struct_field (m, "SIGIOT"); + set_sig_struct_field (m, "SIGKILL"); + set_sig_struct_field (m, "SIGLOST"); + set_sig_struct_field (m, "SIGPIPE"); + set_sig_struct_field (m, "SIGPOLL"); + set_sig_struct_field (m, "SIGPROF"); + set_sig_struct_field (m, "SIGPWR"); + set_sig_struct_field (m, "SIGQUIT"); + set_sig_struct_field (m, "SIGSEGV"); + set_sig_struct_field (m, "SIGSTKFLT"); + set_sig_struct_field (m, "SIGSTOP"); + set_sig_struct_field (m, "SIGSYS"); + set_sig_struct_field (m, "SIGTERM"); + set_sig_struct_field (m, "SIGTRAP"); + set_sig_struct_field (m, "SIGTSTP"); + set_sig_struct_field (m, "SIGTTIN"); + set_sig_struct_field (m, "SIGTTOU"); + set_sig_struct_field (m, "SIGUNUSED"); + set_sig_struct_field (m, "SIGURG"); + set_sig_struct_field (m, "SIGUSR1"); + set_sig_struct_field (m, "SIGUSR2"); + set_sig_struct_field (m, "SIGVTALRM"); + set_sig_struct_field (m, "SIGWINCH"); + set_sig_struct_field (m, "SIGXCPU"); + set_sig_struct_field (m, "SIGXFSZ"); - return m; - } + return m; +} DEFUN (SIG, args, , doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/sighandlers.h --- a/libinterp/corefcn/sighandlers.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/sighandlers.h Thu Dec 01 20:05:44 2022 -0800 @@ -42,44 +42,44 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // This type must match the typedef in signal-wrappers.h. - typedef void sig_handler (int); +// This type must match the typedef in signal-wrappers.h. +typedef void sig_handler (int); - struct interrupt_handler - { - sig_handler *int_handler; - sig_handler *brk_handler; - }; +struct interrupt_handler +{ + sig_handler *int_handler; + sig_handler *brk_handler; +}; - // Nonzero means we have already printed a message for this series of - // SIGPIPES. We assume that the writer will eventually give up. - extern int pipe_handler_error_count; +// Nonzero means we have already printed a message for this series of +// SIGPIPES. We assume that the writer will eventually give up. +extern int pipe_handler_error_count; - // TRUE means we can be interrupted. - extern OCTINTERP_API bool can_interrupt; +// TRUE means we can be interrupted. +extern OCTINTERP_API bool can_interrupt; - extern OCTINTERP_API sig_handler * - set_signal_handler (int sig, sig_handler *h, - bool restart_syscalls = true); +extern OCTINTERP_API sig_handler * +set_signal_handler (int sig, sig_handler *h, + bool restart_syscalls = true); - extern OCTINTERP_API sig_handler * - set_signal_handler (const char *signame, sig_handler *h, - bool restart_syscalls = true); +extern OCTINTERP_API sig_handler * +set_signal_handler (const char *signame, sig_handler *h, + bool restart_syscalls = true); - extern OCTINTERP_API void install_signal_handlers (void); +extern OCTINTERP_API void install_signal_handlers (void); - extern OCTINTERP_API void respond_to_pending_signals (void); +extern OCTINTERP_API void respond_to_pending_signals (void); - extern OCTINTERP_API interrupt_handler catch_interrupts (void); +extern OCTINTERP_API interrupt_handler catch_interrupts (void); - extern OCTINTERP_API interrupt_handler ignore_interrupts (void); +extern OCTINTERP_API interrupt_handler ignore_interrupts (void); - extern OCTINTERP_API interrupt_handler - set_interrupt_handler (const volatile interrupt_handler& h, - bool restart_syscalls = true); +extern OCTINTERP_API interrupt_handler +set_interrupt_handler (const volatile interrupt_handler& h, + bool restart_syscalls = true); - // TRUE means we should try to enter the debugger on SIGINT. - extern OCTINTERP_API bool Vdebug_on_interrupt; +// TRUE means we should try to enter the debugger on SIGINT. +extern OCTINTERP_API bool Vdebug_on_interrupt; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/sparse-xpow.cc --- a/libinterp/corefcn/sparse-xpow.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/sparse-xpow.cc Thu Dec 01 20:05:44 2022 -0800 @@ -144,8 +144,8 @@ uint64_t sparsity = atmp.numel () / atmp.nnz (); // reciprocal of density int threshold = (sparsity >= 1000) ? 40 - : (sparsity >= 100) ? 20 - : 3; + : (sparsity >= 100) ? 20 + : 3; if (btmp > threshold) // use squaring technique { @@ -238,8 +238,8 @@ uint64_t sparsity = atmp.numel () / atmp.nnz (); // reciprocal of density int threshold = (sparsity >= 1000) ? 40 - : (sparsity >= 100) ? 20 - : 3; + : (sparsity >= 100) ? 20 + : 3; if (btmp > threshold) // use squaring technique { @@ -566,7 +566,7 @@ { octave_quit (); result.xelem (a.ridx (i), j) = std::pow (a.data (i), - b(a.ridx (i), j)); + b(a.ridx (i), j)); } } result.maybe_compress (true); @@ -770,7 +770,7 @@ if (xisint (btmp)) result.xelem (a.ridx (i), j) = std::pow (a.data (i), - static_cast (btmp)); + static_cast (btmp)); else result.xelem (a.ridx (i), j) = std::pow (a.data (i), btmp); } @@ -834,7 +834,7 @@ { octave_quit (); result.xelem (a.ridx (i), j) = std::pow (a.data (i), - b(a.ridx (i), j)); + b(a.ridx (i), j)); } } result.maybe_compress (true); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/sqrtm.cc --- a/libinterp/corefcn/sqrtm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/sqrtm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -242,10 +242,10 @@ retval(0) = arg.sqrt (); else if (arg.is_single_type ()) retval(0) = do_sqrtm> (arg); + math::schur> (arg); else if (arg.isnumeric ()) retval(0) = do_sqrtm> (arg); + math::schur> (arg); if (nargout > 1) { @@ -261,7 +261,7 @@ } /* -%!assert (sqrtm (2*ones (2)), ones (2), 3*eps) +%!assert (sqrtm (2* ones (2)), ones (2), 3*eps) %!assert <*60797> (sqrtm (ones (4))^2, ones (4), 5*eps) ## The following two tests are from the reference in the docstring above. diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/stack-frame.cc --- a/libinterp/corefcn/stack-frame.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/stack-frame.cc Thu Dec 01 20:05:44 2022 -0800 @@ -50,2445 +50,2445 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class compiled_fcn_stack_frame : public stack_frame - { - public: - - compiled_fcn_stack_frame (void) = delete; - - compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link) - : stack_frame (tw, index, parent_link, static_link, - static_link->access_link ()), - m_fcn (fcn) - { } - - compiled_fcn_stack_frame (const compiled_fcn_stack_frame& elt) = default; - - compiled_fcn_stack_frame& - operator = (const compiled_fcn_stack_frame& elt) = delete; - - ~compiled_fcn_stack_frame (void) = default; - - bool is_compiled_fcn_frame (void) const { return true; } - - symbol_scope get_scope (void) const - { - return m_static_link->get_scope (); - } - - octave_function * function (void) const { return m_fcn; } - - symbol_record lookup_symbol (const std::string& name) const - { - return m_static_link->lookup_symbol (name); - } - - symbol_record insert_symbol (const std::string& name) - { - return m_static_link->insert_symbol (name); - } - - stack_frame::scope_flags scope_flag (const symbol_record& sym) const - { - // Look in closest stack frame that contains values (either the - // top scope, or a user-defined function or script). - - return m_static_link->scope_flag (sym); - } - - void set_auto_fcn_var (auto_var_type avt, const octave_value& val) - { - m_static_link->set_auto_fcn_var (avt, val); - } - - octave_value get_auto_fcn_var (auto_var_type avt) const - { - return m_static_link->get_auto_fcn_var (avt); - } - - // We only need to override one of each of these functions. The - // using declaration will avoid warnings about partially-overloaded - // virtual functions. - using stack_frame::varval; - using stack_frame::varref; - - octave_value varval (const symbol_record& sym) const - { - // Look in closest stack frame that contains values (either the - // top scope, or a user-defined function or script). - - return m_static_link->varval (sym); - } - - octave_value& varref (const symbol_record& sym) - { - // Look in closest stack frame that contains values (either the - // top scope, or a user-defined function or script). - - return m_static_link->varref (sym); - } - - void mark_scope (const symbol_record& sym, scope_flags flag) - { - // Look in closest stack frame that contains values (either the - // top scope, or a user-defined function or script). - - m_static_link->mark_scope (sym, flag); - } - - void display (bool follow = true) const; - - void accept (stack_frame_walker& sfw); - - private: - - // Compiled function object associated with this stack frame. - // Should always be a built-in, .oct or .mex file function and - // should always be valid. - octave_function *m_fcn; - }; - - // Scripts have a symbol_scope object to store the set of variables - // in the script, but values for those variables are stored in the - // stack frame corresponding to the nearest calling function or in - // the top-level scope (the evaluation stack frame). - // - // Accessing values in a scope requires a mapping from the index of - // the variable for the script scope to the list of values in the - // evaluation frame(s). The frame offset tells us how many access - // links we must follow to find the stack frame that holds the - // value. The value offset is the index into the vector of values - // in that stack frame that we should use to find the value. - // - // Frame and value offsets are set in this stack frame when it is - // created using information from the script and enclosing scopes. - // - // If a script is invoked in a nested function context, the frame - // offsets for individual values may be different. Some may be - // accessed from the invoking function and some may come from a - // parent function. - - class script_stack_frame : public stack_frame - { - public: - - script_stack_frame (void) = delete; - - script_stack_frame (tree_evaluator& tw, octave_user_script *script, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link); - - script_stack_frame (const script_stack_frame& elt) = default; - - script_stack_frame& operator = (const script_stack_frame& elt) = delete; - - ~script_stack_frame (void) - { - delete m_unwind_protect_frame; - } - - bool is_user_script_frame (void) const { return true; } - - static std::shared_ptr - get_access_link (const std::shared_ptr& static_link); - - static std::size_t get_num_symbols (octave_user_script *script); - - void set_script_offsets (void); - - void set_script_offsets_internal (const std::map& symbols); - - void resize_and_update_script_offsets (const symbol_record& sym); - - symbol_scope get_scope (void) const { return m_script->scope (); } - - octave_function * function (void) const { return m_script; } - - unwind_protect * unwind_protect_frame (void); - - symbol_record lookup_symbol (const std::string& name) const; - - symbol_record insert_symbol (const std::string&); - - std::size_t size (void) const { return m_lexical_frame_offsets.size (); } - - void resize (std::size_t size) - { - m_lexical_frame_offsets.resize (size, 0); - m_value_offsets.resize (size, 0); - } - - void get_val_offsets_with_insert (const symbol_record& sym, - std::size_t& frame_offset, - std::size_t& data_offset); - - bool get_val_offsets_internal (const symbol_record& sym, - std::size_t& frame_offset, - std::size_t& data_offset) const; - - bool get_val_offsets (const symbol_record& sym, std::size_t& frame_offset, - std::size_t& data_offset) const; - - scope_flags scope_flag (const symbol_record& sym) const; - - void set_auto_fcn_var (auto_var_type avt, const octave_value& val) - { - m_access_link->set_auto_fcn_var (avt, val); - } - - octave_value get_auto_fcn_var (auto_var_type avt) const - { - return m_access_link->get_auto_fcn_var (avt); - } - - // We only need to override one of each of these functions. The - // using declaration will avoid warnings about partially-overloaded - // virtual functions. - using stack_frame::varval; - using stack_frame::varref; - - octave_value varval (const symbol_record& sym) const; - - octave_value& varref (const symbol_record& sym); - - void mark_scope (const symbol_record& sym, scope_flags flag); - - void display (bool follow = true) const; - - void accept (stack_frame_walker& sfw); - - private: - - // Script object associated with this stack frame. Should always - // be valid. - octave_user_script *m_script; - - // The nearest unwind protect frame that was active when this - // stack frame was created. Should always be valid. - unwind_protect *m_unwind_protect_frame; - - // Mapping between the symbols in the symbol_scope object of the - // script to the stack frame in which the script is executed. The - // frame offsets may be greater than one if the script is executed - // in a nested function context. - - std::vector m_lexical_frame_offsets; - std::vector m_value_offsets; - }; - - // Base class for values and offsets shared by user_fcn and scope - // frames. - - class base_value_stack_frame : public stack_frame - { - public: - - base_value_stack_frame (void) = delete; - - base_value_stack_frame (tree_evaluator& tw, std::size_t num_symbols, +class compiled_fcn_stack_frame : public stack_frame +{ +public: + + compiled_fcn_stack_frame (void) = delete; + + compiled_fcn_stack_frame (tree_evaluator& tw, octave_function *fcn, std::size_t index, const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const std::shared_ptr& access_link) - : stack_frame (tw, index, parent_link, static_link, access_link), - m_values (num_symbols, octave_value ()), - m_flags (num_symbols, LOCAL), - m_auto_vars (NUM_AUTO_VARS, octave_value ()) - { } - - base_value_stack_frame (const base_value_stack_frame& elt) = default; - - base_value_stack_frame& - operator = (const base_value_stack_frame& elt) = delete; - - ~base_value_stack_frame (void) = default; - - std::size_t size (void) const - { - return m_values.size (); - } - - void resize (std::size_t size) - { - m_values.resize (size, octave_value ()); - m_flags.resize (size, LOCAL); - } - - stack_frame::scope_flags get_scope_flag (std::size_t data_offset) const - { - return m_flags.at (data_offset); - } - - void set_scope_flag (std::size_t data_offset, scope_flags flag) - { - m_flags.at (data_offset) = flag; - } - - octave_value get_auto_fcn_var (auto_var_type avt) const - { - return m_auto_vars.at (avt); - } - - void set_auto_fcn_var (auto_var_type avt, const octave_value& val) - { - m_auto_vars.at (avt) = val; - } - - // We only need to override one of each of these functions. The - // using declaration will avoid warnings about partially-overloaded - // virtual functions. - using stack_frame::varval; - using stack_frame::varref; - - octave_value varval (std::size_t data_offset) const - { - return m_values.at (data_offset); - } - - octave_value& varref (std::size_t data_offset) - { - return m_values.at (data_offset); - } - - void display (bool follow = true) const; - - protected: - - // Variable values. This array is indexed by the data_offset - // value stored in the symbol_record objects of the scope - // associated with this stack frame. - std::vector m_values; - - // The type of each variable (local, global, persistent) of each - // value. This array is indexed by the data_offset value stored - // in the symbol_record objects of the scope associated with this - // stack frame. Local values are found in the M_VALUES array. - // Global values are stored in the tree_evaluator object that contains - // the stack frame. Persistent values are stored in the function - // scope corresponding to the stack frame. - std::vector m_flags; - - // A fixed list of Automatic variables created for this function. - // The elements of this vector correspond to the auto_var_type - // enum. - std::vector m_auto_vars; - }; - - // User-defined functions have a symbol_scope object to store the set - // of variables in the function and values are stored in the stack - // frame corresponding to the invocation of the function or one of - // its parents. The frame offset tells us how many access links we - // must follow to find the stack frame that holds the value. The - // value offset is the index into the vector of values in that stack - // frame that we should use to find the value. - // - // Frame and value offsets are determined when the corresponding - // function is parsed. - - class user_fcn_stack_frame : public base_value_stack_frame + const std::shared_ptr& static_link) + : stack_frame (tw, index, parent_link, static_link, + static_link->access_link ()), + m_fcn (fcn) + { } + + compiled_fcn_stack_frame (const compiled_fcn_stack_frame& elt) = default; + + compiled_fcn_stack_frame& + operator = (const compiled_fcn_stack_frame& elt) = delete; + + ~compiled_fcn_stack_frame (void) = default; + + bool is_compiled_fcn_frame (void) const { return true; } + + symbol_scope get_scope (void) const + { + return m_static_link->get_scope (); + } + + octave_function * function (void) const { return m_fcn; } + + symbol_record lookup_symbol (const std::string& name) const + { + return m_static_link->lookup_symbol (name); + } + + symbol_record insert_symbol (const std::string& name) + { + return m_static_link->insert_symbol (name); + } + + stack_frame::scope_flags scope_flag (const symbol_record& sym) const + { + // Look in closest stack frame that contains values (either the + // top scope, or a user-defined function or script). + + return m_static_link->scope_flag (sym); + } + + void set_auto_fcn_var (auto_var_type avt, const octave_value& val) + { + m_static_link->set_auto_fcn_var (avt, val); + } + + octave_value get_auto_fcn_var (auto_var_type avt) const + { + return m_static_link->get_auto_fcn_var (avt); + } + + // We only need to override one of each of these functions. The + // using declaration will avoid warnings about partially-overloaded + // virtual functions. + using stack_frame::varval; + using stack_frame::varref; + + octave_value varval (const symbol_record& sym) const + { + // Look in closest stack frame that contains values (either the + // top scope, or a user-defined function or script). + + return m_static_link->varval (sym); + } + + octave_value& varref (const symbol_record& sym) + { + // Look in closest stack frame that contains values (either the + // top scope, or a user-defined function or script). + + return m_static_link->varref (sym); + } + + void mark_scope (const symbol_record& sym, scope_flags flag) { - public: - - user_fcn_stack_frame (void) = delete; - - user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, + // Look in closest stack frame that contains values (either the + // top scope, or a user-defined function or script). + + m_static_link->mark_scope (sym, flag); + } + + void display (bool follow = true) const; + + void accept (stack_frame_walker& sfw); + +private: + + // Compiled function object associated with this stack frame. + // Should always be a built-in, .oct or .mex file function and + // should always be valid. + octave_function *m_fcn; +}; + +// Scripts have a symbol_scope object to store the set of variables +// in the script, but values for those variables are stored in the +// stack frame corresponding to the nearest calling function or in +// the top-level scope (the evaluation stack frame). +// +// Accessing values in a scope requires a mapping from the index of +// the variable for the script scope to the list of values in the +// evaluation frame(s). The frame offset tells us how many access +// links we must follow to find the stack frame that holds the +// value. The value offset is the index into the vector of values +// in that stack frame that we should use to find the value. +// +// Frame and value offsets are set in this stack frame when it is +// created using information from the script and enclosing scopes. +// +// If a script is invoked in a nested function context, the frame +// offsets for individual values may be different. Some may be +// accessed from the invoking function and some may come from a +// parent function. + +class script_stack_frame : public stack_frame +{ +public: + + script_stack_frame (void) = delete; + + script_stack_frame (tree_evaluator& tw, octave_user_script *script, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link); + + script_stack_frame (const script_stack_frame& elt) = default; + + script_stack_frame& operator = (const script_stack_frame& elt) = delete; + + ~script_stack_frame (void) + { + delete m_unwind_protect_frame; + } + + bool is_user_script_frame (void) const { return true; } + + static std::shared_ptr + get_access_link (const std::shared_ptr& static_link); + + static std::size_t get_num_symbols (octave_user_script *script); + + void set_script_offsets (void); + + void set_script_offsets_internal (const std::map& symbols); + + void resize_and_update_script_offsets (const symbol_record& sym); + + symbol_scope get_scope (void) const { return m_script->scope (); } + + octave_function * function (void) const { return m_script; } + + unwind_protect * unwind_protect_frame (void); + + symbol_record lookup_symbol (const std::string& name) const; + + symbol_record insert_symbol (const std::string&); + + std::size_t size (void) const { return m_lexical_frame_offsets.size (); } + + void resize (std::size_t size) + { + m_lexical_frame_offsets.resize (size, 0); + m_value_offsets.resize (size, 0); + } + + void get_val_offsets_with_insert (const symbol_record& sym, + std::size_t& frame_offset, + std::size_t& data_offset); + + bool get_val_offsets_internal (const symbol_record& sym, + std::size_t& frame_offset, + std::size_t& data_offset) const; + + bool get_val_offsets (const symbol_record& sym, std::size_t& frame_offset, + std::size_t& data_offset) const; + + scope_flags scope_flag (const symbol_record& sym) const; + + void set_auto_fcn_var (auto_var_type avt, const octave_value& val) + { + m_access_link->set_auto_fcn_var (avt, val); + } + + octave_value get_auto_fcn_var (auto_var_type avt) const + { + return m_access_link->get_auto_fcn_var (avt); + } + + // We only need to override one of each of these functions. The + // using declaration will avoid warnings about partially-overloaded + // virtual functions. + using stack_frame::varval; + using stack_frame::varref; + + octave_value varval (const symbol_record& sym) const; + + octave_value& varref (const symbol_record& sym); + + void mark_scope (const symbol_record& sym, scope_flags flag); + + void display (bool follow = true) const; + + void accept (stack_frame_walker& sfw); + +private: + + // Script object associated with this stack frame. Should always + // be valid. + octave_user_script *m_script; + + // The nearest unwind protect frame that was active when this + // stack frame was created. Should always be valid. + unwind_protect *m_unwind_protect_frame; + + // Mapping between the symbols in the symbol_scope object of the + // script to the stack frame in which the script is executed. The + // frame offsets may be greater than one if the script is executed + // in a nested function context. + + std::vector m_lexical_frame_offsets; + std::vector m_value_offsets; +}; + +// Base class for values and offsets shared by user_fcn and scope +// frames. + +class base_value_stack_frame : public stack_frame +{ +public: + + base_value_stack_frame (void) = delete; + + base_value_stack_frame (tree_evaluator& tw, std::size_t num_symbols, std::size_t index, const std::shared_ptr& parent_link, const std::shared_ptr& static_link, - const std::shared_ptr& access_link = std::shared_ptr ()) - : base_value_stack_frame (tw, get_num_symbols (fcn), index, - parent_link, static_link, - (access_link - ? access_link - : get_access_link (fcn, static_link))), - m_fcn (fcn), m_unwind_protect_frame (nullptr) - { } - - user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const local_vars_map& local_vars, - const std::shared_ptr& access_link = std::shared_ptr ()) - : base_value_stack_frame (tw, get_num_symbols (fcn), index, - parent_link, static_link, - (access_link - ? access_link - : get_access_link (fcn, static_link))), - m_fcn (fcn), m_unwind_protect_frame (nullptr) + const std::shared_ptr& access_link) + : stack_frame (tw, index, parent_link, static_link, access_link), + m_values (num_symbols, octave_value ()), + m_flags (num_symbols, LOCAL), + m_auto_vars (NUM_AUTO_VARS, octave_value ()) + { } + + base_value_stack_frame (const base_value_stack_frame& elt) = default; + + base_value_stack_frame& + operator = (const base_value_stack_frame& elt) = delete; + + ~base_value_stack_frame (void) = default; + + std::size_t size (void) const + { + return m_values.size (); + } + + void resize (std::size_t size) + { + m_values.resize (size, octave_value ()); + m_flags.resize (size, LOCAL); + } + + stack_frame::scope_flags get_scope_flag (std::size_t data_offset) const + { + return m_flags.at (data_offset); + } + + void set_scope_flag (std::size_t data_offset, scope_flags flag) + { + m_flags.at (data_offset) = flag; + } + + octave_value get_auto_fcn_var (auto_var_type avt) const + { + return m_auto_vars.at (avt); + } + + void set_auto_fcn_var (auto_var_type avt, const octave_value& val) + { + m_auto_vars.at (avt) = val; + } + + // We only need to override one of each of these functions. The + // using declaration will avoid warnings about partially-overloaded + // virtual functions. + using stack_frame::varval; + using stack_frame::varref; + + octave_value varval (std::size_t data_offset) const + { + return m_values.at (data_offset); + } + + octave_value& varref (std::size_t data_offset) + { + return m_values.at (data_offset); + } + + void display (bool follow = true) const; + +protected: + + // Variable values. This array is indexed by the data_offset + // value stored in the symbol_record objects of the scope + // associated with this stack frame. + std::vector m_values; + + // The type of each variable (local, global, persistent) of each + // value. This array is indexed by the data_offset value stored + // in the symbol_record objects of the scope associated with this + // stack frame. Local values are found in the M_VALUES array. + // Global values are stored in the tree_evaluator object that contains + // the stack frame. Persistent values are stored in the function + // scope corresponding to the stack frame. + std::vector m_flags; + + // A fixed list of Automatic variables created for this function. + // The elements of this vector correspond to the auto_var_type + // enum. + std::vector m_auto_vars; +}; + +// User-defined functions have a symbol_scope object to store the set +// of variables in the function and values are stored in the stack +// frame corresponding to the invocation of the function or one of +// its parents. The frame offset tells us how many access links we +// must follow to find the stack frame that holds the value. The +// value offset is the index into the vector of values in that stack +// frame that we should use to find the value. +// +// Frame and value offsets are determined when the corresponding +// function is parsed. + +class user_fcn_stack_frame : public base_value_stack_frame +{ +public: + + user_fcn_stack_frame (void) = delete; + + user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const std::shared_ptr& access_link = std::shared_ptr ()) + : base_value_stack_frame (tw, get_num_symbols (fcn), index, + parent_link, static_link, + (access_link + ? access_link + : get_access_link (fcn, static_link))), + m_fcn (fcn), m_unwind_protect_frame (nullptr) + { } + + user_fcn_stack_frame (tree_evaluator& tw, octave_user_function *fcn, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const local_vars_map& local_vars, + const std::shared_ptr& access_link = std::shared_ptr ()) + : base_value_stack_frame (tw, get_num_symbols (fcn), index, + parent_link, static_link, + (access_link + ? access_link + : get_access_link (fcn, static_link))), + m_fcn (fcn), m_unwind_protect_frame (nullptr) + { + // Initialize local variable values. + + for (const auto& nm_ov : local_vars) + assign (nm_ov.first, nm_ov.second); + } + + user_fcn_stack_frame (const user_fcn_stack_frame& elt) = default; + + user_fcn_stack_frame& + operator = (const user_fcn_stack_frame& elt) = delete; + + ~user_fcn_stack_frame (void) + { + delete m_unwind_protect_frame; + } + + bool is_user_fcn_frame (void) const { return true; } + + static std::shared_ptr + get_access_link (octave_user_function *fcn, + const std::shared_ptr& static_link); + + static std::size_t get_num_symbols (octave_user_function *fcn) + { + symbol_scope fcn_scope = fcn->scope (); + + return fcn_scope.num_symbols (); + } + + void clear_values (void); + + symbol_scope get_scope (void) const { return m_fcn->scope (); } + + octave_function * function (void) const { return m_fcn; } + + unwind_protect * unwind_protect_frame (void); + + symbol_record lookup_symbol (const std::string& name) const; + + symbol_record insert_symbol (const std::string&); + + scope_flags scope_flag (const symbol_record& sym) const; + + // We only need to override one of each of these functions. The + // using declaration will avoid warnings about partially-overloaded + // virtual functions. + using base_value_stack_frame::varval; + using base_value_stack_frame::varref; + + octave_value varval (const symbol_record& sym) const; + + octave_value& varref (const symbol_record& sym); + + void mark_scope (const symbol_record& sym, scope_flags flag); + + void display (bool follow = true) const; + + void accept (stack_frame_walker& sfw); + + void break_closure_cycles (const std::shared_ptr& frame); + +private: + + // User-defined object associated with this stack frame. Should + // always be valid. + octave_user_function *m_fcn; + + // The nearest unwind protect frame that was active when this + // stack frame was created. Should always be valid. + unwind_protect *m_unwind_protect_frame; +}; + +// Pure scope stack frames (primarily the top-level workspace) have +// a set of variables and values are stored in the stack frame. All +// variable accesses are direct as there are no parent stack frames. +// +// Value offsets are determined when the corresponding variable is +// entered into the symbol_scope object corresponding to the frame. + +class scope_stack_frame : public base_value_stack_frame +{ +public: + + scope_stack_frame (void) = delete; + + scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link) + : base_value_stack_frame (tw, scope.num_symbols (), index, + parent_link, static_link, nullptr), + m_scope (scope) + { } + + scope_stack_frame (const scope_stack_frame& elt) = default; + + scope_stack_frame& operator = (const scope_stack_frame& elt) = delete; + + ~scope_stack_frame (void) = default; + + bool is_scope_frame (void) const { return true; } + + symbol_scope get_scope (void) const { return m_scope; } + + symbol_record lookup_symbol (const std::string& name) const + { + return m_scope.lookup_symbol (name); + } + + symbol_record insert_symbol (const std::string&); + + scope_flags scope_flag (const symbol_record& sym) const; + + // We only need to override one of each of these functions. The + // using declaration will avoid warnings about partially-overloaded + // virtual functions. + using base_value_stack_frame::varval; + using base_value_stack_frame::varref; + + octave_value varval (const symbol_record& sym) const; + + octave_value& varref (const symbol_record& sym); + + void mark_scope (const symbol_record& sym, scope_flags flag); + + void display (bool follow = true) const; + + void accept (stack_frame_walker& sfw); + +private: + + // The scope object associated with this stack frame. + symbol_scope m_scope; +}; + +// FIXME: There should probably be a display method for the script, +// fcn, and scope objects and the script and function objects should +// be responsible for displaying the scopes they contain. + +static void display_scope (std::ostream& os, const symbol_scope& scope) +{ + if (scope) { - // Initialize local variable values. - - for (const auto& nm_ov : local_vars) - assign (nm_ov.first, nm_ov.second); - } - - user_fcn_stack_frame (const user_fcn_stack_frame& elt) = default; - - user_fcn_stack_frame& - operator = (const user_fcn_stack_frame& elt) = delete; - - ~user_fcn_stack_frame (void) - { - delete m_unwind_protect_frame; - } - - bool is_user_fcn_frame (void) const { return true; } - - static std::shared_ptr - get_access_link (octave_user_function *fcn, - const std::shared_ptr& static_link); - - static std::size_t get_num_symbols (octave_user_function *fcn) - { - symbol_scope fcn_scope = fcn->scope (); - - return fcn_scope.num_symbols (); + os << "scope: " << scope.name () << std::endl; + + if (scope.num_symbols () > 0) + { + os << "name (frame offset, data offset, storage class):" + << std::endl; + + std::list symbols = scope.symbol_list (); + + for (auto& sym : symbols) + { + os << " " << sym.name () << " (" << sym.frame_offset () + << ", " << sym.data_offset () << ", " << sym.storage_class () + << ")" << std::endl; + } + } } - - void clear_values (void); - - symbol_scope get_scope (void) const { return m_fcn->scope (); } - - octave_function * function (void) const { return m_fcn; } - - unwind_protect * unwind_protect_frame (void); - - symbol_record lookup_symbol (const std::string& name) const; - - symbol_record insert_symbol (const std::string&); - - scope_flags scope_flag (const symbol_record& sym) const; - - // We only need to override one of each of these functions. The - // using declaration will avoid warnings about partially-overloaded - // virtual functions. - using base_value_stack_frame::varval; - using base_value_stack_frame::varref; - - octave_value varval (const symbol_record& sym) const; - - octave_value& varref (const symbol_record& sym); - - void mark_scope (const symbol_record& sym, scope_flags flag); - - void display (bool follow = true) const; - - void accept (stack_frame_walker& sfw); - - void break_closure_cycles (const std::shared_ptr& frame); - - private: - - // User-defined object associated with this stack frame. Should - // always be valid. - octave_user_function *m_fcn; - - // The nearest unwind protect frame that was active when this - // stack frame was created. Should always be valid. - unwind_protect *m_unwind_protect_frame; - }; - - // Pure scope stack frames (primarily the top-level workspace) have - // a set of variables and values are stored in the stack frame. All - // variable accesses are direct as there are no parent stack frames. - // - // Value offsets are determined when the corresponding variable is - // entered into the symbol_scope object corresponding to the frame. - - class scope_stack_frame : public base_value_stack_frame +} + +class stack_frame_walker +{ +protected: + + stack_frame_walker (void) { } + + virtual ~stack_frame_walker (void) = default; + +public: + + // No copying! + + stack_frame_walker (const stack_frame_walker&) = delete; + + stack_frame_walker& operator = (const stack_frame_walker&) = delete; + + virtual void + visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame&) = 0; + + virtual void + visit_script_stack_frame (script_stack_frame&) = 0; + + virtual void + visit_user_fcn_stack_frame (user_fcn_stack_frame&) = 0; + + virtual void + visit_scope_stack_frame (scope_stack_frame&) = 0; +}; + +class symbol_cleaner : public stack_frame_walker +{ +public: + + symbol_cleaner (const std::string& pattern, bool have_regexp = false) + : stack_frame_walker (), m_patterns (pattern), + m_clear_all_names (false), m_clear_objects (false), + m_have_regexp (have_regexp), m_cleared_names () + { } + + symbol_cleaner (const string_vector& patterns, bool have_regexp = false) + : stack_frame_walker (), m_patterns (patterns), + m_clear_all_names (false), m_clear_objects (false), + m_have_regexp (have_regexp), m_cleared_names () + { } + + symbol_cleaner (bool clear_all_names = true, bool clear_objects = false) + : stack_frame_walker (), m_patterns (), + m_clear_all_names (clear_all_names), m_clear_objects (clear_objects), + m_have_regexp (false), m_cleared_names () + { } + + symbol_cleaner (const symbol_cleaner&) = delete; + + symbol_cleaner& operator = (const symbol_cleaner&) = delete; + + ~symbol_cleaner (void) = default; + + void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame) + { + // This one follows static link always. Hmm, should the access + // link for a compiled_fcn_stack_frame be the same as the static + // link? + + std::shared_ptr slink = frame.static_link (); + + if (slink) + slink->accept (*this); + } + + void visit_script_stack_frame (script_stack_frame& frame) + { + std::shared_ptr alink = frame.access_link (); + + if (alink) + alink->accept (*this); + } + + void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame) { - public: - - scope_stack_frame (void) = delete; - - scope_stack_frame (tree_evaluator& tw, const symbol_scope& scope, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link) - : base_value_stack_frame (tw, scope.num_symbols (), index, - parent_link, static_link, nullptr), - m_scope (scope) - { } - - scope_stack_frame (const scope_stack_frame& elt) = default; - - scope_stack_frame& operator = (const scope_stack_frame& elt) = delete; - - ~scope_stack_frame (void) = default; - - bool is_scope_frame (void) const { return true; } - - symbol_scope get_scope (void) const { return m_scope; } - - symbol_record lookup_symbol (const std::string& name) const - { - return m_scope.lookup_symbol (name); - } - - symbol_record insert_symbol (const std::string&); - - scope_flags scope_flag (const symbol_record& sym) const; - - // We only need to override one of each of these functions. The - // using declaration will avoid warnings about partially-overloaded - // virtual functions. - using base_value_stack_frame::varval; - using base_value_stack_frame::varref; - - octave_value varval (const symbol_record& sym) const; - - octave_value& varref (const symbol_record& sym); - - void mark_scope (const symbol_record& sym, scope_flags flag); - - void display (bool follow = true) const; - - void accept (stack_frame_walker& sfw); - - private: - - // The scope object associated with this stack frame. - symbol_scope m_scope; - }; - - // FIXME: There should probably be a display method for the script, - // fcn, and scope objects and the script and function objects should - // be responsible for displaying the scopes they contain. - - static void display_scope (std::ostream& os, const symbol_scope& scope) + clean_frame (frame); + + std::shared_ptr alink = frame.access_link (); + + if (alink) + alink->accept (*this); + } + + void visit_scope_stack_frame (scope_stack_frame& frame) + { + clean_frame (frame); + + std::shared_ptr alink = frame.access_link (); + + if (alink) + alink->accept (*this); + } + +private: + + void maybe_clear_symbol (stack_frame& frame, const symbol_record& sym) { - if (scope) + std::string name = sym.name (); + + if (m_cleared_names.find (name) == m_cleared_names.end ()) { - os << "scope: " << scope.name () << std::endl; - - if (scope.num_symbols () > 0) + // FIXME: Should we check that the name is defined and skip if + // it is not? Is it possible for another symbol with the same + // name to appear in a later stack frame? + + // FIXME: If we are clearing objects and a symbol is found, + // should we add it to the list of cleared names (since + // we did find a symbol) but skip clearing the object? + + if (m_clear_objects && ! frame.is_object (sym)) + return; + + m_cleared_names.insert (name); + + frame.clear (sym); + } + } + + // FIXME: It would be nice to avoid the duplication in the following + // function. + + void clear_symbols (stack_frame& frame, + const std::list& symbols) + { + if (m_clear_all_names) + { + for (const auto& sym : symbols) + maybe_clear_symbol (frame, sym); + } + else if (m_have_regexp) + { + octave_idx_type npatterns = m_patterns.numel (); + + for (octave_idx_type j = 0; j < npatterns; j++) { - os << "name (frame offset, data offset, storage class):" - << std::endl; - - std::list symbols = scope.symbol_list (); - - for (auto& sym : symbols) + std::string pattern = m_patterns[j]; + + regexp pat (pattern); + + for (const auto& sym : symbols) { - os << " " << sym.name () << " (" << sym.frame_offset () - << ", " << sym.data_offset () << ", " << sym.storage_class () - << ")" << std::endl; + if (pat.is_match (sym.name ())) + maybe_clear_symbol (frame, sym); + } + } + } + else + { + octave_idx_type npatterns = m_patterns.numel (); + + for (octave_idx_type j = 0; j < npatterns; j++) + { + std::string pattern = m_patterns[j]; + + glob_match pat (pattern); + + for (const auto& sym : symbols) + { + if (pat.match (sym.name ())) + maybe_clear_symbol (frame, sym); } } } } - class stack_frame_walker - { - protected: - - stack_frame_walker (void) { } - - virtual ~stack_frame_walker (void) = default; - - public: - - // No copying! - - stack_frame_walker (const stack_frame_walker&) = delete; - - stack_frame_walker& operator = (const stack_frame_walker&) = delete; - - virtual void - visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame&) = 0; - - virtual void - visit_script_stack_frame (script_stack_frame&) = 0; - - virtual void - visit_user_fcn_stack_frame (user_fcn_stack_frame&) = 0; - - virtual void - visit_scope_stack_frame (scope_stack_frame&) = 0; - }; - - class symbol_cleaner : public stack_frame_walker - { - public: - - symbol_cleaner (const std::string& pattern, bool have_regexp = false) - : stack_frame_walker (), m_patterns (pattern), - m_clear_all_names (false), m_clear_objects (false), - m_have_regexp (have_regexp), m_cleared_names () - { } - - symbol_cleaner (const string_vector& patterns, bool have_regexp = false) - : stack_frame_walker (), m_patterns (patterns), - m_clear_all_names (false), m_clear_objects (false), - m_have_regexp (have_regexp), m_cleared_names () - { } - - symbol_cleaner (bool clear_all_names = true, bool clear_objects = false) - : stack_frame_walker (), m_patterns (), - m_clear_all_names (clear_all_names), m_clear_objects (clear_objects), - m_have_regexp (false), m_cleared_names () - { } - - symbol_cleaner (const symbol_cleaner&) = delete; - - symbol_cleaner& operator = (const symbol_cleaner&) = delete; - - ~symbol_cleaner (void) = default; - - void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame) - { - // This one follows static link always. Hmm, should the access - // link for a compiled_fcn_stack_frame be the same as the static - // link? - - std::shared_ptr slink = frame.static_link (); - - if (slink) - slink->accept (*this); - } - - void visit_script_stack_frame (script_stack_frame& frame) - { - std::shared_ptr alink = frame.access_link (); - - if (alink) - alink->accept (*this); - } - - void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame) - { - clean_frame (frame); - - std::shared_ptr alink = frame.access_link (); - - if (alink) - alink->accept (*this); - } - - void visit_scope_stack_frame (scope_stack_frame& frame) - { - clean_frame (frame); - - std::shared_ptr alink = frame.access_link (); - - if (alink) - alink->accept (*this); - } - - private: - - void maybe_clear_symbol (stack_frame& frame, const symbol_record& sym) - { - std::string name = sym.name (); - - if (m_cleared_names.find (name) == m_cleared_names.end ()) - { - // FIXME: Should we check that the name is defined and skip if - // it is not? Is it possible for another symbol with the same - // name to appear in a later stack frame? - - // FIXME: If we are clearing objects and a symbol is found, - // should we add it to the list of cleared names (since - // we did find a symbol) but skip clearing the object? - - if (m_clear_objects && ! frame.is_object (sym)) - return; - - m_cleared_names.insert (name); - - frame.clear (sym); - } - } - - // FIXME: It would be nice to avoid the duplication in the following - // function. - - void clear_symbols (stack_frame& frame, - const std::list& symbols) - { - if (m_clear_all_names) - { - for (const auto& sym : symbols) - maybe_clear_symbol (frame, sym); - } - else if (m_have_regexp) - { - octave_idx_type npatterns = m_patterns.numel (); - - for (octave_idx_type j = 0; j < npatterns; j++) - { - std::string pattern = m_patterns[j]; - - regexp pat (pattern); - - for (const auto& sym : symbols) - { - if (pat.is_match (sym.name ())) - maybe_clear_symbol (frame, sym); - } - } - } - else - { - octave_idx_type npatterns = m_patterns.numel (); - - for (octave_idx_type j = 0; j < npatterns; j++) - { - std::string pattern = m_patterns[j]; - - glob_match pat (pattern); - - for (const auto& sym : symbols) - { - if (pat.match (sym.name ())) - maybe_clear_symbol (frame, sym); - } - } - } - } - - void clean_frame (stack_frame& frame) - { - symbol_scope scope = frame.get_scope (); - - std::list symbols = scope.symbol_list (); - - if (m_clear_all_names || ! m_patterns.empty ()) - clear_symbols (frame, symbols); - } - - string_vector m_patterns; - - bool m_clear_all_names; - bool m_clear_objects; - bool m_have_regexp; - - std::set m_cleared_names; - }; - - class symbol_info_accumulator : public stack_frame_walker + void clean_frame (stack_frame& frame) { - public: - - symbol_info_accumulator (const std::string& pattern, - bool have_regexp = false) - : stack_frame_walker (), m_patterns (pattern), m_match_all (false), - m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (), - m_found_names () - { } - - symbol_info_accumulator (const string_vector& patterns, - bool have_regexp = false) - : stack_frame_walker (), m_patterns (patterns), m_match_all (false), - m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (), - m_found_names () - { } - - symbol_info_accumulator (bool match_all = true, bool first_only = true) - : stack_frame_walker (), m_patterns (), m_match_all (match_all), - m_first_only (first_only), m_have_regexp (false), - m_sym_inf_list (), m_found_names () - { } - - symbol_info_accumulator (const symbol_info_accumulator&) = delete; - - symbol_info_accumulator& operator = (const symbol_info_accumulator&) = delete; - - ~symbol_info_accumulator (void) = default; - - bool is_empty (void) const - { - for (const auto& nm_sil : m_sym_inf_list) - { - const symbol_info_list& lst = nm_sil.second; - - if (! lst.empty ()) - return false; - } - - return true; - } - - std::list names (void) const - { - std::list retval; - - for (const auto& nm_sil : m_sym_inf_list) - { - const symbol_info_list& lst = nm_sil.second; - - std::list nm_list = lst.names (); - - for (const auto& nm : nm_list) - retval.push_back (nm); - } - - return retval; - } - - symbol_info_list symbol_info (void) const - { - symbol_info_list retval; - - for (const auto& nm_sil : m_sym_inf_list) - { - const symbol_info_list& lst = nm_sil.second; - - for (const auto& syminf : lst) - retval.push_back (syminf); - } - - return retval; - } - - octave_map map_value (void) const - { - octave_map retval; - - // FIXME: is there a better way to concatenate structures? - - std::size_t n_frames = m_sym_inf_list.size (); - - OCTAVE_LOCAL_BUFFER (octave_map, map_list, n_frames); - - std::size_t j = 0; - for (const auto& nm_sil : m_sym_inf_list) - { - std::string scope_name = nm_sil.first; - const symbol_info_list& lst = nm_sil.second; - - map_list[j] = lst.map_value (scope_name, n_frames-j); - - j++; - } - - return octave_map::cat (-1, n_frames, map_list); - } - - void display (std::ostream& os, const std::string& format) const - { - for (const auto& nm_sil : m_sym_inf_list) - { - os << "\nvariables in scope: " << nm_sil.first << "\n\n"; - - const symbol_info_list& lst = nm_sil.second; - - lst.display (os, format); - } - } - - void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame) - { - // This one follows static link always. Hmm, should the access - // link for a compiled_fcn_stack_frame be the same as the static - // link? - - std::shared_ptr slink = frame.static_link (); - - if (slink) - slink->accept (*this); - } - - void visit_script_stack_frame (script_stack_frame& frame) - { - std::shared_ptr alink = frame.access_link (); - - if (alink) - alink->accept (*this); - } - - void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame) - { - append_list (frame); - - std::shared_ptr alink = frame.access_link (); - - if (alink) - alink->accept (*this); - } - - void visit_scope_stack_frame (scope_stack_frame& frame) - { - append_list (frame); - - std::shared_ptr alink = frame.access_link (); - - if (alink) - alink->accept (*this); - } - - private: - - typedef std::pair syminf_list_elt; - - // FIXME: the following is too complex and duplicates too much - // code. Maybe it should be split up so we have separate classes - // that do each job that is needed? - - std::list - filter (stack_frame& frame, const std::list& symbols) - { - std::list new_symbols; - - if (m_match_all) - { - for (const auto& sym : symbols) - { - if (frame.is_defined (sym)) - { - std::string name = sym.name (); - - if (m_first_only - && m_found_names.find (name) != m_found_names.end ()) - continue; - - m_found_names.insert (name); - - new_symbols.push_back (sym); - } - } - } - else if (m_have_regexp) - { - octave_idx_type npatterns = m_patterns.numel (); - - for (octave_idx_type j = 0; j < npatterns; j++) - { - std::string pattern = m_patterns[j]; - - regexp pat (pattern); - - for (const auto& sym : symbols) - { - std::string name = sym.name (); - - if (pat.is_match (name) && frame.is_defined (sym)) - { - if (m_first_only - && m_found_names.find (name) != m_found_names.end ()) - continue; - - m_found_names.insert (name); - - new_symbols.push_back (sym); - } - } - } - } - else - { - octave_idx_type npatterns = m_patterns.numel (); - - for (octave_idx_type j = 0; j < npatterns; j++) - { - std::string pattern = m_patterns[j]; - - glob_match pat (pattern); - - for (const auto& sym : symbols) - { - std::string name = sym.name (); - - if (pat.match (name) && frame.is_defined (sym)) - { - if (m_first_only - && m_found_names.find (name) == m_found_names.end ()) - continue; - - m_found_names.insert (name); - - new_symbols.push_back (sym); - } - } - } - } - - return new_symbols; - } - - void append_list (stack_frame& frame) - { - symbol_scope scope = frame.get_scope (); - - std::list symbols = scope.symbol_list (); - - if (m_match_all || ! m_patterns.empty ()) - symbols = filter (frame, symbols); - - symbol_info_list syminf_list = frame.make_symbol_info_list (symbols); - - m_sym_inf_list.push_back (syminf_list_elt (scope.name (), syminf_list)); - } - - string_vector m_patterns; - - bool m_match_all; - bool m_first_only; - bool m_have_regexp; - - std::list> m_sym_inf_list; - - std::set m_found_names; - }; - - stack_frame * stack_frame::create (tree_evaluator& tw, octave_function *fcn, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link) + symbol_scope scope = frame.get_scope (); + + std::list symbols = scope.symbol_list (); + + if (m_clear_all_names || ! m_patterns.empty ()) + clear_symbols (frame, symbols); + } + + string_vector m_patterns; + + bool m_clear_all_names; + bool m_clear_objects; + bool m_have_regexp; + + std::set m_cleared_names; +}; + +class symbol_info_accumulator : public stack_frame_walker +{ +public: + + symbol_info_accumulator (const std::string& pattern, + bool have_regexp = false) + : stack_frame_walker (), m_patterns (pattern), m_match_all (false), + m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (), + m_found_names () + { } + + symbol_info_accumulator (const string_vector& patterns, + bool have_regexp = false) + : stack_frame_walker (), m_patterns (patterns), m_match_all (false), + m_first_only (false), m_have_regexp (have_regexp), m_sym_inf_list (), + m_found_names () + { } + + symbol_info_accumulator (bool match_all = true, bool first_only = true) + : stack_frame_walker (), m_patterns (), m_match_all (match_all), + m_first_only (first_only), m_have_regexp (false), + m_sym_inf_list (), m_found_names () + { } + + symbol_info_accumulator (const symbol_info_accumulator&) = delete; + + symbol_info_accumulator& operator = (const symbol_info_accumulator&) = delete; + + ~symbol_info_accumulator (void) = default; + + bool is_empty (void) const { - return new compiled_fcn_stack_frame (tw, fcn, index, - parent_link, static_link); - } - - stack_frame * stack_frame::create (tree_evaluator& tw, - octave_user_script *script, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link) - { - return new script_stack_frame (tw, script, index, parent_link, static_link); - } - - stack_frame * stack_frame::create (tree_evaluator& tw, - octave_user_function *fcn, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const std::shared_ptr& access_link) - { - return new user_fcn_stack_frame (tw, fcn, index, - parent_link, static_link, access_link); - } - - stack_frame * stack_frame::create (tree_evaluator& tw, - octave_user_function *fcn, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const local_vars_map& local_vars, - const std::shared_ptr& access_link) - { - return new user_fcn_stack_frame (tw, fcn, index, - parent_link, static_link, local_vars, - access_link); - } - - stack_frame * stack_frame::create (tree_evaluator& tw, - const symbol_scope& scope, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link) - { - return new scope_stack_frame (tw, scope, index, parent_link, static_link); - } - - // This function is only implemented and should only be called for - // user_fcn stack frames. Anything else indicates an error in the - // implementation, but we'll simply warn if that happens. - - void stack_frame::clear_values (void) - { - warning ("invalid call to stack_frame::clear_values; please report"); - } - - symbol_info_list - stack_frame::make_symbol_info_list (const std::list& symrec_list) const - { - symbol_info_list symbol_stats; - - for (const auto& sym : symrec_list) + for (const auto& nm_sil : m_sym_inf_list) { - octave_value value = varval (sym); - - if (! value.is_defined () - || (is_user_fcn_frame () && sym.frame_offset () > 0)) - continue; - - symbol_info syminf (sym.name (), value, sym.is_formal (), - is_global (sym), is_persistent (sym)); - - symbol_stats.append (syminf); + const symbol_info_list& lst = nm_sil.second; + + if (! lst.empty ()) + return false; } - return symbol_stats; + return true; } - octave_value stack_frame::who (const string_vector& patterns, - bool have_regexp, bool return_list, - bool verbose, const std::string& whos_line_fmt, - const std::string& msg) - { - symbol_info_accumulator sym_inf_accum (patterns, have_regexp); - - accept (sym_inf_accum); - - if (return_list) - { - if (verbose) - return sym_inf_accum.map_value (); - else - return Cell (string_vector (sym_inf_accum.names ())); - } - else if (! sym_inf_accum.is_empty ()) - { - - if (msg.empty ()) - octave_stdout << "Variables visible from the current scope:\n"; - else - octave_stdout << msg; - - if (verbose) - sym_inf_accum.display (octave_stdout, whos_line_fmt); - else - { - octave_stdout << "\n"; - string_vector names (sym_inf_accum.names ()); - names.list_in_columns (octave_stdout); - } - - octave_stdout << "\n"; - } - - return octave_value (); - } - - // Return first occurrence of variables in current stack frame and any - // parent frames reachable through access links. - - symbol_info_list stack_frame::all_variables (void) - { - symbol_info_accumulator sia (true, true); - - accept (sia); - - return sia.symbol_info (); - } - - octave_value stack_frame::workspace (void) - { - std::list ws_list; - - stack_frame *frame = this; - - while (frame) - { - symbol_info_list symbols = frame->all_variables (); - - octave_scalar_map ws; - - for (const auto& sym_name : symbols.names ()) - { - octave_value val = symbols.varval (sym_name); - - if (val.is_defined ()) - ws.assign (sym_name, val); - } - - ws_list.push_back (ws); - - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - Cell ws_frames (ws_list.size (), 1); - - octave_idx_type i = 0; - for (const auto& elt : ws_list) - ws_frames(i++) = elt; - - return ws_frames; - } - - // FIXME: Should this function also find any variables in parent - // scopes accessible through access_links? - - std::list stack_frame::variable_names (void) const + std::list names (void) const { std::list retval; - symbol_scope scope = get_scope (); - - const std::map& symbols = scope.symbols (); - - for (const auto& nm_sr : symbols) + for (const auto& nm_sil : m_sym_inf_list) { - if (is_variable (nm_sr.second)) - retval.push_back (nm_sr.first); + const symbol_info_list& lst = nm_sil.second; + + std::list nm_list = lst.names (); + + for (const auto& nm : nm_list) + retval.push_back (nm); } - retval.sort (); + return retval; + } + + symbol_info_list symbol_info (void) const + { + symbol_info_list retval; + + for (const auto& nm_sil : m_sym_inf_list) + { + const symbol_info_list& lst = nm_sil.second; + + for (const auto& syminf : lst) + retval.push_back (syminf); + } return retval; } - symbol_info_list stack_frame::glob_symbol_info (const std::string& pattern) - { - symbol_info_accumulator sia (pattern, false); - - accept (sia); - - return sia.symbol_info (); - } - - symbol_info_list stack_frame::regexp_symbol_info (const std::string& pattern) - { - symbol_info_accumulator sia (pattern, true); - - accept (sia); - - return sia.symbol_info (); - } - - std::size_t stack_frame::size (void) const - { - // This function should only be called for user_fcn_stack_frame or - // scope_stack_frame objects. Anything else indicates an error in - // the implementation. - - panic_impossible (); - } - - void stack_frame::resize (std::size_t) - { - // This function should only be called for user_fcn_stack_frame or - // scope_stack_frame objects. Anything else indicates an error in - // the implementation. - - panic_impossible (); - } - - stack_frame::scope_flags stack_frame::get_scope_flag (std::size_t) const - { - // This function should only be called for user_fcn_stack_frame or - // scope_stack_frame objects. Anything else indicates an error in - // the implementation. - - panic_impossible (); - } - - void stack_frame::set_scope_flag (std::size_t, scope_flags) - { - // This function should only be called for user_fcn_stack_frame or - // scope_stack_frame objects. Anything else indicates an error in - // the implementation. - - panic_impossible (); - } - - void stack_frame::install_variable (const symbol_record& sym, - const octave_value& value, bool global) - { - if (global && ! is_global (sym)) - { - octave_value val = varval (sym); - - if (val.is_defined ()) - { - std::string nm = sym.name (); - - warning_with_id ("Octave:global-local-conflict", - "global: '%s' is defined in the current scope.\n", - nm.c_str ()); - warning_with_id ("Octave:global-local-conflict", - "global: in a future version, global variables must be declared before use.\n"); - - // If the symbol is defined in the local but not the - // global scope, then use the local value as the - // initial value. This value will also override any - // initializer in the global statement. - octave_value global_val = m_evaluator.global_varval (nm); - - if (global_val.is_defined ()) - { - warning_with_id ("Octave:global-local-conflict", - "global: global value overrides existing local value"); - - clear (sym); - } - else - { - warning_with_id ("Octave:global-local-conflict", - "global: existing local value used to initialize global variable"); - - m_evaluator.global_varref (nm) = val; - } - } - - mark_global (sym); - } - - if (value.is_defined ()) - assign (sym, value); - } - - octave_value stack_frame::varval (std::size_t) const - { - // This function should only be called for user_fcn_stack_frame or - // scope_stack_frame objects. Anything else indicates an error in - // the implementation. - - panic_impossible (); - } - - octave_value& stack_frame::varref (std::size_t) + octave_map map_value (void) const { - // This function should only be called for user_fcn_stack_frame or - // scope_stack_frame objects. Anything else indicates an error in - // the implementation. - - panic_impossible (); - } - - void stack_frame::clear_objects (void) - { - symbol_cleaner sc (true, true); - - accept (sc); - } - - void stack_frame::clear_variable (const std::string& name) - { - symbol_cleaner sc (name); - - accept (sc); - } - - void stack_frame::clear_variable_pattern (const std::string& pattern) - { - symbol_cleaner sc (pattern); - - accept (sc); + octave_map retval; + + // FIXME: is there a better way to concatenate structures? + + std::size_t n_frames = m_sym_inf_list.size (); + + OCTAVE_LOCAL_BUFFER (octave_map, map_list, n_frames); + + std::size_t j = 0; + for (const auto& nm_sil : m_sym_inf_list) + { + std::string scope_name = nm_sil.first; + const symbol_info_list& lst = nm_sil.second; + + map_list[j] = lst.map_value (scope_name, n_frames-j); + + j++; + } + + return octave_map::cat (-1, n_frames, map_list); } - void stack_frame::clear_variable_pattern (const string_vector& patterns) - { - symbol_cleaner sc (patterns); - - accept (sc); - } - - void stack_frame::clear_variable_regexp (const std::string& pattern) - { - symbol_cleaner sc (pattern, true); - - accept (sc); - } - - void stack_frame::clear_variable_regexp (const string_vector& patterns) - { - symbol_cleaner sc (patterns, true); - - accept (sc); - } - - void stack_frame::clear_variables (void) - { - symbol_cleaner sc; - - accept (sc); - } - - void stack_frame::display_stopped_in_message (std::ostream& os) const + void display (std::ostream& os, const std::string& format) const { - if (index () == 0) - os << "at top level" << std::endl; - else + for (const auto& nm_sil : m_sym_inf_list) { - os << "stopped in " << fcn_name (); - - int l = line (); - if (l > 0) - os << " at line " << line (); - - os << " [" << fcn_file_name () << "] " << std::endl; - } - } - - void stack_frame::display (bool follow) const - { - std::ostream& os = octave_stdout; - - os << "-- [stack_frame] (" << this << ") --" << std::endl; - - os << "parent link: "; - if (m_parent_link) - os << m_parent_link.get (); - else - os << "NULL"; - os << std::endl; - - os << "static link: "; - if (m_static_link) - os << m_static_link.get (); - else - os << "NULL"; - os << std::endl; - - os << "access link: "; - if (m_access_link) - os << m_access_link.get (); - else - os << "NULL"; - os << std::endl; - - os << "line: " << m_line << std::endl; - os << "column: " << m_column << std::endl; - os << "index: " << m_index << std::endl; - - os << std::endl; - - if (! follow) - return; - - os << "FOLLOWING ACCESS LINKS:" << std::endl; - std::shared_ptr frm = access_link (); - while (frm) - { - frm->display (false); - os << std::endl; - - frm = frm->access_link (); + os << "\nvariables in scope: " << nm_sil.first << "\n\n"; + + const symbol_info_list& lst = nm_sil.second; + + lst.display (os, format); } } - void compiled_fcn_stack_frame::display (bool follow) const + void visit_compiled_fcn_stack_frame (compiled_fcn_stack_frame& frame) { - std::ostream& os = octave_stdout; - - os << "-- [compiled_fcn_stack_frame] (" << this << ") --" << std::endl; - stack_frame::display (follow); - - os << "fcn: " << m_fcn->name () - << " (" << m_fcn->type_name () << ")" << std::endl; - } - - void compiled_fcn_stack_frame::accept (stack_frame_walker& sfw) - { - sfw.visit_compiled_fcn_stack_frame (*this); + // This one follows static link always. Hmm, should the access + // link for a compiled_fcn_stack_frame be the same as the static + // link? + + std::shared_ptr slink = frame.static_link (); + + if (slink) + slink->accept (*this); } - script_stack_frame::script_stack_frame (tree_evaluator& tw, - octave_user_script *script, - std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link) - : stack_frame (tw, index, parent_link, static_link, - get_access_link (static_link)), - m_script (script), m_unwind_protect_frame (nullptr), - m_lexical_frame_offsets (get_num_symbols (script), 1), - m_value_offsets (get_num_symbols (script), 0) + void visit_script_stack_frame (script_stack_frame& frame) { - set_script_offsets (); + std::shared_ptr alink = frame.access_link (); + + if (alink) + alink->accept (*this); } - std::size_t script_stack_frame::get_num_symbols (octave_user_script *script) + void visit_user_fcn_stack_frame (user_fcn_stack_frame& frame) { - symbol_scope script_scope = script->scope (); - - return script_scope.num_symbols (); + append_list (frame); + + std::shared_ptr alink = frame.access_link (); + + if (alink) + alink->accept (*this); } - void script_stack_frame::set_script_offsets (void) + void visit_scope_stack_frame (scope_stack_frame& frame) { - // Set frame and data offsets inside stack frame based on enclosing - // scope(s). - - symbol_scope script_scope = m_script->scope (); - - std::size_t num_script_symbols = script_scope.num_symbols (); - - resize (num_script_symbols); - - const std::map& script_symbols - = script_scope.symbols (); - - set_script_offsets_internal (script_symbols); + append_list (frame); + + std::shared_ptr alink = frame.access_link (); + + if (alink) + alink->accept (*this); } - void script_stack_frame::set_script_offsets_internal - (const std::map& script_symbols) +private: + + typedef std::pair syminf_list_elt; + + // FIXME: the following is too complex and duplicates too much + // code. Maybe it should be split up so we have separate classes + // that do each job that is needed? + + std::list + filter (stack_frame& frame, const std::list& symbols) { - // This scope will be used to evaluate the script. Find (or - // possibly insert) symbols from the dummy script scope here. - - symbol_scope eval_scope = m_access_link->get_scope (); - - if (eval_scope.is_nested ()) + std::list new_symbols; + + if (m_match_all) { - bool found = false; - - for (const auto& nm_sr : script_symbols) + for (const auto& sym : symbols) { - std::string name = nm_sr.first; - symbol_record script_sr = nm_sr.second; - - symbol_scope parent_scope = eval_scope; - - std::size_t count = 1; - - while (parent_scope) + if (frame.is_defined (sym)) { - const std::map& parent_scope_symbols - = parent_scope.symbols (); - - auto p = parent_scope_symbols.find (name); - - if (p != parent_scope_symbols.end ()) - { - found = true; - symbol_record parent_scope_sr = p->second; - - std::size_t script_sr_data_offset = script_sr.data_offset (); - - m_lexical_frame_offsets.at (script_sr_data_offset) - = parent_scope_sr.frame_offset () + count; - - m_value_offsets.at (script_sr_data_offset) - = parent_scope_sr.data_offset (); - - break; - } - else - { - count++; - parent_scope = parent_scope.parent_scope (); - } + std::string name = sym.name (); + + if (m_first_only + && m_found_names.find (name) != m_found_names.end ()) + continue; + + m_found_names.insert (name); + + new_symbols.push_back (sym); } - - if (! found) - error ("symbol '%s' cannot be added to static scope", - name.c_str ()); - } - } - else - { - const std::map& eval_scope_symbols - = eval_scope.symbols (); - - for (const auto& nm_sr : script_symbols) - { - std::string name = nm_sr.first; - symbol_record script_sr = nm_sr.second; - - auto p = eval_scope_symbols.find (name); - - symbol_record eval_scope_sr; - - if (p == eval_scope_symbols.end ()) - eval_scope_sr = eval_scope.insert (name); - else - eval_scope_sr = p->second; - - std::size_t script_sr_data_offset = script_sr.data_offset (); - - // The +1 is for going from the script frame to the eval - // frame. Only one access_link should need to be followed. - - m_lexical_frame_offsets.at (script_sr_data_offset) - = eval_scope_sr.frame_offset () + 1; - - m_value_offsets.at (script_sr_data_offset) - = eval_scope_sr.data_offset (); } } - } - - void script_stack_frame::resize_and_update_script_offsets (const symbol_record& sym) - { - std::size_t data_offset = sym.data_offset (); - - // This function is called when adding new symbols to a script - // scope. If the symbol wasn't present before, it should be outside - // the range so we need to resize then update offsets. - - panic_unless (data_offset >= size ()); - - resize (data_offset+1); - - // FIXME: We should be able to avoid creating the map object and the - // looping in the set_scripts_offsets_internal function. Can we do - // that without (or with minimal) code duplication? - - std::map tmp_symbols; - tmp_symbols[sym.name ()] = sym; - set_script_offsets_internal (tmp_symbols); - } - - // If this is a nested scope, set access_link to nearest parent - // stack frame that corresponds to the lexical parent of this scope. - - std::shared_ptr - script_stack_frame::get_access_link (const std::shared_ptr& static_link) - { - // If this script is called from another script, set access - // link to ultimate parent stack frame. - - std::shared_ptr alink = static_link; - - while (alink->is_user_script_frame ()) - { - if (alink->access_link ()) - alink = alink->access_link (); - else - break; - } - - return alink; - } - - unwind_protect * script_stack_frame::unwind_protect_frame (void) - { - if (! m_unwind_protect_frame) - m_unwind_protect_frame = new unwind_protect (); - - return m_unwind_protect_frame; - } - - symbol_record script_stack_frame::lookup_symbol (const std::string& name) const - { - symbol_scope scope = get_scope (); - - symbol_record sym = scope.lookup_symbol (name); - - if (sym) + else if (m_have_regexp) { - panic_unless (sym.frame_offset () == 0); - - return sym; - } - - sym = m_access_link->lookup_symbol (name); - - // Return symbol record with adjusted frame offset. - symbol_record new_sym = sym.dup (); - - new_sym.set_frame_offset (sym.frame_offset () + 1); - - return new_sym; - } - - symbol_record script_stack_frame::insert_symbol (const std::string& name) - { - // If the symbols is already in the immediate scope, there is - // nothing more to do. - - symbol_scope scope = get_scope (); - - symbol_record sym = scope.lookup_symbol (name); - - if (sym) - { - // All symbol records in a script scope should have zero offset, - // which means we redirect our lookup using - // lexical_frame_offsets and values_offets. - panic_unless (sym.frame_offset () == 0); - - return sym; - } - - // Insert the symbol in the current scope then resize and update - // offsets. This operation should never fail. - - sym = scope.find_symbol (name); - - panic_unless (sym.is_valid ()); - - resize_and_update_script_offsets (sym); - - return sym; - } - - // Similar to set_script_offsets_internal except that we only return - // frame and data offsets for symbols found by name in parent scopes - // instead of updating the offsets stored in the script frame itself. - - bool - script_stack_frame::get_val_offsets_internal (const symbol_record& script_sr, - std::size_t& frame_offset, - std::size_t& data_offset) const - { - bool found = false; - - // This scope will be used to evaluate the script. Find symbols - // here by name. - - symbol_scope eval_scope = m_access_link->get_scope (); - - if (eval_scope.is_nested ()) - { - std::string name = script_sr.name (); - - symbol_scope parent_scope = eval_scope; - - std::size_t count = 1; - - while (parent_scope) + octave_idx_type npatterns = m_patterns.numel (); + + for (octave_idx_type j = 0; j < npatterns; j++) { - const std::map& parent_scope_symbols - = parent_scope.symbols (); - - auto p = parent_scope_symbols.find (name); - - if (p != parent_scope_symbols.end ()) + std::string pattern = m_patterns[j]; + + regexp pat (pattern); + + for (const auto& sym : symbols) { - found = true; - symbol_record parent_scope_sr = p->second; - - frame_offset = parent_scope_sr.frame_offset () + count; - - data_offset = parent_scope_sr.data_offset (); - - break; - } - else - { - count++; - parent_scope = parent_scope.parent_scope (); + std::string name = sym.name (); + + if (pat.is_match (name) && frame.is_defined (sym)) + { + if (m_first_only + && m_found_names.find (name) != m_found_names.end ()) + continue; + + m_found_names.insert (name); + + new_symbols.push_back (sym); + } } } } else { - const std::map& eval_scope_symbols - = eval_scope.symbols (); - - std::string name = script_sr.name (); - - auto p = eval_scope_symbols.find (name); - - symbol_record eval_scope_sr; - - if (p != eval_scope_symbols.end ()) - { - found = true; - eval_scope_sr = p->second; - - // The +1 is for going from the script frame to the eval - // frame. Only one access_link should need to be followed. - - frame_offset = eval_scope_sr.frame_offset () + 1; - - data_offset = eval_scope_sr.data_offset (); - } - } - - return found; - } - - bool script_stack_frame::get_val_offsets (const symbol_record& sym, - std::size_t& frame_offset, - std::size_t& data_offset) const - { - data_offset = sym.data_offset (); - frame_offset = sym.frame_offset (); - - if (frame_offset == 0) - { - // An out of range data_offset value here means that we have a - // symbol that was not originally in the script. But this - // function is called in places where we can't insert a new - // symbol, so we fail and it is up to the caller to decide what - // to do. - - if (data_offset >= size ()) - return get_val_offsets_internal (sym, frame_offset, data_offset); - - // Use frame and value offsets stored in this stack frame, - // indexed by data_offset from the symbol_record to find the - // values. These offsets were determined by - // script_stack_frame::set_script_offsets when this script was - // invoked. - - frame_offset = m_lexical_frame_offsets.at (data_offset); - - if (frame_offset == 0) - { - // If the frame offset stored in m_lexical_frame_offsets is - // zero, then the data offset in the evaluation scope has - // not been determined so try to do that now. The symbol - // may have been added by eval and without calling - // resize_and_update_script_offsets. - - return get_val_offsets_internal (sym, frame_offset, data_offset); - } - - data_offset = m_value_offsets.at (data_offset); - } - else - { - // If frame_offset is not zero, then then we must have a symbol - // that was not originally in the script. The values should - // have been determined by the script_stack_frame::lookup function. - } - - return true; - } - - void script_stack_frame::get_val_offsets_with_insert (const symbol_record& sym, - std::size_t& frame_offset, - std::size_t& data_offset) - { - data_offset = sym.data_offset (); - frame_offset = sym.frame_offset (); - - if (frame_offset == 0) - { - if (data_offset >= size ()) - { - // If the data_offset is out of range, then we must have a - // symbol that was not originally in the script. Resize and - // update the offsets. - - resize_and_update_script_offsets (sym); - } - - // Use frame and value offsets stored in this stack frame, - // indexed by data_offset from the symbol_record to find the - // values. These offsets were determined by - // script_stack_frame::set_script_offsets when this script was - // invoked. - - frame_offset = m_lexical_frame_offsets.at (data_offset); - - if (frame_offset == 0) + octave_idx_type npatterns = m_patterns.numel (); + + for (octave_idx_type j = 0; j < npatterns; j++) { - // If the frame offset stored in m_lexical_frame_offsets is - // zero, then the data offset in the evaluation scope has - // not been determined so try to do that now. The symbol - // may have been added by eval and without calling - // resize_and_update_script_offsets. - - // We don't need to resize here. That case is handled above. - - // FIXME: We should be able to avoid creating the map object - // and the looping in the set_scripts_offsets_internal - // function. Can we do that without (or with minimal) code - // duplication? - - std::map tmp_symbols; - tmp_symbols[sym.name ()] = sym; - set_script_offsets_internal (tmp_symbols); - - // set_script_offsets_internal may have modified - // m_lexical_frame_offsets and m_value_offsets. - - frame_offset = m_lexical_frame_offsets.at (data_offset); - } - - data_offset = m_value_offsets.at (data_offset); - } - else - { - // If frame_offset is not zero, then then we must have a symbol - // that was not originally in the script. The values were - // determined by the script_stack_frame::lookup function. - } - } - - stack_frame::scope_flags - script_stack_frame::scope_flag (const symbol_record& sym) const - { - std::size_t frame_offset; - std::size_t data_offset; - - bool found = get_val_offsets (sym, frame_offset, data_offset); - - // It can't be global or persistent, so call it local. - if (! found) - return LOCAL; - - // Follow frame_offset access links to stack frame that holds - // the value. - - const stack_frame *frame = this; - - for (std::size_t i = 0; i < frame_offset; i++) - { - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - if (! frame) - error ("internal error: invalid access link in function call stack"); - - if (data_offset >= frame->size ()) - return LOCAL; - - return frame->get_scope_flag (data_offset); - } - - octave_value script_stack_frame::varval (const symbol_record& sym) const - { - std::size_t frame_offset; - std::size_t data_offset; - - bool found = get_val_offsets (sym, frame_offset, data_offset); - - if (! found) - return octave_value (); - - // Follow frame_offset access links to stack frame that holds - // the value. - - const stack_frame *frame = this; - - for (std::size_t i = 0; i < frame_offset; i++) - { - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - if (! frame) - error ("internal error: invalid access link in function call stack"); - - if (data_offset >= frame->size ()) - return octave_value (); - - switch (frame->get_scope_flag (data_offset)) - { - case LOCAL: - return frame->varval (data_offset); - - case PERSISTENT: - { - symbol_scope scope = frame->get_scope (); - - return scope.persistent_varval (data_offset); - } - - case GLOBAL: - return m_evaluator.global_varval (sym.name ()); - } - - error ("internal error: invalid switch case"); - } - - octave_value& script_stack_frame::varref (const symbol_record& sym) - { - std::size_t frame_offset; - std::size_t data_offset; - get_val_offsets_with_insert (sym, frame_offset, data_offset); - - // Follow frame_offset access links to stack frame that holds - // the value. - - stack_frame *frame = this; - - for (std::size_t i = 0; i < frame_offset; i++) - { - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - if (data_offset >= frame->size ()) - frame->resize (data_offset+1); - - switch (frame->get_scope_flag (data_offset)) - { - case LOCAL: - return frame->varref (data_offset); - - case PERSISTENT: - { - symbol_scope scope = frame->get_scope (); - - return scope.persistent_varref (data_offset); - } - - case GLOBAL: - return m_evaluator.global_varref (sym.name ()); - } - - error ("internal error: invalid switch case"); - } - - void script_stack_frame::mark_scope (const symbol_record& sym, - scope_flags flag) - { - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - resize_and_update_script_offsets (sym); - - // Redirection to evaluation context for the script. - - std::size_t frame_offset = m_lexical_frame_offsets.at (data_offset); - data_offset = m_value_offsets.at (data_offset); - - if (frame_offset > 1) - error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used"); - - std::shared_ptr frame = access_link (); - - if (data_offset >= frame->size ()) - frame->resize (data_offset+1); - - frame->set_scope_flag (data_offset, flag); - } - - void script_stack_frame::display (bool follow) const - { - std::ostream& os = octave_stdout; - - os << "-- [script_stack_frame] (" << this << ") --" << std::endl; - stack_frame::display (follow); - - os << "script: " << m_script->name () - << " (" << m_script->type_name () << ")" << std::endl; - - os << "lexical_offsets: " << m_lexical_frame_offsets.size () - << " elements:"; - - for (std::size_t i = 0; i < m_lexical_frame_offsets.size (); i++) - os << " " << m_lexical_frame_offsets.at (i); - os << std::endl; - - os << "value_offsets: " << m_value_offsets.size () << " elements:"; - for (std::size_t i = 0; i < m_value_offsets.size (); i++) - os << " " << m_value_offsets.at (i); - os << std::endl; - - display_scope (os, get_scope ()); - } - - void script_stack_frame::accept (stack_frame_walker& sfw) - { - sfw.visit_script_stack_frame (*this); - } - - void base_value_stack_frame::display (bool follow) const - { - std::ostream& os = octave_stdout; - - os << "-- [base_value_stack_frame] (" << this << ") --" << std::endl; - stack_frame::display (follow); - - os << "values: " << m_values.size () - << " elements (idx, scope flag, type):" << std::endl; - - for (std::size_t i = 0; i < m_values.size (); i++) - { - os << " (" << i << ", " << m_flags.at (i) << ", "; - - octave_value val = varval (i); - - os << (val.is_defined () ? val.type_name () : " UNDEFINED") << ")" - << std::endl; - } - } - - // If this is a nested scope, set access_link to nearest parent - // stack frame that corresponds to the lexical parent of this scope. - - std::shared_ptr - user_fcn_stack_frame::get_access_link (octave_user_function *fcn, - const std::shared_ptr& static_link) - { - std::shared_ptr alink; - - symbol_scope fcn_scope = fcn->scope (); - - if (fcn_scope.is_nested ()) - { - if (! static_link) - error ("internal call stack error (invalid static link)"); - - symbol_scope caller_scope = static_link->get_scope (); - - int nesting_depth = fcn_scope.nesting_depth (); - int caller_nesting_depth = caller_scope.nesting_depth (); - - if (caller_nesting_depth < nesting_depth) - { - // FIXME: do we need to ensure that the called - // function is a child of the caller? Does it hurt - // to panic_unless this condition, at least for now? - - alink = static_link; - } - else - { - // FIXME: do we need to check that the parent of the - // called function is also a parent of the caller? - // Does it hurt to panic_unless this condition, at least - // for now? - - int links_to_follow = caller_nesting_depth - nesting_depth + 1; - - alink = static_link; - - while (alink && --links_to_follow >= 0) - alink = alink->access_link (); - - if (! alink) - error ("internal function nesting error (invalid access link)"); - } - } - - return alink; - } - - void user_fcn_stack_frame::clear_values (void) - { - symbol_scope fcn_scope = m_fcn->scope (); - - const std::list& symbols = fcn_scope.symbol_list (); - - if (size () == 0) - return; - - for (const auto& sym : symbols) - { - std::size_t frame_offset = sym.frame_offset (); - - if (frame_offset > 0) - continue; - - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - continue; - - if (get_scope_flag (data_offset) == LOCAL) - { - octave_value& ref = m_values.at (data_offset); - - if (ref.get_count () == 1) + std::string pattern = m_patterns[j]; + + glob_match pat (pattern); + + for (const auto& sym : symbols) { - ref.call_object_destructor (); - ref = octave_value (); + std::string name = sym.name (); + + if (pat.match (name) && frame.is_defined (sym)) + { + if (m_first_only + && m_found_names.find (name) == m_found_names.end ()) + continue; + + m_found_names.insert (name); + + new_symbols.push_back (sym); + } } } } + + return new_symbols; } - unwind_protect * user_fcn_stack_frame::unwind_protect_frame (void) + void append_list (stack_frame& frame) { - if (! m_unwind_protect_frame) - m_unwind_protect_frame = new unwind_protect (); - - return m_unwind_protect_frame; + symbol_scope scope = frame.get_scope (); + + std::list symbols = scope.symbol_list (); + + if (m_match_all || ! m_patterns.empty ()) + symbols = filter (frame, symbols); + + symbol_info_list syminf_list = frame.make_symbol_info_list (symbols); + + m_sym_inf_list.push_back (syminf_list_elt (scope.name (), syminf_list)); } - symbol_record user_fcn_stack_frame::lookup_symbol (const std::string& name) const - { - const stack_frame *frame = this; - - while (frame) + string_vector m_patterns; + + bool m_match_all; + bool m_first_only; + bool m_have_regexp; + + std::list> m_sym_inf_list; + + std::set m_found_names; +}; + +stack_frame *stack_frame::create (tree_evaluator& tw, octave_function *fcn, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link) +{ + return new compiled_fcn_stack_frame (tw, fcn, index, + parent_link, static_link); +} + +stack_frame *stack_frame::create (tree_evaluator& tw, + octave_user_script *script, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link) +{ + return new script_stack_frame (tw, script, index, parent_link, static_link); +} + +stack_frame *stack_frame::create (tree_evaluator& tw, + octave_user_function *fcn, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const std::shared_ptr& access_link) +{ + return new user_fcn_stack_frame (tw, fcn, index, + parent_link, static_link, access_link); +} + +stack_frame *stack_frame::create (tree_evaluator& tw, + octave_user_function *fcn, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const local_vars_map& local_vars, + const std::shared_ptr& access_link) +{ + return new user_fcn_stack_frame (tw, fcn, index, + parent_link, static_link, local_vars, + access_link); +} + +stack_frame *stack_frame::create (tree_evaluator& tw, + const symbol_scope& scope, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link) +{ + return new scope_stack_frame (tw, scope, index, parent_link, static_link); +} + +// This function is only implemented and should only be called for +// user_fcn stack frames. Anything else indicates an error in the +// implementation, but we'll simply warn if that happens. + +void stack_frame::clear_values (void) +{ + warning ("invalid call to stack_frame::clear_values; please report"); +} + +symbol_info_list +stack_frame::make_symbol_info_list (const std::list& symrec_list) const +{ + symbol_info_list symbol_stats; + + for (const auto& sym : symrec_list) + { + octave_value value = varval (sym); + + if (! value.is_defined () + || (is_user_fcn_frame () && sym.frame_offset () > 0)) + continue; + + symbol_info syminf (sym.name (), value, sym.is_formal (), + is_global (sym), is_persistent (sym)); + + symbol_stats.append (syminf); + } + + return symbol_stats; +} + +octave_value stack_frame::who (const string_vector& patterns, + bool have_regexp, bool return_list, + bool verbose, const std::string& whos_line_fmt, + const std::string& msg) +{ + symbol_info_accumulator sym_inf_accum (patterns, have_regexp); + + accept (sym_inf_accum); + + if (return_list) + { + if (verbose) + return sym_inf_accum.map_value (); + else + return Cell (string_vector (sym_inf_accum.names ())); + } + else if (! sym_inf_accum.is_empty ()) + { + + if (msg.empty ()) + octave_stdout << "Variables visible from the current scope:\n"; + else + octave_stdout << msg; + + if (verbose) + sym_inf_accum.display (octave_stdout, whos_line_fmt); + else + { + octave_stdout << "\n"; + string_vector names (sym_inf_accum.names ()); + names.list_in_columns (octave_stdout); + } + + octave_stdout << "\n"; + } + + return octave_value (); +} + +// Return first occurrence of variables in current stack frame and any +// parent frames reachable through access links. + +symbol_info_list stack_frame::all_variables (void) +{ + symbol_info_accumulator sia (true, true); + + accept (sia); + + return sia.symbol_info (); +} + +octave_value stack_frame::workspace (void) +{ + std::list ws_list; + + stack_frame *frame = this; + + while (frame) + { + symbol_info_list symbols = frame->all_variables (); + + octave_scalar_map ws; + + for (const auto& sym_name : symbols.names ()) + { + octave_value val = symbols.varval (sym_name); + + if (val.is_defined ()) + ws.assign (sym_name, val); + } + + ws_list.push_back (ws); + + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + Cell ws_frames (ws_list.size (), 1); + + octave_idx_type i = 0; + for (const auto& elt : ws_list) + ws_frames(i++) = elt; + + return ws_frames; +} + +// FIXME: Should this function also find any variables in parent +// scopes accessible through access_links? + +std::list stack_frame::variable_names (void) const +{ + std::list retval; + + symbol_scope scope = get_scope (); + + const std::map& symbols = scope.symbols (); + + for (const auto& nm_sr : symbols) + { + if (is_variable (nm_sr.second)) + retval.push_back (nm_sr.first); + } + + retval.sort (); + + return retval; +} + +symbol_info_list stack_frame::glob_symbol_info (const std::string& pattern) +{ + symbol_info_accumulator sia (pattern, false); + + accept (sia); + + return sia.symbol_info (); +} + +symbol_info_list stack_frame::regexp_symbol_info (const std::string& pattern) +{ + symbol_info_accumulator sia (pattern, true); + + accept (sia); + + return sia.symbol_info (); +} + +std::size_t stack_frame::size (void) const +{ + // This function should only be called for user_fcn_stack_frame or + // scope_stack_frame objects. Anything else indicates an error in + // the implementation. + + panic_impossible (); +} + +void stack_frame::resize (std::size_t) +{ + // This function should only be called for user_fcn_stack_frame or + // scope_stack_frame objects. Anything else indicates an error in + // the implementation. + + panic_impossible (); +} + +stack_frame::scope_flags stack_frame::get_scope_flag (std::size_t) const +{ + // This function should only be called for user_fcn_stack_frame or + // scope_stack_frame objects. Anything else indicates an error in + // the implementation. + + panic_impossible (); +} + +void stack_frame::set_scope_flag (std::size_t, scope_flags) +{ + // This function should only be called for user_fcn_stack_frame or + // scope_stack_frame objects. Anything else indicates an error in + // the implementation. + + panic_impossible (); +} + +void stack_frame::install_variable (const symbol_record& sym, + const octave_value& value, bool global) +{ + if (global && ! is_global (sym)) + { + octave_value val = varval (sym); + + if (val.is_defined ()) + { + std::string nm = sym.name (); + + warning_with_id ("Octave:global-local-conflict", + "global: '%s' is defined in the current scope.\n", + nm.c_str ()); + warning_with_id ("Octave:global-local-conflict", + "global: in a future version, global variables must be declared before use.\n"); + + // If the symbol is defined in the local but not the + // global scope, then use the local value as the + // initial value. This value will also override any + // initializer in the global statement. + octave_value global_val = m_evaluator.global_varval (nm); + + if (global_val.is_defined ()) + { + warning_with_id ("Octave:global-local-conflict", + "global: global value overrides existing local value"); + + clear (sym); + } + else + { + warning_with_id ("Octave:global-local-conflict", + "global: existing local value used to initialize global variable"); + + m_evaluator.global_varref (nm) = val; + } + } + + mark_global (sym); + } + + if (value.is_defined ()) + assign (sym, value); +} + +octave_value stack_frame::varval (std::size_t) const +{ + // This function should only be called for user_fcn_stack_frame or + // scope_stack_frame objects. Anything else indicates an error in + // the implementation. + + panic_impossible (); +} + +octave_value& stack_frame::varref (std::size_t) +{ + // This function should only be called for user_fcn_stack_frame or + // scope_stack_frame objects. Anything else indicates an error in + // the implementation. + + panic_impossible (); +} + +void stack_frame::clear_objects (void) +{ + symbol_cleaner sc (true, true); + + accept (sc); +} + +void stack_frame::clear_variable (const std::string& name) +{ + symbol_cleaner sc (name); + + accept (sc); +} + +void stack_frame::clear_variable_pattern (const std::string& pattern) +{ + symbol_cleaner sc (pattern); + + accept (sc); +} + +void stack_frame::clear_variable_pattern (const string_vector& patterns) +{ + symbol_cleaner sc (patterns); + + accept (sc); +} + +void stack_frame::clear_variable_regexp (const std::string& pattern) +{ + symbol_cleaner sc (pattern, true); + + accept (sc); +} + +void stack_frame::clear_variable_regexp (const string_vector& patterns) +{ + symbol_cleaner sc (patterns, true); + + accept (sc); +} + +void stack_frame::clear_variables (void) +{ + symbol_cleaner sc; + + accept (sc); +} + +void stack_frame::display_stopped_in_message (std::ostream& os) const +{ + if (index () == 0) + os << "at top level" << std::endl; + else + { + os << "stopped in " << fcn_name (); + + int l = line (); + if (l > 0) + os << " at line " << line (); + + os << " [" << fcn_file_name () << "] " << std::endl; + } +} + +void stack_frame::display (bool follow) const +{ + std::ostream& os = octave_stdout; + + os << "-- [stack_frame] (" << this << ") --" << std::endl; + + os << "parent link: "; + if (m_parent_link) + os << m_parent_link.get (); + else + os << "NULL"; + os << std::endl; + + os << "static link: "; + if (m_static_link) + os << m_static_link.get (); + else + os << "NULL"; + os << std::endl; + + os << "access link: "; + if (m_access_link) + os << m_access_link.get (); + else + os << "NULL"; + os << std::endl; + + os << "line: " << m_line << std::endl; + os << "column: " << m_column << std::endl; + os << "index: " << m_index << std::endl; + + os << std::endl; + + if (! follow) + return; + + os << "FOLLOWING ACCESS LINKS:" << std::endl; + std::shared_ptr frm = access_link (); + while (frm) + { + frm->display (false); + os << std::endl; + + frm = frm->access_link (); + } +} + +void compiled_fcn_stack_frame::display (bool follow) const +{ + std::ostream& os = octave_stdout; + + os << "-- [compiled_fcn_stack_frame] (" << this << ") --" << std::endl; + stack_frame::display (follow); + + os << "fcn: " << m_fcn->name () + << " (" << m_fcn->type_name () << ")" << std::endl; +} + +void compiled_fcn_stack_frame::accept (stack_frame_walker& sfw) +{ + sfw.visit_compiled_fcn_stack_frame (*this); +} + +script_stack_frame::script_stack_frame (tree_evaluator& tw, + octave_user_script *script, + std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link) + : stack_frame (tw, index, parent_link, static_link, + get_access_link (static_link)), + m_script (script), m_unwind_protect_frame (nullptr), + m_lexical_frame_offsets (get_num_symbols (script), 1), + m_value_offsets (get_num_symbols (script), 0) +{ + set_script_offsets (); +} + +std::size_t script_stack_frame::get_num_symbols (octave_user_script *script) +{ + symbol_scope script_scope = script->scope (); + + return script_scope.num_symbols (); +} + +void script_stack_frame::set_script_offsets (void) +{ + // Set frame and data offsets inside stack frame based on enclosing + // scope(s). + + symbol_scope script_scope = m_script->scope (); + + std::size_t num_script_symbols = script_scope.num_symbols (); + + resize (num_script_symbols); + + const std::map& script_symbols + = script_scope.symbols (); + + set_script_offsets_internal (script_symbols); +} + +void script_stack_frame::set_script_offsets_internal +(const std::map& script_symbols) +{ + // This scope will be used to evaluate the script. Find (or + // possibly insert) symbols from the dummy script scope here. + + symbol_scope eval_scope = m_access_link->get_scope (); + + if (eval_scope.is_nested ()) + { + bool found = false; + + for (const auto& nm_sr : script_symbols) + { + std::string name = nm_sr.first; + symbol_record script_sr = nm_sr.second; + + symbol_scope parent_scope = eval_scope; + + std::size_t count = 1; + + while (parent_scope) + { + const std::map& parent_scope_symbols + = parent_scope.symbols (); + + auto p = parent_scope_symbols.find (name); + + if (p != parent_scope_symbols.end ()) + { + found = true; + symbol_record parent_scope_sr = p->second; + + std::size_t script_sr_data_offset = script_sr.data_offset (); + + m_lexical_frame_offsets.at (script_sr_data_offset) + = parent_scope_sr.frame_offset () + count; + + m_value_offsets.at (script_sr_data_offset) + = parent_scope_sr.data_offset (); + + break; + } + else + { + count++; + parent_scope = parent_scope.parent_scope (); + } + } + + if (! found) + error ("symbol '%s' cannot be added to static scope", + name.c_str ()); + } + } + else + { + const std::map& eval_scope_symbols + = eval_scope.symbols (); + + for (const auto& nm_sr : script_symbols) + { + std::string name = nm_sr.first; + symbol_record script_sr = nm_sr.second; + + auto p = eval_scope_symbols.find (name); + + symbol_record eval_scope_sr; + + if (p == eval_scope_symbols.end ()) + eval_scope_sr = eval_scope.insert (name); + else + eval_scope_sr = p->second; + + std::size_t script_sr_data_offset = script_sr.data_offset (); + + // The +1 is for going from the script frame to the eval + // frame. Only one access_link should need to be followed. + + m_lexical_frame_offsets.at (script_sr_data_offset) + = eval_scope_sr.frame_offset () + 1; + + m_value_offsets.at (script_sr_data_offset) + = eval_scope_sr.data_offset (); + } + } +} + +void script_stack_frame::resize_and_update_script_offsets (const symbol_record& sym) +{ + std::size_t data_offset = sym.data_offset (); + + // This function is called when adding new symbols to a script + // scope. If the symbol wasn't present before, it should be outside + // the range so we need to resize then update offsets. + + panic_unless (data_offset >= size ()); + + resize (data_offset+1); + + // FIXME: We should be able to avoid creating the map object and the + // looping in the set_scripts_offsets_internal function. Can we do + // that without (or with minimal) code duplication? + + std::map tmp_symbols; + tmp_symbols[sym.name ()] = sym; + set_script_offsets_internal (tmp_symbols); +} + +// If this is a nested scope, set access_link to nearest parent +// stack frame that corresponds to the lexical parent of this scope. + +std::shared_ptr +script_stack_frame::get_access_link (const std::shared_ptr& static_link) +{ + // If this script is called from another script, set access + // link to ultimate parent stack frame. + + std::shared_ptr alink = static_link; + + while (alink->is_user_script_frame ()) + { + if (alink->access_link ()) + alink = alink->access_link (); + else + break; + } + + return alink; +} + +unwind_protect *script_stack_frame::unwind_protect_frame (void) +{ + if (! m_unwind_protect_frame) + m_unwind_protect_frame = new unwind_protect (); + + return m_unwind_protect_frame; +} + +symbol_record script_stack_frame::lookup_symbol (const std::string& name) const +{ + symbol_scope scope = get_scope (); + + symbol_record sym = scope.lookup_symbol (name); + + if (sym) + { + panic_unless (sym.frame_offset () == 0); + + return sym; + } + + sym = m_access_link->lookup_symbol (name); + + // Return symbol record with adjusted frame offset. + symbol_record new_sym = sym.dup (); + + new_sym.set_frame_offset (sym.frame_offset () + 1); + + return new_sym; +} + +symbol_record script_stack_frame::insert_symbol (const std::string& name) +{ + // If the symbols is already in the immediate scope, there is + // nothing more to do. + + symbol_scope scope = get_scope (); + + symbol_record sym = scope.lookup_symbol (name); + + if (sym) + { + // All symbol records in a script scope should have zero offset, + // which means we redirect our lookup using + // lexical_frame_offsets and values_offets. + panic_unless (sym.frame_offset () == 0); + + return sym; + } + + // Insert the symbol in the current scope then resize and update + // offsets. This operation should never fail. + + sym = scope.find_symbol (name); + + panic_unless (sym.is_valid ()); + + resize_and_update_script_offsets (sym); + + return sym; +} + +// Similar to set_script_offsets_internal except that we only return +// frame and data offsets for symbols found by name in parent scopes +// instead of updating the offsets stored in the script frame itself. + +bool +script_stack_frame::get_val_offsets_internal (const symbol_record& script_sr, + std::size_t& frame_offset, + std::size_t& data_offset) const +{ + bool found = false; + + // This scope will be used to evaluate the script. Find symbols + // here by name. + + symbol_scope eval_scope = m_access_link->get_scope (); + + if (eval_scope.is_nested ()) + { + std::string name = script_sr.name (); + + symbol_scope parent_scope = eval_scope; + + std::size_t count = 1; + + while (parent_scope) + { + const std::map& parent_scope_symbols + = parent_scope.symbols (); + + auto p = parent_scope_symbols.find (name); + + if (p != parent_scope_symbols.end ()) + { + found = true; + symbol_record parent_scope_sr = p->second; + + frame_offset = parent_scope_sr.frame_offset () + count; + + data_offset = parent_scope_sr.data_offset (); + + break; + } + else + { + count++; + parent_scope = parent_scope.parent_scope (); + } + } + } + else + { + const std::map& eval_scope_symbols + = eval_scope.symbols (); + + std::string name = script_sr.name (); + + auto p = eval_scope_symbols.find (name); + + symbol_record eval_scope_sr; + + if (p != eval_scope_symbols.end ()) + { + found = true; + eval_scope_sr = p->second; + + // The +1 is for going from the script frame to the eval + // frame. Only one access_link should need to be followed. + + frame_offset = eval_scope_sr.frame_offset () + 1; + + data_offset = eval_scope_sr.data_offset (); + } + } + + return found; +} + +bool script_stack_frame::get_val_offsets (const symbol_record& sym, + std::size_t& frame_offset, + std::size_t& data_offset) const +{ + data_offset = sym.data_offset (); + frame_offset = sym.frame_offset (); + + if (frame_offset == 0) + { + // An out of range data_offset value here means that we have a + // symbol that was not originally in the script. But this + // function is called in places where we can't insert a new + // symbol, so we fail and it is up to the caller to decide what + // to do. + + if (data_offset >= size ()) + return get_val_offsets_internal (sym, frame_offset, data_offset); + + // Use frame and value offsets stored in this stack frame, + // indexed by data_offset from the symbol_record to find the + // values. These offsets were determined by + // script_stack_frame::set_script_offsets when this script was + // invoked. + + frame_offset = m_lexical_frame_offsets.at (data_offset); + + if (frame_offset == 0) + { + // If the frame offset stored in m_lexical_frame_offsets is + // zero, then the data offset in the evaluation scope has + // not been determined so try to do that now. The symbol + // may have been added by eval and without calling + // resize_and_update_script_offsets. + + return get_val_offsets_internal (sym, frame_offset, data_offset); + } + + data_offset = m_value_offsets.at (data_offset); + } + else + { + // If frame_offset is not zero, then then we must have a symbol + // that was not originally in the script. The values should + // have been determined by the script_stack_frame::lookup function. + } + + return true; +} + +void script_stack_frame::get_val_offsets_with_insert (const symbol_record& sym, + std::size_t& frame_offset, + std::size_t& data_offset) +{ + data_offset = sym.data_offset (); + frame_offset = sym.frame_offset (); + + if (frame_offset == 0) + { + if (data_offset >= size ()) + { + // If the data_offset is out of range, then we must have a + // symbol that was not originally in the script. Resize and + // update the offsets. + + resize_and_update_script_offsets (sym); + } + + // Use frame and value offsets stored in this stack frame, + // indexed by data_offset from the symbol_record to find the + // values. These offsets were determined by + // script_stack_frame::set_script_offsets when this script was + // invoked. + + frame_offset = m_lexical_frame_offsets.at (data_offset); + + if (frame_offset == 0) + { + // If the frame offset stored in m_lexical_frame_offsets is + // zero, then the data offset in the evaluation scope has + // not been determined so try to do that now. The symbol + // may have been added by eval and without calling + // resize_and_update_script_offsets. + + // We don't need to resize here. That case is handled above. + + // FIXME: We should be able to avoid creating the map object + // and the looping in the set_scripts_offsets_internal + // function. Can we do that without (or with minimal) code + // duplication? + + std::map tmp_symbols; + tmp_symbols[sym.name ()] = sym; + set_script_offsets_internal (tmp_symbols); + + // set_script_offsets_internal may have modified + // m_lexical_frame_offsets and m_value_offsets. + + frame_offset = m_lexical_frame_offsets.at (data_offset); + } + + data_offset = m_value_offsets.at (data_offset); + } + else + { + // If frame_offset is not zero, then then we must have a symbol + // that was not originally in the script. The values were + // determined by the script_stack_frame::lookup function. + } +} + +stack_frame::scope_flags +script_stack_frame::scope_flag (const symbol_record& sym) const +{ + std::size_t frame_offset; + std::size_t data_offset; + + bool found = get_val_offsets (sym, frame_offset, data_offset); + + // It can't be global or persistent, so call it local. + if (! found) + return LOCAL; + + // Follow frame_offset access links to stack frame that holds + // the value. + + const stack_frame *frame = this; + + for (std::size_t i = 0; i < frame_offset; i++) + { + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + if (! frame) + error ("internal error: invalid access link in function call stack"); + + if (data_offset >= frame->size ()) + return LOCAL; + + return frame->get_scope_flag (data_offset); +} + +octave_value script_stack_frame::varval (const symbol_record& sym) const +{ + std::size_t frame_offset; + std::size_t data_offset; + + bool found = get_val_offsets (sym, frame_offset, data_offset); + + if (! found) + return octave_value (); + + // Follow frame_offset access links to stack frame that holds + // the value. + + const stack_frame *frame = this; + + for (std::size_t i = 0; i < frame_offset; i++) + { + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + if (! frame) + error ("internal error: invalid access link in function call stack"); + + if (data_offset >= frame->size ()) + return octave_value (); + + switch (frame->get_scope_flag (data_offset)) + { + case LOCAL: + return frame->varval (data_offset); + + case PERSISTENT: { symbol_scope scope = frame->get_scope (); - symbol_record sym = scope.lookup_symbol (name); - - if (sym) - return sym; - - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - return symbol_record (); - } - - symbol_record user_fcn_stack_frame::insert_symbol (const std::string& name) - { - // If the symbols is already in the immediate scope, there is - // nothing more to do. - - symbol_scope scope = get_scope (); - - symbol_record sym = scope.lookup_symbol (name); - - if (sym) - return sym; - - // FIXME: This needs some thought... We may need to add a symbol to - // a static workspace, but the symbol can never be defined as a - // variable. This currently works by tagging the added symbol as - // "added_static". Aside from the bad name, this doesn't seem like - // the best solution. Maybe scopes should have a separate set of - // symbols that may only be defined as functions? - - // Insert the symbol in the current scope. This is not possible for - // anonymous functions, nested functions, or functions that contain - // nested functions (their scopes will all be marked static). - - // if (scope.is_static ()) - // error ("can not add variable '%s' to a static workspace", - // name.c_str ()); - - // At this point, non-local references are not possible so we only - // need to look in the current scope and insert there. This - // operation should never fail. - - sym = scope.find_symbol (name); - - panic_unless (sym.is_valid ()); - - return sym; - } - - stack_frame::scope_flags - user_fcn_stack_frame::scope_flag (const symbol_record& sym) const - { - std::size_t frame_offset = sym.frame_offset (); - std::size_t data_offset = sym.data_offset (); - - // Follow frame_offset access links to stack frame that holds - // the value. - - const stack_frame *frame = this; - - for (std::size_t i = 0; i < frame_offset; i++) - { - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); + return scope.persistent_varval (data_offset); } - if (! frame) - error ("internal error: invalid access link in function call stack"); - - if (data_offset >= frame->size ()) - return LOCAL; - - return frame->get_scope_flag (data_offset); - } - - octave_value user_fcn_stack_frame::varval (const symbol_record& sym) const - { - std::size_t frame_offset = sym.frame_offset (); - std::size_t data_offset = sym.data_offset (); - - // Follow frame_offset access links to stack frame that holds - // the value. - - const stack_frame *frame = this; - - for (std::size_t i = 0; i < frame_offset; i++) - { - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - if (! frame) - error ("internal error: invalid access link in function call stack"); - - if (data_offset >= frame->size ()) - return octave_value (); - - switch (frame->get_scope_flag (data_offset)) + case GLOBAL: + return m_evaluator.global_varval (sym.name ()); + } + + error ("internal error: invalid switch case"); +} + +octave_value& script_stack_frame::varref (const symbol_record& sym) +{ + std::size_t frame_offset; + std::size_t data_offset; + get_val_offsets_with_insert (sym, frame_offset, data_offset); + + // Follow frame_offset access links to stack frame that holds + // the value. + + stack_frame *frame = this; + + for (std::size_t i = 0; i < frame_offset; i++) + { + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + if (data_offset >= frame->size ()) + frame->resize (data_offset+1); + + switch (frame->get_scope_flag (data_offset)) + { + case LOCAL: + return frame->varref (data_offset); + + case PERSISTENT: { - case LOCAL: - return frame->varval (data_offset); - - case PERSISTENT: - { - symbol_scope scope = frame->get_scope (); - - return scope.persistent_varval (data_offset); - } - - case GLOBAL: - return m_evaluator.global_varval (sym.name ()); - } - - error ("internal error: invalid switch case"); - } - - octave_value& user_fcn_stack_frame::varref (const symbol_record& sym) - { - std::size_t frame_offset = sym.frame_offset (); - std::size_t data_offset = sym.data_offset (); - - // Follow frame_offset access links to stack frame that holds - // the value. - - stack_frame *frame = this; - - for (std::size_t i = 0; i < frame_offset; i++) - { - std::shared_ptr nxt = frame->access_link (); - frame = nxt.get (); - } - - if (data_offset >= frame->size ()) - frame->resize (data_offset+1); - - switch (frame->get_scope_flag (data_offset)) - { - case LOCAL: - return frame->varref (data_offset); - - case PERSISTENT: - { - symbol_scope scope = frame->get_scope (); - - return scope.persistent_varref (data_offset); - } - - case GLOBAL: - return m_evaluator.global_varref (sym.name ()); + symbol_scope scope = frame->get_scope (); + + return scope.persistent_varref (data_offset); } - error ("internal error: invalid switch case"); - } - - void user_fcn_stack_frame::mark_scope (const symbol_record& sym, scope_flags flag) - { - std::size_t frame_offset = sym.frame_offset (); - - if (frame_offset > 0 && (flag == PERSISTENT || flag == GLOBAL)) - error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used"); - - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - resize (data_offset+1); - - set_scope_flag (data_offset, flag); - } - - void user_fcn_stack_frame::display (bool follow) const - { - std::ostream& os = octave_stdout; - - os << "-- [user_fcn_stack_frame] (" << this << ") --" << std::endl; - base_value_stack_frame::display (follow); - - os << "fcn: " << m_fcn->name () - << " (" << m_fcn->type_name () << ")" << std::endl; - - display_scope (os, get_scope ()); - } - - void user_fcn_stack_frame::accept (stack_frame_walker& sfw) - { - sfw.visit_user_fcn_stack_frame (*this); - } - - void user_fcn_stack_frame::break_closure_cycles (const std::shared_ptr& frame) - { - for (auto& val : m_values) - val.break_closure_cycles (frame); - - if (m_access_link) - m_access_link->break_closure_cycles (frame); - } - - symbol_record scope_stack_frame::insert_symbol (const std::string& name) - { - // There is no access link for scope frames, so there is no other - // frame to search in and the offset must be zero. - - symbol_record sym = m_scope.lookup_symbol (name); - - if (sym) - return sym; - - // If the symbol is not found, insert it. We only need to search in - // the local scope object. This operation should never fail. - - sym = m_scope.find_symbol (name); - - panic_unless (sym.is_valid ()); - + case GLOBAL: + return m_evaluator.global_varref (sym.name ()); + } + + error ("internal error: invalid switch case"); +} + +void script_stack_frame::mark_scope (const symbol_record& sym, + scope_flags flag) +{ + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + resize_and_update_script_offsets (sym); + + // Redirection to evaluation context for the script. + + std::size_t frame_offset = m_lexical_frame_offsets.at (data_offset); + data_offset = m_value_offsets.at (data_offset); + + if (frame_offset > 1) + error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used"); + + std::shared_ptr frame = access_link (); + + if (data_offset >= frame->size ()) + frame->resize (data_offset+1); + + frame->set_scope_flag (data_offset, flag); +} + +void script_stack_frame::display (bool follow) const +{ + std::ostream& os = octave_stdout; + + os << "-- [script_stack_frame] (" << this << ") --" << std::endl; + stack_frame::display (follow); + + os << "script: " << m_script->name () + << " (" << m_script->type_name () << ")" << std::endl; + + os << "lexical_offsets: " << m_lexical_frame_offsets.size () + << " elements:"; + + for (std::size_t i = 0; i < m_lexical_frame_offsets.size (); i++) + os << " " << m_lexical_frame_offsets.at (i); + os << std::endl; + + os << "value_offsets: " << m_value_offsets.size () << " elements:"; + for (std::size_t i = 0; i < m_value_offsets.size (); i++) + os << " " << m_value_offsets.at (i); + os << std::endl; + + display_scope (os, get_scope ()); +} + +void script_stack_frame::accept (stack_frame_walker& sfw) +{ + sfw.visit_script_stack_frame (*this); +} + +void base_value_stack_frame::display (bool follow) const +{ + std::ostream& os = octave_stdout; + + os << "-- [base_value_stack_frame] (" << this << ") --" << std::endl; + stack_frame::display (follow); + + os << "values: " << m_values.size () + << " elements (idx, scope flag, type):" << std::endl; + + for (std::size_t i = 0; i < m_values.size (); i++) + { + os << " (" << i << ", " << m_flags.at (i) << ", "; + + octave_value val = varval (i); + + os << (val.is_defined () ? val.type_name () : " UNDEFINED") << ")" + << std::endl; + } +} + +// If this is a nested scope, set access_link to nearest parent +// stack frame that corresponds to the lexical parent of this scope. + +std::shared_ptr +user_fcn_stack_frame::get_access_link (octave_user_function *fcn, + const std::shared_ptr& static_link) +{ + std::shared_ptr alink; + + symbol_scope fcn_scope = fcn->scope (); + + if (fcn_scope.is_nested ()) + { + if (! static_link) + error ("internal call stack error (invalid static link)"); + + symbol_scope caller_scope = static_link->get_scope (); + + int nesting_depth = fcn_scope.nesting_depth (); + int caller_nesting_depth = caller_scope.nesting_depth (); + + if (caller_nesting_depth < nesting_depth) + { + // FIXME: do we need to ensure that the called + // function is a child of the caller? Does it hurt + // to panic_unless this condition, at least for now? + + alink = static_link; + } + else + { + // FIXME: do we need to check that the parent of the + // called function is also a parent of the caller? + // Does it hurt to panic_unless this condition, at least + // for now? + + int links_to_follow = caller_nesting_depth - nesting_depth + 1; + + alink = static_link; + + while (alink && --links_to_follow >= 0) + alink = alink->access_link (); + + if (! alink) + error ("internal function nesting error (invalid access link)"); + } + } + + return alink; +} + +void user_fcn_stack_frame::clear_values (void) +{ + symbol_scope fcn_scope = m_fcn->scope (); + + const std::list& symbols = fcn_scope.symbol_list (); + + if (size () == 0) + return; + + for (const auto& sym : symbols) + { + std::size_t frame_offset = sym.frame_offset (); + + if (frame_offset > 0) + continue; + + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + continue; + + if (get_scope_flag (data_offset) == LOCAL) + { + octave_value& ref = m_values.at (data_offset); + + if (ref.get_count () == 1) + { + ref.call_object_destructor (); + ref = octave_value (); + } + } + } +} + +unwind_protect *user_fcn_stack_frame::unwind_protect_frame (void) +{ + if (! m_unwind_protect_frame) + m_unwind_protect_frame = new unwind_protect (); + + return m_unwind_protect_frame; +} + +symbol_record user_fcn_stack_frame::lookup_symbol (const std::string& name) const +{ + const stack_frame *frame = this; + + while (frame) + { + symbol_scope scope = frame->get_scope (); + + symbol_record sym = scope.lookup_symbol (name); + + if (sym) + return sym; + + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + return symbol_record (); +} + +symbol_record user_fcn_stack_frame::insert_symbol (const std::string& name) +{ + // If the symbols is already in the immediate scope, there is + // nothing more to do. + + symbol_scope scope = get_scope (); + + symbol_record sym = scope.lookup_symbol (name); + + if (sym) return sym; - } - - stack_frame::scope_flags - scope_stack_frame::scope_flag (const symbol_record& sym) const - { - // There is no access link for scope frames, so the frame - // offset must be zero. - - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - return LOCAL; - - return get_scope_flag (data_offset); - } - - octave_value scope_stack_frame::varval (const symbol_record& sym) const - { - // There is no access link for scope frames, so the frame - // offset must be zero. - - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - return octave_value (); - - switch (get_scope_flag (data_offset)) + + // FIXME: This needs some thought... We may need to add a symbol to + // a static workspace, but the symbol can never be defined as a + // variable. This currently works by tagging the added symbol as + // "added_static". Aside from the bad name, this doesn't seem like + // the best solution. Maybe scopes should have a separate set of + // symbols that may only be defined as functions? + + // Insert the symbol in the current scope. This is not possible for + // anonymous functions, nested functions, or functions that contain + // nested functions (their scopes will all be marked static). + + // if (scope.is_static ()) + // error ("can not add variable '%s' to a static workspace", + // name.c_str ()); + + // At this point, non-local references are not possible so we only + // need to look in the current scope and insert there. This + // operation should never fail. + + sym = scope.find_symbol (name); + + panic_unless (sym.is_valid ()); + + return sym; +} + +stack_frame::scope_flags +user_fcn_stack_frame::scope_flag (const symbol_record& sym) const +{ + std::size_t frame_offset = sym.frame_offset (); + std::size_t data_offset = sym.data_offset (); + + // Follow frame_offset access links to stack frame that holds + // the value. + + const stack_frame *frame = this; + + for (std::size_t i = 0; i < frame_offset; i++) + { + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + if (! frame) + error ("internal error: invalid access link in function call stack"); + + if (data_offset >= frame->size ()) + return LOCAL; + + return frame->get_scope_flag (data_offset); +} + +octave_value user_fcn_stack_frame::varval (const symbol_record& sym) const +{ + std::size_t frame_offset = sym.frame_offset (); + std::size_t data_offset = sym.data_offset (); + + // Follow frame_offset access links to stack frame that holds + // the value. + + const stack_frame *frame = this; + + for (std::size_t i = 0; i < frame_offset; i++) + { + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + if (! frame) + error ("internal error: invalid access link in function call stack"); + + if (data_offset >= frame->size ()) + return octave_value (); + + switch (frame->get_scope_flag (data_offset)) + { + case LOCAL: + return frame->varval (data_offset); + + case PERSISTENT: { - case LOCAL: - return m_values.at (data_offset); - - case PERSISTENT: - return m_scope.persistent_varval (data_offset); - - case GLOBAL: - return m_evaluator.global_varval (sym.name ()); + symbol_scope scope = frame->get_scope (); + + return scope.persistent_varval (data_offset); + } + + case GLOBAL: + return m_evaluator.global_varval (sym.name ()); + } + + error ("internal error: invalid switch case"); +} + +octave_value& user_fcn_stack_frame::varref (const symbol_record& sym) +{ + std::size_t frame_offset = sym.frame_offset (); + std::size_t data_offset = sym.data_offset (); + + // Follow frame_offset access links to stack frame that holds + // the value. + + stack_frame *frame = this; + + for (std::size_t i = 0; i < frame_offset; i++) + { + std::shared_ptr nxt = frame->access_link (); + frame = nxt.get (); + } + + if (data_offset >= frame->size ()) + frame->resize (data_offset+1); + + switch (frame->get_scope_flag (data_offset)) + { + case LOCAL: + return frame->varref (data_offset); + + case PERSISTENT: + { + symbol_scope scope = frame->get_scope (); + + return scope.persistent_varref (data_offset); } - error ("internal error: invalid switch case"); - } - - octave_value& scope_stack_frame::varref (const symbol_record& sym) - { - // There is no access link for scope frames, so the frame - // offset must be zero. - - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - resize (data_offset+1); - - switch (get_scope_flag (data_offset)) - { - case LOCAL: - return m_values.at (data_offset); - - case PERSISTENT: - return m_scope.persistent_varref (data_offset); - - case GLOBAL: - return m_evaluator.global_varref (sym.name ()); - } - - error ("internal error: invalid switch case"); - } - - void scope_stack_frame::mark_scope (const symbol_record& sym, - scope_flags flag) - { - // There is no access link for scope frames, so the frame - // offset must be zero. - - std::size_t data_offset = sym.data_offset (); - - if (data_offset >= size ()) - resize (data_offset+1); - - set_scope_flag (data_offset, flag); - } - - void scope_stack_frame::display (bool follow) const - { - std::ostream& os = octave_stdout; - - os << "-- [scope_stack_frame] (" << this << ") --" << std::endl; - base_value_stack_frame::display (follow); - - display_scope (os, m_scope); - } - - void scope_stack_frame::accept (stack_frame_walker& sfw) - { - sfw.visit_scope_stack_frame (*this); - } + case GLOBAL: + return m_evaluator.global_varref (sym.name ()); + } + + error ("internal error: invalid switch case"); +} + +void user_fcn_stack_frame::mark_scope (const symbol_record& sym, scope_flags flag) +{ + std::size_t frame_offset = sym.frame_offset (); + + if (frame_offset > 0 && (flag == PERSISTENT || flag == GLOBAL)) + error ("variables must be made PERSISTENT or GLOBAL in the first scope in which they are used"); + + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + resize (data_offset+1); + + set_scope_flag (data_offset, flag); +} + +void user_fcn_stack_frame::display (bool follow) const +{ + std::ostream& os = octave_stdout; + + os << "-- [user_fcn_stack_frame] (" << this << ") --" << std::endl; + base_value_stack_frame::display (follow); + + os << "fcn: " << m_fcn->name () + << " (" << m_fcn->type_name () << ")" << std::endl; + + display_scope (os, get_scope ()); +} + +void user_fcn_stack_frame::accept (stack_frame_walker& sfw) +{ + sfw.visit_user_fcn_stack_frame (*this); +} + +void user_fcn_stack_frame::break_closure_cycles (const std::shared_ptr& frame) +{ + for (auto& val : m_values) + val.break_closure_cycles (frame); + + if (m_access_link) + m_access_link->break_closure_cycles (frame); +} + +symbol_record scope_stack_frame::insert_symbol (const std::string& name) +{ + // There is no access link for scope frames, so there is no other + // frame to search in and the offset must be zero. + + symbol_record sym = m_scope.lookup_symbol (name); + + if (sym) + return sym; + + // If the symbol is not found, insert it. We only need to search in + // the local scope object. This operation should never fail. + + sym = m_scope.find_symbol (name); + + panic_unless (sym.is_valid ()); + + return sym; +} + +stack_frame::scope_flags +scope_stack_frame::scope_flag (const symbol_record& sym) const +{ + // There is no access link for scope frames, so the frame + // offset must be zero. + + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + return LOCAL; + + return get_scope_flag (data_offset); +} + +octave_value scope_stack_frame::varval (const symbol_record& sym) const +{ + // There is no access link for scope frames, so the frame + // offset must be zero. + + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + return octave_value (); + + switch (get_scope_flag (data_offset)) + { + case LOCAL: + return m_values.at (data_offset); + + case PERSISTENT: + return m_scope.persistent_varval (data_offset); + + case GLOBAL: + return m_evaluator.global_varval (sym.name ()); + } + + error ("internal error: invalid switch case"); +} + +octave_value& scope_stack_frame::varref (const symbol_record& sym) +{ + // There is no access link for scope frames, so the frame + // offset must be zero. + + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + resize (data_offset+1); + + switch (get_scope_flag (data_offset)) + { + case LOCAL: + return m_values.at (data_offset); + + case PERSISTENT: + return m_scope.persistent_varref (data_offset); + + case GLOBAL: + return m_evaluator.global_varref (sym.name ()); + } + + error ("internal error: invalid switch case"); +} + +void scope_stack_frame::mark_scope (const symbol_record& sym, + scope_flags flag) +{ + // There is no access link for scope frames, so the frame + // offset must be zero. + + std::size_t data_offset = sym.data_offset (); + + if (data_offset >= size ()) + resize (data_offset+1); + + set_scope_flag (data_offset, flag); +} + +void scope_stack_frame::display (bool follow) const +{ + std::ostream& os = octave_stdout; + + os << "-- [scope_stack_frame] (" << this << ") --" << std::endl; + base_value_stack_frame::display (follow); + + display_scope (os, m_scope); +} + +void scope_stack_frame::accept (stack_frame_walker& sfw) +{ + sfw.visit_scope_stack_frame (*this); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/stack-frame.h --- a/libinterp/corefcn/stack-frame.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/stack-frame.h Thu Dec 01 20:05:44 2022 -0800 @@ -99,501 +99,501 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; - class symbol_info_list; - class unwind_protect; +class tree_evaluator; +class symbol_info_list; +class unwind_protect; - class stack_frame_walker; +class stack_frame_walker; - class stack_frame - { - public: +class stack_frame +{ +public: - typedef std::map local_vars_map; + typedef std::map local_vars_map; - // Markers indicating the type of a variable. Values for local - // variables are stored in the stack frame. Values for - // global variables are stored in the tree_evaluator object that - // contains the stack frame. Values for persistent variables are - // stored in the function scope corresponding to the stack frame. + // Markers indicating the type of a variable. Values for local + // variables are stored in the stack frame. Values for + // global variables are stored in the tree_evaluator object that + // contains the stack frame. Values for persistent variables are + // stored in the function scope corresponding to the stack frame. - enum scope_flags - { - LOCAL, - GLOBAL, - PERSISTENT - }; + enum scope_flags + { + LOCAL, + GLOBAL, + PERSISTENT + }; - // Index into the list of automatic variables for user-defined - // function stack frames. + // Index into the list of automatic variables for user-defined + // function stack frames. - enum auto_var_type - { - ARG_NAMES, - IGNORED, - NARGIN, - NARGOUT, - SAVED_WARNING_STATES, - NUM_AUTO_VARS - }; + enum auto_var_type + { + ARG_NAMES, + IGNORED, + NARGIN, + NARGOUT, + SAVED_WARNING_STATES, + NUM_AUTO_VARS + }; - stack_frame (void) = delete; + stack_frame (void) = delete; - stack_frame (tree_evaluator& tw, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const std::shared_ptr& access_link) - : m_evaluator (tw), m_is_closure_context (false), - m_line (-1), m_column (-1), m_index (index), - m_parent_link (parent_link), m_static_link (static_link), - m_access_link (access_link), m_dispatch_class () - { } + stack_frame (tree_evaluator& tw, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const std::shared_ptr& access_link) + : m_evaluator (tw), m_is_closure_context (false), + m_line (-1), m_column (-1), m_index (index), + m_parent_link (parent_link), m_static_link (static_link), + m_access_link (access_link), m_dispatch_class () + { } - // Compiled function. - static stack_frame * - create (tree_evaluator& tw, octave_function *fcn, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link); + // Compiled function. + static stack_frame * + create (tree_evaluator& tw, octave_function *fcn, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link); - // Script. - static stack_frame * - create (tree_evaluator& tw, octave_user_script *script, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link); + // Script. + static stack_frame * + create (tree_evaluator& tw, octave_user_script *script, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link); - // User-defined function. - static stack_frame * - create (tree_evaluator& tw, octave_user_function *fcn, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const std::shared_ptr& access_link = std::shared_ptr ()); + // User-defined function. + static stack_frame * + create (tree_evaluator& tw, octave_user_function *fcn, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const std::shared_ptr& access_link = std::shared_ptr ()); - // Anonymous user-defined function with init vars. - static stack_frame * - create (tree_evaluator& tw, octave_user_function *fcn, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link, - const local_vars_map& local_vars, - const std::shared_ptr& access_link = std::shared_ptr ()); + // Anonymous user-defined function with init vars. + static stack_frame * + create (tree_evaluator& tw, octave_user_function *fcn, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link, + const local_vars_map& local_vars, + const std::shared_ptr& access_link = std::shared_ptr ()); - // Scope. - static stack_frame * - create (tree_evaluator& tw, const symbol_scope& scope, std::size_t index, - const std::shared_ptr& parent_link, - const std::shared_ptr& static_link); + // Scope. + static stack_frame * + create (tree_evaluator& tw, const symbol_scope& scope, std::size_t index, + const std::shared_ptr& parent_link, + const std::shared_ptr& static_link); - stack_frame (const stack_frame& elt) = default; + stack_frame (const stack_frame& elt) = default; - stack_frame& operator = (const stack_frame& elt) = delete; + stack_frame& operator = (const stack_frame& elt) = delete; - virtual ~stack_frame (void) = default; + virtual ~stack_frame (void) = default; - // FIXME: It would be nice to eliminate these but there are a few - // places where we still need to know the specific type of the - // stack frame that we are handling. + // FIXME: It would be nice to eliminate these but there are a few + // places where we still need to know the specific type of the + // stack frame that we are handling. - virtual bool is_compiled_fcn_frame (void) const { return false; } - virtual bool is_user_script_frame (void) const { return false; } - virtual bool is_user_fcn_frame (void) const { return false; } - virtual bool is_scope_frame (void) const { return false; } + virtual bool is_compiled_fcn_frame (void) const { return false; } + virtual bool is_user_script_frame (void) const { return false; } + virtual bool is_user_fcn_frame (void) const { return false; } + virtual bool is_scope_frame (void) const { return false; } - virtual void clear_values (void); + virtual void clear_values (void); - std::size_t index (void) const { return m_index; } + std::size_t index (void) const { return m_index; } - void line (int l) { m_line = l; } - int line (void) const { return m_line; } + void line (int l) { m_line = l; } + int line (void) const { return m_line; } - void column (int c) { m_column = c; } - int column (void) const { return m_column; } + void column (int c) { m_column = c; } + int column (void) const { return m_column; } - std::string fcn_file_name (void) const - { - octave_function *fcn = function (); + std::string fcn_file_name (void) const + { + octave_function *fcn = function (); - return fcn ? fcn->fcn_file_name () : ""; - } + return fcn ? fcn->fcn_file_name () : ""; + } - std::string fcn_name (bool print_subfn = true) const - { - std::string retval; + std::string fcn_name (bool print_subfn = true) const + { + std::string retval; - octave_function *fcn = function (); + octave_function *fcn = function (); - if (fcn) - { - std::string parent_fcn_name = fcn->parent_fcn_name (); + if (fcn) + { + std::string parent_fcn_name = fcn->parent_fcn_name (); - if (print_subfn && ! parent_fcn_name.empty ()) - retval = parent_fcn_name + '>'; + if (print_subfn && ! parent_fcn_name.empty ()) + retval = parent_fcn_name + '>'; - if (fcn->is_anonymous_function ()) - retval += "@"; - else - retval += fcn->name (); - } - else - retval = ""; + if (fcn->is_anonymous_function ()) + retval += "@"; + else + retval += fcn->name (); + } + else + retval = ""; - return retval; - } + return retval; + } - virtual symbol_scope get_scope (void) const = 0; + virtual symbol_scope get_scope (void) const = 0; - virtual octave_function * function (void) const { return nullptr; } + virtual octave_function * function (void) const { return nullptr; } - virtual unwind_protect * unwind_protect_frame (void) { return nullptr; } + virtual unwind_protect * unwind_protect_frame (void) { return nullptr; } - symbol_info_list - make_symbol_info_list (const std::list& symrec_list) const; + symbol_info_list + make_symbol_info_list (const std::list& symrec_list) const; - octave_value who (const string_vector& patterns, bool have_regexp, - bool return_list, bool verbose, - const std::string& whos_line_fmt, - const std::string& msg); + octave_value who (const string_vector& patterns, bool have_regexp, + bool return_list, bool verbose, + const std::string& whos_line_fmt, + const std::string& msg); - symbol_info_list all_variables (void); + symbol_info_list all_variables (void); - octave_value workspace (void); + octave_value workspace (void); - std::list variable_names (void) const; + std::list variable_names (void) const; - // Look for named symbol visible from current scope. Don't - // attempt to insert if missing. - virtual symbol_record lookup_symbol (const std::string&) const = 0; + // Look for named symbol visible from current scope. Don't + // attempt to insert if missing. + virtual symbol_record lookup_symbol (const std::string&) const = 0; - // Look for named symbol visible from current scope. Attempt to - // insert if missing. - virtual symbol_record insert_symbol (const std::string&) = 0; + // Look for named symbol visible from current scope. Attempt to + // insert if missing. + virtual symbol_record insert_symbol (const std::string&) = 0; - symbol_info_list glob_symbol_info (const std::string& pattern); + symbol_info_list glob_symbol_info (const std::string& pattern); - symbol_info_list regexp_symbol_info (const std::string& pattern); + symbol_info_list regexp_symbol_info (const std::string& pattern); - symbol_info_list get_symbol_info (void) - { - return all_variables (); - } + symbol_info_list get_symbol_info (void) + { + return all_variables (); + } - void make_persistent (const symbol_record& sym) - { - if (sym.is_formal ()) - { - std::string nm = sym.name (); - error ("can't make function parameter %s persistent", nm.c_str ()); - } + void make_persistent (const symbol_record& sym) + { + if (sym.is_formal ()) + { + std::string nm = sym.name (); + error ("can't make function parameter %s persistent", nm.c_str ()); + } - if (is_global (sym)) - { - std::string nm = sym.name (); - error ("can't make global variable '%s' persistent", nm.c_str ()); - } + if (is_global (sym)) + { + std::string nm = sym.name (); + error ("can't make global variable '%s' persistent", nm.c_str ()); + } - install_variable (sym, octave_value (), false); + install_variable (sym, octave_value (), false); - mark_persistent (sym); - } + mark_persistent (sym); + } - void make_global (const symbol_record& sym) - { - if (is_persistent (sym)) - { - std::string nm = sym.name (); - error ("can't make persistent variable '%s' global", nm.c_str ()); - } + void make_global (const symbol_record& sym) + { + if (is_persistent (sym)) + { + std::string nm = sym.name (); + error ("can't make persistent variable '%s' global", nm.c_str ()); + } - install_variable (sym, octave_value (), true); + install_variable (sym, octave_value (), true); - mark_global (sym); - } + mark_global (sym); + } - std::shared_ptr - parent_link (void) const {return m_parent_link; } + std::shared_ptr + parent_link (void) const {return m_parent_link; } - std::shared_ptr - static_link (void) const {return m_static_link; } + std::shared_ptr + static_link (void) const {return m_static_link; } - std::shared_ptr - access_link (void) const {return m_access_link; } + std::shared_ptr + access_link (void) const {return m_access_link; } - virtual std::size_t size (void) const; + virtual std::size_t size (void) const; - virtual void resize (std::size_t); + virtual void resize (std::size_t); - void mark_global (const symbol_record& sym) - { - mark_scope (sym, GLOBAL); - } + void mark_global (const symbol_record& sym) + { + mark_scope (sym, GLOBAL); + } - void unmark_global (const symbol_record& sym) - { - mark_scope (sym, LOCAL); - } + void unmark_global (const symbol_record& sym) + { + mark_scope (sym, LOCAL); + } - void mark_persistent (const symbol_record& sym) - { - mark_scope (sym, PERSISTENT); - } + void mark_persistent (const symbol_record& sym) + { + mark_scope (sym, PERSISTENT); + } - void unmark_persistent (const symbol_record& sym) - { - mark_scope (sym, LOCAL); - } + void unmark_persistent (const symbol_record& sym) + { + mark_scope (sym, LOCAL); + } - bool is_defined (const symbol_record& sym) const - { - octave_value val = varval (sym); + bool is_defined (const symbol_record& sym) const + { + octave_value val = varval (sym); - return val.is_defined (); - } + return val.is_defined (); + } - bool is_variable (const symbol_record& sym) const - { - octave_value val = varval (sym); + bool is_variable (const symbol_record& sym) const + { + octave_value val = varval (sym); - return val.is_defined (); - } + return val.is_defined (); + } - bool is_variable (const std::string& name) const - { - symbol_record sym = lookup_symbol (name); + bool is_variable (const std::string& name) const + { + symbol_record sym = lookup_symbol (name); - return sym ? is_variable (sym) : false; - } + return sym ? is_variable (sym) : false; + } - bool is_local_variable (const std::string& name) const - { - symbol_record sym = lookup_symbol (name); + bool is_local_variable (const std::string& name) const + { + symbol_record sym = lookup_symbol (name); - return sym ? (is_variable (sym) && ! is_global (sym)) : false; - } + return sym ? (is_variable (sym) && ! is_global (sym)) : false; + } - bool is_object (const symbol_record& sym) const - { - octave_value val = varval (sym); + bool is_object (const symbol_record& sym) const + { + octave_value val = varval (sym); - return val.isobject (); - } + return val.isobject (); + } - bool is_object (const std::string& name) const - { - symbol_record sym = lookup_symbol (name); + bool is_object (const std::string& name) const + { + symbol_record sym = lookup_symbol (name); - return sym ? is_object (sym) : false; - } + return sym ? is_object (sym) : false; + } - virtual scope_flags scope_flag (const symbol_record&) const = 0; + virtual scope_flags scope_flag (const symbol_record&) const = 0; - virtual scope_flags get_scope_flag (std::size_t) const; + virtual scope_flags get_scope_flag (std::size_t) const; - virtual void set_scope_flag (std::size_t, scope_flags); + virtual void set_scope_flag (std::size_t, scope_flags); - bool is_global (const symbol_record& sym) const - { - return scope_flag (sym) == GLOBAL; - } + bool is_global (const symbol_record& sym) const + { + return scope_flag (sym) == GLOBAL; + } - bool is_global (const std::string& name) const - { - symbol_record sym = lookup_symbol (name); + bool is_global (const std::string& name) const + { + symbol_record sym = lookup_symbol (name); - return sym ? is_global (sym) : false; - } + return sym ? is_global (sym) : false; + } - bool is_persistent (const symbol_record& sym) const - { - return scope_flag (sym) == PERSISTENT; - } + bool is_persistent (const symbol_record& sym) const + { + return scope_flag (sym) == PERSISTENT; + } - bool is_persistent (const std::string& name) const - { - symbol_record sym = lookup_symbol (name); + bool is_persistent (const std::string& name) const + { + symbol_record sym = lookup_symbol (name); - return sym ? is_persistent (sym) : false; - } + return sym ? is_persistent (sym) : false; + } - void install_variable (const symbol_record& sym, - const octave_value& value, bool global); + void install_variable (const symbol_record& sym, + const octave_value& value, bool global); - void install_variable (const std::string& name, - const octave_value& value, bool global) - { - symbol_record sym = insert_symbol (name); + void install_variable (const std::string& name, + const octave_value& value, bool global) + { + symbol_record sym = insert_symbol (name); - install_variable (sym, value, global); - } + install_variable (sym, value, global); + } - virtual octave_value get_auto_fcn_var (auto_var_type) const = 0; + virtual octave_value get_auto_fcn_var (auto_var_type) const = 0; - virtual void set_auto_fcn_var (auto_var_type, const octave_value&) = 0; + virtual void set_auto_fcn_var (auto_var_type, const octave_value&) = 0; - virtual octave_value varval (const symbol_record& sym) const = 0;; + virtual octave_value varval (const symbol_record& sym) const = 0;; - virtual octave_value varval (std::size_t data_offset) const; + virtual octave_value varval (std::size_t data_offset) const; - octave_value varval (const std::string& name) const - { - symbol_record sym = lookup_symbol (name); + octave_value varval (const std::string& name) const + { + symbol_record sym = lookup_symbol (name); - return sym ? varval (sym) : octave_value (); - } + return sym ? varval (sym) : octave_value (); + } - virtual octave_value& varref (const symbol_record& sym) = 0; + virtual octave_value& varref (const symbol_record& sym) = 0; - virtual octave_value& varref (std::size_t data_offset); + virtual octave_value& varref (std::size_t data_offset); - void assign (const symbol_record& sym, const octave_value& val) - { - octave_value& lhs = varref (sym); + void assign (const symbol_record& sym, const octave_value& val) + { + octave_value& lhs = varref (sym); - if (lhs.get_count () == 1) - lhs.call_object_destructor (); + if (lhs.get_count () == 1) + lhs.call_object_destructor (); - // Regularize a null matrix if stored into a variable. - lhs = val.storable_value (); - } + // Regularize a null matrix if stored into a variable. + lhs = val.storable_value (); + } - void assign (const std::string& name, const octave_value& val) - { - symbol_record sym = insert_symbol (name); + void assign (const std::string& name, const octave_value& val) + { + symbol_record sym = insert_symbol (name); - assign (sym, val); - } + assign (sym, val); + } - void assign (octave_value::assign_op op, const symbol_record& sym, - const std::string& type, - const std::list& idx, - const octave_value& rhs) - { - if (idx.empty ()) - { - if (op == octave_value::op_asn_eq) - assign (sym, rhs); - else - varref (sym).assign (op, rhs); - } - else - varref (sym).assign (op, type, idx, rhs); - } + void assign (octave_value::assign_op op, const symbol_record& sym, + const std::string& type, + const std::list& idx, + const octave_value& rhs) + { + if (idx.empty ()) + { + if (op == octave_value::op_asn_eq) + assign (sym, rhs); + else + varref (sym).assign (op, rhs); + } + else + varref (sym).assign (op, type, idx, rhs); + } - void non_const_unary_op (octave_value::unary_op op, - const symbol_record& sym, - const std::string& type, - const std::list& idx) - { - if (idx.empty ()) - varref (sym).non_const_unary_op (op); - else - varref (sym).non_const_unary_op (op, type, idx); - } + void non_const_unary_op (octave_value::unary_op op, + const symbol_record& sym, + const std::string& type, + const std::list& idx) + { + if (idx.empty ()) + varref (sym).non_const_unary_op (op); + else + varref (sym).non_const_unary_op (op, type, idx); + } - octave_value value (const symbol_record& sym, const std::string& type, - const std::list& idx) const - { - octave_value retval = varval (sym); + octave_value value (const symbol_record& sym, const std::string& type, + const std::list& idx) const + { + octave_value retval = varval (sym); - if (! idx.empty ()) - { - if (retval.is_constant ()) - retval = retval.subsref (type, idx); - else - { - octave_value_list t = retval.subsref (type, idx, 1); + if (! idx.empty ()) + { + if (retval.is_constant ()) + retval = retval.subsref (type, idx); + else + { + octave_value_list t = retval.subsref (type, idx, 1); - retval = t.length () > 0 ? t(0) : octave_value (); - } - } + retval = t.length () > 0 ? t(0) : octave_value (); + } + } - return retval; - } + return retval; + } - octave_value find_subfunction (const std::string& name) const - { - symbol_scope scope = get_scope (); + octave_value find_subfunction (const std::string& name) const + { + symbol_scope scope = get_scope (); - return scope.find_subfunction (name); - } + return scope.find_subfunction (name); + } - void clear (const symbol_record& sym) - { - if (is_global (sym)) - unmark_global (sym); + void clear (const symbol_record& sym) + { + if (is_global (sym)) + unmark_global (sym); - assign (sym, octave_value ()); + assign (sym, octave_value ()); - if (is_persistent (sym)) - unmark_persistent (sym); - } + if (is_persistent (sym)) + unmark_persistent (sym); + } - void clear_objects (void); + void clear_objects (void); - void clear_variable (const std::string& name); + void clear_variable (const std::string& name); - void clear_variable_pattern (const std::string& pattern); - void clear_variable_pattern (const string_vector& patterns); + void clear_variable_pattern (const std::string& pattern); + void clear_variable_pattern (const string_vector& patterns); - void clear_variable_regexp (const std::string& pattern); - void clear_variable_regexp (const string_vector& patterns); + void clear_variable_regexp (const std::string& pattern); + void clear_variable_regexp (const string_vector& patterns); - void clear_variables (void); + void clear_variables (void); - std::string get_dispatch_class (void) const { return m_dispatch_class; } + std::string get_dispatch_class (void) const { return m_dispatch_class; } - void set_dispatch_class (const std::string& class_name) - { - m_dispatch_class = class_name; - } + void set_dispatch_class (const std::string& class_name) + { + m_dispatch_class = class_name; + } - void display_stopped_in_message (std::ostream& os) const; + void display_stopped_in_message (std::ostream& os) const; - virtual void mark_scope (const symbol_record&, scope_flags) = 0; + virtual void mark_scope (const symbol_record&, scope_flags) = 0; - virtual void display (bool follow = true) const; + virtual void display (bool follow = true) const; - virtual void accept (stack_frame_walker& sfw) = 0; + virtual void accept (stack_frame_walker& sfw) = 0; - virtual void break_closure_cycles (const std::shared_ptr&) { } + virtual void break_closure_cycles (const std::shared_ptr&) { } - void mark_closure_context (void) { m_is_closure_context = true; } - bool is_closure_context (void) const { return m_is_closure_context; } + void mark_closure_context (void) { m_is_closure_context = true; } + bool is_closure_context (void) const { return m_is_closure_context; } - protected: +protected: - // Reference to the call stack that contains this frame. Global - // variables are stored in the call stack. This link gives us - // immediate access to them. - tree_evaluator& m_evaluator; + // Reference to the call stack that contains this frame. Global + // variables are stored in the call stack. This link gives us + // immediate access to them. + tree_evaluator& m_evaluator; - // TRUE if this stack frame is saved with a handle to a nested - // function (closure). - bool m_is_closure_context; + // TRUE if this stack frame is saved with a handle to a nested + // function (closure). + bool m_is_closure_context; - // The line and column of the source file where this stack frame - // was created. Used to print stack traces. - int m_line; - int m_column; + // The line and column of the source file where this stack frame + // was created. Used to print stack traces. + int m_line; + int m_column; - // Index in call stack. - std::size_t m_index; + // Index in call stack. + std::size_t m_index; - // Pointer to the nearest parent frame. May include compiled - // functions. - std::shared_ptr m_parent_link; + // Pointer to the nearest parent frame. May include compiled + // functions. + std::shared_ptr m_parent_link; - // Pointer to the nearest parent frame that contains variable - // information (script, function, or scope). This link skips over - // compiled function parent frames. - std::shared_ptr m_static_link; + // Pointer to the nearest parent frame that contains variable + // information (script, function, or scope). This link skips over + // compiled function parent frames. + std::shared_ptr m_static_link; - // Pointer to the nearest lexical parent frame. Used to access - // non-local variables for nested and anonymous functions or as a - // link to the parent frame in which a script is executed. - std::shared_ptr m_access_link; + // Pointer to the nearest lexical parent frame. Used to access + // non-local variables for nested and anonymous functions or as a + // link to the parent frame in which a script is executed. + std::shared_ptr m_access_link; - // Allow function handles to temporarily store their dispatch class - // in the call stack. - std::string m_dispatch_class; - }; + // Allow function handles to temporarily store their dispatch class + // in the call stack. + std::string m_dispatch_class; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/stream-euler.cc --- a/libinterp/corefcn/stream-euler.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/stream-euler.cc Thu Dec 01 20:05:44 2022 -0800 @@ -137,17 +137,18 @@ is_in_definition_set2d (const Cell2 X, const octave_idx_type cols, const octave_idx_type rows) { - return ( (((X.idx >= 0) && (X.idx < cols-1)) || - ((X.idx == cols-1) && (X.fcx == 0.0))) && - (((X.idy >= 0) && (X.idy < rows-1)) || - ((X.idy == rows-1) && (X.fcy == 0.0))) ); + return ( (((X.idx >= 0) && (X.idx < cols-1)) || + ((X.idx == cols-1) && (X.fcx == 0.0))) && + (((X.idy >= 0) && (X.idy < rows-1)) || + ((X.idy == rows-1) && (X.fcy == 0.0))) ); } static inline Vector2 add2d (const Cell2 X, const Vector2 Y) { Vector2 Z = {X.idx + X.fcx + Y.x, - X.idy + X.fcy + Y.y}; + X.idy + X.fcy + Y.y + }; return (Z); } @@ -243,7 +244,8 @@ // Runge Kutta - Heun's Scheme const Vector2 S = {0.5 * (S0.x + S1.x), - 0.5 * (S0.y + S1.y)}; + 0.5 * (S0.y + S1.y) + }; Xnxt = add2d (X0f, S); X0f = vector_to_cell2d (Xnxt); @@ -306,7 +308,8 @@ { Vector3 Z = {X.idx + X.fcx + Y.x, X.idy + X.fcy + Y.y, - X.idz + X.fcz + Y.z}; + X.idz + X.fcz + Y.z + }; return (Z); } @@ -417,7 +420,8 @@ // Runge Kutta - Heun's Scheme const Vector3 S = {0.5 * (S0.x + S1.x), 0.5 * (S0.y + S1.y), - 0.5 * (S0.z + S1.z)}; + 0.5 * (S0.z + S1.z) + }; Xnxt = add3d (X0f, S); X0f = vector_to_cell3d (Xnxt); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/strfns.cc --- a/libinterp/corefcn/strfns.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/strfns.cc Thu Dec 01 20:05:44 2022 -0800 @@ -1219,7 +1219,8 @@ if (nargin < 1 || nargin > 3) print_usage (); - string_vector s = args(0).xstring_vector_value ("list_in_columns: ARG must be a cellstr or char array"); + string_vector s = args( + 0).xstring_vector_value ("list_in_columns: ARG must be a cellstr or char array"); int width = -1; diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/svd.cc --- a/libinterp/corefcn/svd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/svd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -199,9 +199,9 @@ error ("svd: cannot take SVD of matrix containing Inf or NaN values"); math::svd result - (tmp, - svd_type (nargin, nargout, args, tmp), - svd_driver ()); + (tmp, + svd_type (nargin, nargout, args, tmp), + svd_driver ()); FloatDiagMatrix sigma = result.singular_values (); @@ -223,9 +223,9 @@ error ("svd: cannot take SVD of matrix containing Inf or NaN values"); math::svd result - (ctmp, - svd_type (nargin, nargout, args, ctmp), - svd_driver ()); + (ctmp, + svd_type (nargin, nargout, args, ctmp), + svd_driver ()); FloatDiagMatrix sigma = result.singular_values (); @@ -250,9 +250,9 @@ error ("svd: cannot take SVD of matrix containing Inf or NaN values"); math::svd result - (tmp, - svd_type (nargin, nargout, args, tmp), - svd_driver ()); + (tmp, + svd_type (nargin, nargout, args, tmp), + svd_driver ()); DiagMatrix sigma = result.singular_values (); @@ -274,9 +274,9 @@ error ("svd: cannot take SVD of matrix containing Inf or NaN values"); math::svd result - (ctmp, - svd_type (nargin, nargout, args, ctmp), - svd_driver ()); + (ctmp, + svd_type (nargin, nargout, args, ctmp), + svd_driver ()); DiagMatrix sigma = result.singular_values (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/syminfo.cc --- a/libinterp/corefcn/syminfo.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/syminfo.cc Thu Dec 01 20:05:44 2022 -0800 @@ -42,539 +42,539 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - symbol_info::display_line (std::ostream& os, - const std::list& params) const - { - std::string dims_str = m_value.get_dims_str (); - - auto i = params.begin (); - - preserve_stream_state stream_state (os); - - while (i != params.end ()) - { - whos_parameter param = *i; - - if (param.command != '\0') - { - // Do the actual printing. - - switch (param.modifier) - { - case 'l': - os << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - break; - - case 'r': - os << std::setiosflags (std::ios::right) - << std::setw (param.parameter_length); - break; +void +symbol_info::display_line (std::ostream& os, + const std::list& params) const +{ + std::string dims_str = m_value.get_dims_str (); - case 'c': - if (param.command == 's') - { - int front = param.first_parameter_length - - dims_str.find ('x'); - int back = param.parameter_length - - dims_str.length () - - front; - front = (front > 0) ? front : 0; - back = (back > 0) ? back : 0; + auto i = params.begin (); + + preserve_stream_state stream_state (os); - os << std::setiosflags (std::ios::left) - << std::setw (front) - << "" - << std::resetiosflags (std::ios::left) - << dims_str - << std::setiosflags (std::ios::left) - << std::setw (back) - << "" - << std::resetiosflags (std::ios::left); - } - else - { - os << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - } - break; - - default: - error ("whos_line_format: modifier '%c' unknown", - param.modifier); - } + while (i != params.end ()) + { + whos_parameter param = *i; - switch (param.command) - { - case 'a': - { - char tmp[6]; - - tmp[0] = (m_is_complex ? 'c' : ' '); - tmp[1] = (m_is_sparse ? 's' : ' '); - tmp[2] = (m_is_formal ? 'f' : ' '); - tmp[3] = (m_is_global ? 'g' : ' '); - tmp[4] = (m_is_persistent ? 'p' : ' '); - tmp[5] = 0; - - os << tmp; - } - break; - - case 'b': - os << m_value.byte_size (); - break; - - case 'c': - os << m_value.class_name (); - break; - - case 'e': - os << m_value.numel (); - break; - - case 'n': - os << m_name; - break; + if (param.command != '\0') + { + // Do the actual printing. - case 's': - if (param.modifier != 'c') - os << dims_str; - break; - - case 't': - os << m_value.type_name (); - break; - - default: - error ("whos_line_format: command '%c' unknown", - param.command); - } + switch (param.modifier) + { + case 'l': + os << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + break; - os << std::resetiosflags (std::ios::left) - << std::resetiosflags (std::ios::right); - i++; - } - else - { - os << param.text; - i++; - } - } - } - - // FIXME: should we be using std::map instead of a list? - - octave_value symbol_info_list::varval (const std::string& name) const - { - for (const auto& syminfo : m_lst) - { - if (name == syminfo.name ()) - return syminfo.value (); - } + case 'r': + os << std::setiosflags (std::ios::right) + << std::setw (param.parameter_length); + break; - return octave_value (); - } - - std::list symbol_info_list::names (void) const - { - std::list retval; - - for (const auto& syminfo : m_lst) - retval.push_back (syminfo.name ()); - - return retval; - } - - octave_map - symbol_info_list::map_value (const std::string& caller_function_name, - int nesting_level) const - { - std::size_t len = m_lst.size (); - - Cell name_info (len, 1); - Cell size_info (len, 1); - Cell bytes_info (len, 1); - Cell class_info (len, 1); - Cell global_info (len, 1); - Cell sparse_info (len, 1); - Cell complex_info (len, 1); - Cell nesting_info (len, 1); - Cell persistent_info (len, 1); - - std::size_t j = 0; - - for (const auto& syminfo : m_lst) - { - octave_scalar_map ni; - - ni.assign ("function", caller_function_name); - ni.assign ("level", nesting_level); - - name_info(j) = syminfo.name (); - global_info(j) = syminfo.is_global (); - persistent_info(j) = syminfo.is_persistent (); - - octave_value val = syminfo.value (); - - size_info(j) = val.size (); - bytes_info(j) = val.byte_size (); - class_info(j) = val.class_name (); - sparse_info(j) = val.issparse (); - complex_info(j) = val.iscomplex (); - nesting_info(j) = ni; - - j++; - } - - octave_map info; - - info.assign ("name", name_info); - info.assign ("size", size_info); - info.assign ("bytes", bytes_info); - info.assign ("class", class_info); - info.assign ("global", global_info); - info.assign ("sparse", sparse_info); - info.assign ("complex", complex_info); - info.assign ("nesting", nesting_info); - info.assign ("persistent", persistent_info); + case 'c': + if (param.command == 's') + { + int front = param.first_parameter_length + - dims_str.find ('x'); + int back = param.parameter_length + - dims_str.length () + - front; + front = (front > 0) ? front : 0; + back = (back > 0) ? back : 0; - return info; - } - - void - symbol_info_list::print_descriptor (std::ostream& os, - const std::list params) const - { - std::ostringstream param_buf; - - preserve_stream_state stream_state (os); - - for (const auto& param : params) - { - if (param.command != '\0') - { - // Do the actual printing - switch (param.modifier) - { - case 'l': - os << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - param_buf << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - break; - - case 'r': - os << std::setiosflags (std::ios::right) - << std::setw (param.parameter_length); - param_buf << std::setiosflags (std::ios::right) - << std::setw (param.parameter_length); - break; + os << std::setiosflags (std::ios::left) + << std::setw (front) + << "" + << std::resetiosflags (std::ios::left) + << dims_str + << std::setiosflags (std::ios::left) + << std::setw (back) + << "" + << std::resetiosflags (std::ios::left); + } + else + { + os << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + } + break; - case 'c': - if (param.command != 's') - { - os << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - param_buf << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - } - break; - - default: - os << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - param_buf << std::setiosflags (std::ios::left) - << std::setw (param.parameter_length); - } + default: + error ("whos_line_format: modifier '%c' unknown", + param.modifier); + } - if (param.command == 's' && param.modifier == 'c') + switch (param.command) + { + case 'a': { - int a = param.first_parameter_length - param.balance; - a = (a < 0 ? 0 : a); - int b = param.parameter_length - a - param.text.length (); - b = (b < 0 ? 0 : b); - os << std::setiosflags (std::ios::left) << std::setw (a) - << "" << std::resetiosflags (std::ios::left) << param.text - << std::setiosflags (std::ios::left) - << std::setw (b) << "" - << std::resetiosflags (std::ios::left); - param_buf << std::setiosflags (std::ios::left) - << std::setw (a) - << "" << std::resetiosflags (std::ios::left) - << param.line - << std::setiosflags (std::ios::left) - << std::setw (b) << "" - << std::resetiosflags (std::ios::left); + char tmp[6]; + + tmp[0] = (m_is_complex ? 'c' : ' '); + tmp[1] = (m_is_sparse ? 's' : ' '); + tmp[2] = (m_is_formal ? 'f' : ' '); + tmp[3] = (m_is_global ? 'g' : ' '); + tmp[4] = (m_is_persistent ? 'p' : ' '); + tmp[5] = 0; + + os << tmp; } - else - { - os << param.text; - param_buf << param.line; - } - os << std::resetiosflags (std::ios::left) - << std::resetiosflags (std::ios::right); - param_buf << std::resetiosflags (std::ios::left) - << std::resetiosflags (std::ios::right); - } - else - { - os << param.text; - param_buf << param.line; - } - } + break; + + case 'b': + os << m_value.byte_size (); + break; + + case 'c': + os << m_value.class_name (); + break; + + case 'e': + os << m_value.numel (); + break; + + case 'n': + os << m_name; + break; + + case 's': + if (param.modifier != 'c') + os << dims_str; + break; + + case 't': + os << m_value.type_name (); + break; - os << param_buf.str (); - } + default: + error ("whos_line_format: command '%c' unknown", + param.command); + } - void symbol_info_list::display (std::ostream& os, - const std::string& format) const - { - if (! m_lst.empty ()) - { - std::size_t bytes = 0; - std::size_t elements = 0; + os << std::resetiosflags (std::ios::left) + << std::resetiosflags (std::ios::right); + i++; + } + else + { + os << param.text; + i++; + } + } +} - std::list params = parse_whos_line_format (format); +// FIXME: should we be using std::map instead of a list? + +octave_value symbol_info_list::varval (const std::string& name) const +{ + for (const auto& syminfo : m_lst) + { + if (name == syminfo.name ()) + return syminfo.value (); + } - print_descriptor (os, params); + return octave_value (); +} - octave_stdout << "\n"; +std::list symbol_info_list::names (void) const +{ + std::list retval; - for (const auto& syminfo : m_lst) - { - syminfo.display_line (os, params); + for (const auto& syminfo : m_lst) + retval.push_back (syminfo.name ()); + + return retval; +} - octave_value val = syminfo.value (); - - elements += val.numel (); - bytes += val.byte_size (); - } +octave_map +symbol_info_list::map_value (const std::string& caller_function_name, + int nesting_level) const +{ + std::size_t len = m_lst.size (); - os << "\nTotal is " << elements - << (elements == 1 ? " element" : " elements") - << " using " << bytes << (bytes == 1 ? " byte" : " bytes") - << "\n"; - } - } + Cell name_info (len, 1); + Cell size_info (len, 1); + Cell bytes_info (len, 1); + Cell class_info (len, 1); + Cell global_info (len, 1); + Cell sparse_info (len, 1); + Cell complex_info (len, 1); + Cell nesting_info (len, 1); + Cell persistent_info (len, 1); + + std::size_t j = 0; + + for (const auto& syminfo : m_lst) + { + octave_scalar_map ni; - std::list - symbol_info_list::parse_whos_line_format (const std::string& format) const - { - int idx; - std::size_t format_len = format.length (); - char garbage; - std::list params; + ni.assign ("function", caller_function_name); + ni.assign ("level", nesting_level); + + name_info(j) = syminfo.name (); + global_info(j) = syminfo.is_global (); + persistent_info(j) = syminfo.is_persistent (); + + octave_value val = syminfo.value (); - std::size_t bytes1; - int elements1; + size_info(j) = val.size (); + bytes_info(j) = val.byte_size (); + class_info(j) = val.class_name (); + sparse_info(j) = val.issparse (); + complex_info(j) = val.iscomplex (); + nesting_info(j) = ni; + + j++; + } + + octave_map info; - std::string param_string = "abcenst"; - Array param_length (dim_vector (param_string.length (), 1)); - Array param_names (dim_vector (param_string.length (), 1)); - std::size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t; + info.assign ("name", name_info); + info.assign ("size", size_info); + info.assign ("bytes", bytes_info); + info.assign ("class", class_info); + info.assign ("global", global_info); + info.assign ("sparse", sparse_info); + info.assign ("complex", complex_info); + info.assign ("nesting", nesting_info); + info.assign ("persistent", persistent_info); - pos_a = param_string.find ('a'); // Attributes - pos_b = param_string.find ('b'); // Bytes - pos_c = param_string.find ('c'); // Class - pos_e = param_string.find ('e'); // Elements - pos_n = param_string.find ('n'); // Name - pos_s = param_string.find ('s'); // Size - pos_t = param_string.find ('t'); // Type + return info; +} + +void +symbol_info_list::print_descriptor (std::ostream& os, + const std::list params) const +{ + std::ostringstream param_buf; + + preserve_stream_state stream_state (os); - param_names(pos_a) = "Attr"; - param_names(pos_b) = "Bytes"; - param_names(pos_c) = "Class"; - param_names(pos_e) = "Elements"; - param_names(pos_n) = "Name"; - param_names(pos_s) = "Size"; - param_names(pos_t) = "Type"; + for (const auto& param : params) + { + if (param.command != '\0') + { + // Do the actual printing + switch (param.modifier) + { + case 'l': + os << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + param_buf << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + break; - for (std::size_t i = 0; i < param_string.length (); i++) - param_length(i) = param_names(i).length (); + case 'r': + os << std::setiosflags (std::ios::right) + << std::setw (param.parameter_length); + param_buf << std::setiosflags (std::ios::right) + << std::setw (param.parameter_length); + break; - // The attribute column needs size 6. - param_length(pos_a) = 6; + case 'c': + if (param.command != 's') + { + os << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + param_buf << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + } + break; - // Calculating necessary spacing for name column, - // bytes column, elements column and class column + default: + os << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + param_buf << std::setiosflags (std::ios::left) + << std::setw (param.parameter_length); + } - for (const auto& syminfo : m_lst) - { - std::stringstream ss1, ss2; - std::string str; - - str = syminfo.name (); - param_length(pos_n) = ((str.length () - > static_cast (param_length(pos_n))) - ? str.length () : param_length(pos_n)); - - octave_value val = syminfo.value (); - - str = val.type_name (); - param_length(pos_t) = ((str.length () - > static_cast (param_length(pos_t))) - ? str.length () : param_length(pos_t)); + if (param.command == 's' && param.modifier == 'c') + { + int a = param.first_parameter_length - param.balance; + a = (a < 0 ? 0 : a); + int b = param.parameter_length - a - param.text.length (); + b = (b < 0 ? 0 : b); + os << std::setiosflags (std::ios::left) << std::setw (a) + << "" << std::resetiosflags (std::ios::left) << param.text + << std::setiosflags (std::ios::left) + << std::setw (b) << "" + << std::resetiosflags (std::ios::left); + param_buf << std::setiosflags (std::ios::left) + << std::setw (a) + << "" << std::resetiosflags (std::ios::left) + << param.line + << std::setiosflags (std::ios::left) + << std::setw (b) << "" + << std::resetiosflags (std::ios::left); + } + else + { + os << param.text; + param_buf << param.line; + } + os << std::resetiosflags (std::ios::left) + << std::resetiosflags (std::ios::right); + param_buf << std::resetiosflags (std::ios::left) + << std::resetiosflags (std::ios::right); + } + else + { + os << param.text; + param_buf << param.line; + } + } - elements1 = val.numel (); - ss1 << elements1; - str = ss1.str (); - param_length(pos_e) = ((str.length () - > static_cast (param_length(pos_e))) - ? str.length () : param_length(pos_e)); + os << param_buf.str (); +} + +void symbol_info_list::display (std::ostream& os, + const std::string& format) const +{ + if (! m_lst.empty ()) + { + std::size_t bytes = 0; + std::size_t elements = 0; - bytes1 = val.byte_size (); - ss2 << bytes1; - str = ss2.str (); - param_length(pos_b) = ((str.length () - > static_cast (param_length(pos_b))) - ? str.length () : param_length (pos_b)); - } + std::list params = parse_whos_line_format (format); + + print_descriptor (os, params); + + octave_stdout << "\n"; - idx = 0; - while (static_cast (idx) < format_len) - { - whos_parameter param; - param.command = '\0'; + for (const auto& syminfo : m_lst) + { + syminfo.display_line (os, params); + + octave_value val = syminfo.value (); - if (format[idx] == '%') - { - param.modifier = 'r'; - param.parameter_length = 0; + elements += val.numel (); + bytes += val.byte_size (); + } + + os << "\nTotal is " << elements + << (elements == 1 ? " element" : " elements") + << " using " << bytes << (bytes == 1 ? " byte" : " bytes") + << "\n"; + } +} - int a = 0; - int b = -1; - int balance = 1; - unsigned int items; - std::size_t pos; - std::string cmd; +std::list +symbol_info_list::parse_whos_line_format (const std::string& format) const +{ + int idx; + std::size_t format_len = format.length (); + char garbage; + std::list params; + + std::size_t bytes1; + int elements1; + + std::string param_string = "abcenst"; + Array param_length (dim_vector (param_string.length (), 1)); + Array param_names (dim_vector (param_string.length (), 1)); + std::size_t pos_a, pos_b, pos_c, pos_e, pos_n, pos_s, pos_t; - // Parse one command from format - cmd = format.substr (idx, format.length ()); - pos = cmd.find (';'); - if (pos == std::string::npos) - error ("parameter without ; in format"); + pos_a = param_string.find ('a'); // Attributes + pos_b = param_string.find ('b'); // Bytes + pos_c = param_string.find ('c'); // Class + pos_e = param_string.find ('e'); // Elements + pos_n = param_string.find ('n'); // Name + pos_s = param_string.find ('s'); // Size + pos_t = param_string.find ('t'); // Type - cmd = cmd.substr (0, pos+1); + param_names(pos_a) = "Attr"; + param_names(pos_b) = "Bytes"; + param_names(pos_c) = "Class"; + param_names(pos_e) = "Elements"; + param_names(pos_n) = "Name"; + param_names(pos_s) = "Size"; + param_names(pos_t) = "Type"; + + for (std::size_t i = 0; i < param_string.length (); i++) + param_length(i) = param_names(i).length (); - idx += cmd.length (); + // The attribute column needs size 6. + param_length(pos_a) = 6; - // FIXME: use iostream functions instead of sscanf! + // Calculating necessary spacing for name column, + // bytes column, elements column and class column + + for (const auto& syminfo : m_lst) + { + std::stringstream ss1, ss2; + std::string str; - if (cmd.find_first_of ("crl") != 1) - items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d;", - &garbage, ¶m.command, &a, &b, &balance); - else - items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d;", - &garbage, ¶m.modifier, ¶m.command, - &a, &b, &balance) - 1; + str = syminfo.name (); + param_length(pos_n) = ((str.length () + > static_cast (param_length(pos_n))) + ? str.length () : param_length(pos_n)); + + octave_value val = syminfo.value (); + + str = val.type_name (); + param_length(pos_t) = ((str.length () + > static_cast (param_length(pos_t))) + ? str.length () : param_length(pos_t)); - if (items < 2) - error ("whos_line_format: found parameter structure without command"); + elements1 = val.numel (); + ss1 << elements1; + str = ss1.str (); + param_length(pos_e) = ((str.length () + > static_cast (param_length(pos_e))) + ? str.length () : param_length(pos_e)); + + bytes1 = val.byte_size (); + ss2 << bytes1; + str = ss2.str (); + param_length(pos_b) = ((str.length () + > static_cast (param_length(pos_b))) + ? str.length () : param_length (pos_b)); + } - // Exception case of bare class command 'c' without modifier 'l/r' - if (param.modifier == 'c' - && param_string.find (param.command) == std::string::npos) - { - param.modifier = 'r'; - param.command = 'c'; - } + idx = 0; + while (static_cast (idx) < format_len) + { + whos_parameter param; + param.command = '\0'; + + if (format[idx] == '%') + { + param.modifier = 'r'; + param.parameter_length = 0; - // Insert data into parameter - param.first_parameter_length = 0; - pos = param_string.find (param.command); - if (pos == std::string::npos) - error ("whos_line_format: '%c' is not a command", param.command); + int a = 0; + int b = -1; + int balance = 1; + unsigned int items; + std::size_t pos; + std::string cmd; - param.parameter_length = param_length(pos); - param.text = param_names(pos); - param.line.assign (param_names(pos).length (), '='); + // Parse one command from format + cmd = format.substr (idx, format.length ()); + pos = cmd.find (';'); + if (pos == std::string::npos) + error ("parameter without ; in format"); - param.parameter_length = (a > param.parameter_length - ? a : param.parameter_length); - if (param.command == 's' && param.modifier == 'c' && b > 0) - param.first_parameter_length = b; + cmd = cmd.substr (0, pos+1); + + idx += cmd.length (); + + // FIXME: use iostream functions instead of sscanf! - if (param.command == 's') - { - // Have to calculate space needed for printing - // matrix dimensions Space needed for Size column is - // hard to determine in prior, because it depends on - // dimensions to be shown. That is why it is - // recalculated for each Size-command int first, - // rest = 0, total; - int rest = 0; - int first = param.first_parameter_length; - int total = param.parameter_length; + if (cmd.find_first_of ("crl") != 1) + items = sscanf (cmd.c_str (), "%c%c:%d:%d:%d;", + &garbage, ¶m.command, &a, &b, &balance); + else + items = sscanf (cmd.c_str (), "%c%c%c:%d:%d:%d;", + &garbage, ¶m.modifier, ¶m.command, + &a, &b, &balance) - 1; + + if (items < 2) + error ("whos_line_format: found parameter structure without command"); + + // Exception case of bare class command 'c' without modifier 'l/r' + if (param.modifier == 'c' + && param_string.find (param.command) == std::string::npos) + { + param.modifier = 'r'; + param.command = 'c'; + } - for (const auto& syminfo : m_lst) - { - octave_value val = syminfo.value (); - std::string dims_str = val.get_dims_str (); - int first1 = dims_str.find ('x'); - int total1 = dims_str.length (); - int rest1 = total1 - first1; - rest = (rest1 > rest ? rest1 : rest); - first = (first1 > first ? first1 : first); - total = (total1 > total ? total1 : total); - } + // Insert data into parameter + param.first_parameter_length = 0; + pos = param_string.find (param.command); + if (pos == std::string::npos) + error ("whos_line_format: '%c' is not a command", param.command); + + param.parameter_length = param_length(pos); + param.text = param_names(pos); + param.line.assign (param_names(pos).length (), '='); - if (param.modifier == 'c') - { - if (first < balance) - first += balance - first; - if (rest + balance < param.parameter_length) - rest += param.parameter_length - rest - balance; + param.parameter_length = (a > param.parameter_length + ? a : param.parameter_length); + if (param.command == 's' && param.modifier == 'c' && b > 0) + param.first_parameter_length = b; + + if (param.command == 's') + { + // Have to calculate space needed for printing + // matrix dimensions Space needed for Size column is + // hard to determine in prior, because it depends on + // dimensions to be shown. That is why it is + // recalculated for each Size-command int first, + // rest = 0, total; + int rest = 0; + int first = param.first_parameter_length; + int total = param.parameter_length; - param.parameter_length = first + rest; - param.first_parameter_length = first; - param.balance = balance; - } - else - { - param.parameter_length = total; - param.first_parameter_length = 0; - } - } - else if (param.modifier == 'c') - error ("whos_line_format: modifier 'c' not available for command '%c'", - param.command); + for (const auto& syminfo : m_lst) + { + octave_value val = syminfo.value (); + std::string dims_str = val.get_dims_str (); + int first1 = dims_str.find ('x'); + int total1 = dims_str.length (); + int rest1 = total1 - first1; + rest = (rest1 > rest ? rest1 : rest); + first = (first1 > first ? first1 : first); + total = (total1 > total ? total1 : total); + } + + if (param.modifier == 'c') + { + if (first < balance) + first += balance - first; + if (rest + balance < param.parameter_length) + rest += param.parameter_length - rest - balance; + + param.parameter_length = first + rest; + param.first_parameter_length = first; + param.balance = balance; + } + else + { + param.parameter_length = total; + param.first_parameter_length = 0; + } + } + else if (param.modifier == 'c') + error ("whos_line_format: modifier 'c' not available for command '%c'", + param.command); - // What happens if format contains negative numbers - // at param_length positions? - param.balance = (b < 0 ? 0 : param.balance); - param.first_parameter_length = (b < 0 - ? 0 - : param.first_parameter_length); - param.parameter_length = (a < 0 - ? 0 - : (param.parameter_length - < param_length(pos_s) - ? param_length(pos_s) - : param.parameter_length)); + // What happens if format contains negative numbers + // at param_length positions? + param.balance = (b < 0 ? 0 : param.balance); + param.first_parameter_length = (b < 0 + ? 0 + : param.first_parameter_length); + param.parameter_length = (a < 0 + ? 0 + : (param.parameter_length + < param_length(pos_s) + ? param_length(pos_s) + : param.parameter_length)); - params.push_back (param); - } - else - { - // Text string, to be printed as it is ... - std::string text; - std::size_t pos; - text = format.substr (idx, format.length ()); - pos = text.find ('%'); - if (pos != std::string::npos) - text = text.substr (0, pos); + params.push_back (param); + } + else + { + // Text string, to be printed as it is ... + std::string text; + std::size_t pos; + text = format.substr (idx, format.length ()); + pos = text.find ('%'); + if (pos != std::string::npos) + text = text.substr (0, pos); - // Push parameter into list ... - idx += text.length (); - param.text=text; - param.line.assign (text.length (), ' '); - params.push_back (param); - } - } + // Push parameter into list ... + idx += text.length (); + param.text=text; + param.line.assign (text.length (), ' '); + params.push_back (param); + } + } - return params; - } + return params; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/syminfo.h --- a/libinterp/corefcn/syminfo.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/syminfo.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,90 +39,90 @@ OCTAVE_BEGIN_NAMESPACE(octave) - struct whos_parameter - { - char command; - char modifier; - int parameter_length; - int first_parameter_length; - int balance; - std::string text; - std::string line; - }; +struct whos_parameter +{ + char command; + char modifier; + int parameter_length; + int first_parameter_length; + int balance; + std::string text; + std::string line; +}; - class - OCTINTERP_API - symbol_info - { - public: +class +OCTINTERP_API +symbol_info +{ +public: - symbol_info (const std::string& name, const octave_value& value, - bool is_formal, bool is_global, bool is_persistent) - : m_name (name), m_value (value), m_is_complex (value.iscomplex ()), - m_is_sparse (value.issparse ()), m_is_formal (is_formal), - m_is_global (is_global), m_is_persistent (is_persistent) - { } + symbol_info (const std::string& name, const octave_value& value, + bool is_formal, bool is_global, bool is_persistent) + : m_name (name), m_value (value), m_is_complex (value.iscomplex ()), + m_is_sparse (value.issparse ()), m_is_formal (is_formal), + m_is_global (is_global), m_is_persistent (is_persistent) + { } - std::string name (void) const { return m_name; } + std::string name (void) const { return m_name; } - octave_value value (void) const { return m_value; } + octave_value value (void) const { return m_value; } - bool is_complex (void) const { return m_is_complex; } + bool is_complex (void) const { return m_is_complex; } - bool is_sparse (void) const { return m_is_sparse; } + bool is_sparse (void) const { return m_is_sparse; } - bool is_formal (void) const { return m_is_formal; } + bool is_formal (void) const { return m_is_formal; } - bool is_global (void) const { return m_is_global; } + bool is_global (void) const { return m_is_global; } - bool is_persistent (void) const { return m_is_persistent; } + bool is_persistent (void) const { return m_is_persistent; } - void display_line (std::ostream& os, - const std::list& params) const; - private: + void display_line (std::ostream& os, + const std::list& params) const; +private: - std::string m_name; - octave_value m_value; - bool m_is_complex; - bool m_is_sparse; - bool m_is_formal; - bool m_is_global; - bool m_is_persistent; - }; + std::string m_name; + octave_value m_value; + bool m_is_complex; + bool m_is_sparse; + bool m_is_formal; + bool m_is_global; + bool m_is_persistent; +}; - class - OCTINTERP_API - symbol_info_list : public base_list - { - public: +class +OCTINTERP_API +symbol_info_list : public base_list +{ +public: - symbol_info_list (void) = default; + symbol_info_list (void) = default; - symbol_info_list (const symbol_info_list&) = default; + symbol_info_list (const symbol_info_list&) = default; - symbol_info_list& operator = (const symbol_info_list&) = default; + symbol_info_list& operator = (const symbol_info_list&) = default; - ~symbol_info_list (void) = default; + ~symbol_info_list (void) = default; - octave_value varval (const std::string& name) const; + octave_value varval (const std::string& name) const; - std::list names (void) const; + std::list names (void) const; - octave_map map_value (const std::string& caller_function_name, - int nesting_level) const; + octave_map map_value (const std::string& caller_function_name, + int nesting_level) const; - // Print a line of information for a given symbol. - void print_descriptor (std::ostream& os, - const std::list params) const; + // Print a line of information for a given symbol. + void print_descriptor (std::ostream& os, + const std::list params) const; - void display (std::ostream& os, const std::string& format) const; + void display (std::ostream& os, const std::string& format) const; - // Parse FORMAT, and return a parameter list, - // containing all information needed to print the given - // attributes of the symbols. - std::list - parse_whos_line_format (const std::string& format) const; - }; + // Parse FORMAT, and return a parameter list, + // containing all information needed to print the given + // attributes of the symbols. + std::list + parse_whos_line_format (const std::string& format) const; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/symrcm.cc --- a/libinterp/corefcn/symrcm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/symrcm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -115,9 +115,9 @@ // the left descendant of entry i #define LEFT(i) (((i) << 1) + 1) // = (2*(i)+1) -// the right descendant of entry i + // the right descendant of entry i #define RIGHT(i) (((i) << 1) + 2) // = (2*(i)+2) -// the parent of entry i + // the parent of entry i #define PARENT(i) (((i) - 1) >> 1) // = floor(((i)-1)/2) // Builds a min-heap (the root contains the smallest element). A is an array diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/symrec.cc --- a/libinterp/corefcn/symrec.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/symrec.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,23 +41,24 @@ OCTAVE_BEGIN_NAMESPACE(octave) - std::shared_ptr - symbol_record::symbol_record_rep::dup (void) const - { - return std::shared_ptr (new symbol_record_rep (*this)); - } +std::shared_ptr +symbol_record::symbol_record_rep::dup (void) const +{ + return std::shared_ptr (new symbol_record_rep (*this)); +} - octave_value - symbol_record::symbol_record_rep::dump (void) const - { - std::map m - = {{ "frame_offset", m_frame_offset }, - { "data_offset", m_data_offset }, - { "name", m_name }, - { "local", is_local () }, - { "formal", is_formal () }}; +octave_value +symbol_record::symbol_record_rep::dump (void) const +{ + std::map m + = {{ "frame_offset", m_frame_offset }, + { "data_offset", m_data_offset }, + { "name", m_name }, + { "local", is_local () }, + { "formal", is_formal () } + }; - return octave_value (m); - } + return octave_value (m); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/symrec.h --- a/libinterp/corefcn/symrec.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/symrec.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,204 +40,204 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope_rep; +class symbol_scope_rep; + +class symbol_record +{ +public: + + typedef std::size_t context_id; - class symbol_record + enum symrec_t : unsigned char + { + // generic variable + LOCAL = 1, + // formal parameter + FORMAL = 2, + // this symbol may NOT become a variable. + // (symbol added to a static workspace) + ADDED_STATIC = 4, + // this symbol was recognized as a variable from syntax + VARIABLE = 8 + }; + +private: + + class symbol_record_rep { public: - typedef std::size_t context_id; + symbol_record_rep (const std::string& nm, symrec_t sc) + : m_frame_offset (0), m_data_offset (0), m_storage_class (sc), + m_name (nm) + { } + + symbol_record_rep (const symbol_record_rep&) = default; + + symbol_record_rep& operator = (const symbol_record_rep&) = default; + + ~symbol_record_rep (void) = default; + + // FIXME: use special storage class instead? + bool is_valid (void) const { return ! m_name.empty (); } + + void set_frame_offset (std::size_t offset) { m_frame_offset = offset; } + + std::size_t frame_offset (void) const { return m_frame_offset; } + + void set_data_offset (std::size_t offset) { m_data_offset = offset; } + + std::size_t data_offset (void) const { return m_data_offset; } - enum symrec_t : unsigned char + bool is_local (void) const + { + return m_storage_class & LOCAL; + } + + bool is_formal (void) const + { + return m_storage_class & FORMAL; + } + + bool is_added_static (void) const + { + return m_storage_class & ADDED_STATIC; + } + + bool is_variable (void) const + { + return m_storage_class & VARIABLE; + } + + void mark_local (void) { - // generic variable - LOCAL = 1, - // formal parameter - FORMAL = 2, - // this symbol may NOT become a variable. - // (symbol added to a static workspace) - ADDED_STATIC = 4, - // this symbol was recognized as a variable from syntax - VARIABLE = 8 - }; + m_storage_class = static_cast (m_storage_class | LOCAL); + } + + void mark_formal (void) + { + // Formal parameters are also variables. + m_storage_class = static_cast (m_storage_class + | FORMAL | VARIABLE); + } + + void mark_added_static (void) + { + m_storage_class = static_cast (m_storage_class + | ADDED_STATIC); + } + + void mark_as_variable (void) + { + m_storage_class = static_cast (m_storage_class | VARIABLE); + } + + void unmark_local (void) + { + m_storage_class = static_cast (m_storage_class & ~LOCAL); + } + + void unmark_formal (void) + { + m_storage_class = static_cast (m_storage_class & ~FORMAL); + } + + void unmark_added_static (void) + { + m_storage_class = static_cast (m_storage_class + & ~ADDED_STATIC); + } + + void unmark_as_variable (void) + { + m_storage_class = static_cast (m_storage_class & ~VARIABLE); + } + + unsigned int storage_class (void) const { return m_storage_class; } + + std::shared_ptr dup (void) const; + + octave_value dump (void) const; + + std::string name (void) const { return m_name; } + + void rename (const std::string& new_name) { m_name = new_name; } private: - class symbol_record_rep - { - public: - - symbol_record_rep (const std::string& nm, symrec_t sc) - : m_frame_offset (0), m_data_offset (0), m_storage_class (sc), - m_name (nm) - { } + std::size_t m_frame_offset; + std::size_t m_data_offset; - symbol_record_rep (const symbol_record_rep&) = default; - - symbol_record_rep& operator = (const symbol_record_rep&) = default; - - ~symbol_record_rep (void) = default; - - // FIXME: use special storage class instead? - bool is_valid (void) const { return ! m_name.empty (); } - - void set_frame_offset (std::size_t offset) { m_frame_offset = offset; } + symrec_t m_storage_class; - std::size_t frame_offset (void) const { return m_frame_offset; } - - void set_data_offset (std::size_t offset) { m_data_offset = offset; } - - std::size_t data_offset (void) const { return m_data_offset; } + std::string m_name; + }; - bool is_local (void) const - { - return m_storage_class & LOCAL; - } +public: - bool is_formal (void) const - { - return m_storage_class & FORMAL; - } - - bool is_added_static (void) const - { - return m_storage_class & ADDED_STATIC; - } + symbol_record (const std::string& nm = "", symrec_t sc = LOCAL) + : m_rep (new symbol_record_rep (nm, sc)) + { } - bool is_variable (void) const - { - return m_storage_class & VARIABLE; - } + symbol_record (const std::string& nm, const octave_value&, + symrec_t sc = LOCAL) + : m_rep (new symbol_record_rep (nm, sc)) + { } - void mark_local (void) - { - m_storage_class = static_cast (m_storage_class | LOCAL); - } + symbol_record (const symbol_record&) = default; - void mark_formal (void) - { - // Formal parameters are also variables. - m_storage_class = static_cast (m_storage_class - | FORMAL | VARIABLE); - } + symbol_record& operator = (const symbol_record&) = default; + + ~symbol_record (void) = default; - void mark_added_static (void) - { - m_storage_class = static_cast (m_storage_class - | ADDED_STATIC); - } + bool is_valid (void) const { return m_rep->is_valid (); } - void mark_as_variable (void) - { - m_storage_class = static_cast (m_storage_class | VARIABLE); - } + explicit operator bool () const { return is_valid (); } - void unmark_local (void) - { - m_storage_class = static_cast (m_storage_class & ~LOCAL); - } + void set_frame_offset (std::size_t offset) + { m_rep->set_frame_offset (offset); } - void unmark_formal (void) - { - m_storage_class = static_cast (m_storage_class & ~FORMAL); - } + std::size_t frame_offset (void) const { return m_rep->frame_offset (); } - void unmark_added_static (void) - { - m_storage_class = static_cast (m_storage_class - & ~ADDED_STATIC); - } + void set_data_offset (std::size_t offset) + { m_rep->set_data_offset (offset); } - void unmark_as_variable (void) - { - m_storage_class = static_cast (m_storage_class & ~VARIABLE); - } + std::size_t data_offset (void) const { return m_rep->data_offset (); } - unsigned int storage_class (void) const { return m_storage_class; } - - std::shared_ptr dup (void) const; - - octave_value dump (void) const; + symbol_record dup (void) const { return symbol_record (m_rep->dup ()); } - std::string name (void) const { return m_name; } - - void rename (const std::string& new_name) { m_name = new_name; } + std::string name (void) const { return m_rep->name (); } - private: - - std::size_t m_frame_offset; - std::size_t m_data_offset; - - symrec_t m_storage_class; + void rename (const std::string& new_name) { m_rep->rename (new_name); } - std::string m_name; - }; - - public: - - symbol_record (const std::string& nm = "", symrec_t sc = LOCAL) - : m_rep (new symbol_record_rep (nm, sc)) - { } + bool is_local (void) const { return m_rep->is_local (); } + bool is_formal (void) const { return m_rep->is_formal (); } + bool is_added_static (void) const { return m_rep->is_added_static (); } + bool is_variable (void) const { return m_rep->is_variable (); } - symbol_record (const std::string& nm, const octave_value&, - symrec_t sc = LOCAL) - : m_rep (new symbol_record_rep (nm, sc)) - { } - - symbol_record (const symbol_record&) = default; - - symbol_record& operator = (const symbol_record&) = default; - - ~symbol_record (void) = default; - - bool is_valid (void) const { return m_rep->is_valid (); } + void mark_local (void) { m_rep->mark_local (); } + void mark_formal (void) { m_rep->mark_formal (); } + void mark_added_static (void) { m_rep->mark_added_static (); } + void mark_as_variable (void) { m_rep->mark_as_variable (); } - explicit operator bool () const { return is_valid (); } - - void set_frame_offset (std::size_t offset) - { m_rep->set_frame_offset (offset); } - - std::size_t frame_offset (void) const { return m_rep->frame_offset (); } - - void set_data_offset (std::size_t offset) - { m_rep->set_data_offset (offset); } + void unmark_local (void) { m_rep->unmark_local (); } + void unmark_formal (void) { m_rep->unmark_formal (); } + void unmark_added_static (void) { m_rep->unmark_added_static (); } + void unmark_as_variable (void) { m_rep->unmark_as_variable (); } - std::size_t data_offset (void) const { return m_rep->data_offset (); } - - symbol_record dup (void) const { return symbol_record (m_rep->dup ()); } - - std::string name (void) const { return m_rep->name (); } + unsigned int storage_class (void) const { return m_rep->storage_class (); } - void rename (const std::string& new_name) { m_rep->rename (new_name); } - - bool is_local (void) const { return m_rep->is_local (); } - bool is_formal (void) const { return m_rep->is_formal (); } - bool is_added_static (void) const { return m_rep->is_added_static (); } - bool is_variable (void) const { return m_rep->is_variable (); } + octave_value dump (void) const { return m_rep->dump (); } - void mark_local (void) { m_rep->mark_local (); } - void mark_formal (void) { m_rep->mark_formal (); } - void mark_added_static (void) { m_rep->mark_added_static (); } - void mark_as_variable (void) { m_rep->mark_as_variable (); } +private: - void unmark_local (void) { m_rep->unmark_local (); } - void unmark_formal (void) { m_rep->unmark_formal (); } - void unmark_added_static (void) { m_rep->unmark_added_static (); } - void unmark_as_variable (void) { m_rep->unmark_as_variable (); } - - unsigned int storage_class (void) const { return m_rep->storage_class (); } + std::shared_ptr m_rep; - octave_value dump (void) const { return m_rep->dump (); } - - private: - - std::shared_ptr m_rep; - - // NEW_REP must be dynamically allocated or nullptr. - symbol_record (const std::shared_ptr& new_rep) - : m_rep (new_rep) - { } - }; + // NEW_REP must be dynamically allocated or nullptr. + symbol_record (const std::shared_ptr& new_rep) + : m_rep (new_rep) + { } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/symscope.cc --- a/libinterp/corefcn/symscope.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/symscope.cc Thu Dec 01 20:05:44 2022 -0800 @@ -42,348 +42,349 @@ OCTAVE_BEGIN_NAMESPACE(octave) - symbol_record symbol_scope_rep::insert_local (const std::string& name) - { - symbol_record sym (name); +symbol_record symbol_scope_rep::insert_local (const std::string& name) +{ + symbol_record sym (name); - insert_symbol_record (sym); + insert_symbol_record (sym); - return sym; - } + return sym; +} - void symbol_scope_rep::insert_symbol_record (symbol_record& sr) - { - std::size_t data_offset = num_symbols (); - std::string name = sr.name (); +void symbol_scope_rep::insert_symbol_record (symbol_record& sr) +{ + std::size_t data_offset = num_symbols (); + std::string name = sr.name (); - sr.set_data_offset (data_offset); + sr.set_data_offset (data_offset); - m_symbols[name] = sr; - } + m_symbols[name] = sr; +} - symbol_record symbol_scope_rep::insert (const std::string& name) - { - table_iterator p = m_symbols.find (name); +symbol_record symbol_scope_rep::insert (const std::string& name) +{ + table_iterator p = m_symbols.find (name); - if (p == m_symbols.end ()) - { - symbol_record ret (name); + if (p == m_symbols.end ()) + { + symbol_record ret (name); + + std::size_t data_offset = num_symbols (); + + ret.set_data_offset (data_offset); - std::size_t data_offset = num_symbols (); + auto t_parent = m_parent.lock (); - ret.set_data_offset (data_offset); + std::size_t offset = 0; - auto t_parent = m_parent.lock (); + if (is_nested () && t_parent + && t_parent->look_nonlocal (name, offset, ret)) + return m_symbols[name] = ret; + else + { + if (m_is_static) + ret.mark_added_static (); - std::size_t offset = 0; - - if (is_nested () && t_parent - && t_parent->look_nonlocal (name, offset, ret)) return m_symbols[name] = ret; - else - { - if (m_is_static) - ret.mark_added_static (); + } + } + else + return p->second; +} - return m_symbols[name] = ret; - } - } - else - return p->second; - } +std::list symbol_scope_rep::localfunctions (void) const +{ + std::list retval; - std::list symbol_scope_rep::localfunctions (void) const - { - std::list retval; + // Find the subfunctions of this function (which should be the + // primary parent function for this scope). - // Find the subfunctions of this function (which should be the - // primary parent function for this scope). + // 1) m_subfunction_names contains only valid subfunctions + // 2) m_subfunctions contains both nested functions and subfunctions - // 1) m_subfunction_names contains only valid subfunctions - // 2) m_subfunctions contains both nested functions and subfunctions + // loop over them. - // loop over them. + for (const auto& nm : m_subfunction_names) + { + auto nm_fcn_iter = m_subfunctions.find (nm); - for (const auto& nm : m_subfunction_names) - { - auto nm_fcn_iter = m_subfunctions.find (nm); - - if (nm_fcn_iter != m_subfunctions.end ()) - { - octave_value ov_fcn = nm_fcn_iter->second; - octave_user_code *fcn = ov_fcn.user_code_value (); + if (nm_fcn_iter != m_subfunctions.end ()) + { + octave_value ov_fcn = nm_fcn_iter->second; + octave_user_code *fcn = ov_fcn.user_code_value (); - if (! fcn) - continue; + if (! fcn) + continue; - symbol_scope scope = fcn->scope (); + symbol_scope scope = fcn->scope (); - std::list plst = scope.parent_fcn_names (); + std::list plst = scope.parent_fcn_names (); - octave_fcn_handle *fh = new octave_fcn_handle (ov_fcn, nm, plst); + octave_fcn_handle *fh = new octave_fcn_handle (ov_fcn, nm, plst); - retval.push_back (octave_value (fh)); - } - } + retval.push_back (octave_value (fh)); + } + } - return retval; - } + return retval; +} - octave_value - symbol_scope_rep::dump (void) const - { - std::map m - = {{ "name", m_name }, - { "nesting_depth", m_nesting_depth }, - { "is_static", m_is_static }, - { "symbols", dump_symbols_map () }, - { "subfunction_names", string_vector (m_subfunction_names) }, - { "subfunctions", dump_function_map (m_subfunctions) }}; +octave_value +symbol_scope_rep::dump (void) const +{ + std::map m + = {{ "name", m_name }, + { "nesting_depth", m_nesting_depth }, + { "is_static", m_is_static }, + { "symbols", dump_symbols_map () }, + { "subfunction_names", string_vector (m_subfunction_names) }, + { "subfunctions", dump_function_map (m_subfunctions) } + }; - return octave_value (m); - } + return octave_value (m); +} - octave_value - symbol_scope_rep::dump_symbols_map (void) const - { - std::map info_map; +octave_value +symbol_scope_rep::dump_symbols_map (void) const +{ + std::map info_map; - for (const auto& nm_sr : m_symbols) - { - std::string nm = nm_sr.first; - symbol_record sr = nm_sr.second; - info_map[nm] = sr.dump (); - } + for (const auto& nm_sr : m_symbols) + { + std::string nm = nm_sr.first; + symbol_record sr = nm_sr.second; + info_map[nm] = sr.dump (); + } - return octave_value (info_map); - } + return octave_value (info_map); +} - std::list symbol_scope_rep::symbol_list (void) const - { - std::list retval; +std::list symbol_scope_rep::symbol_list (void) const +{ + std::list retval; - for (const auto& nm_sr : m_symbols) - retval.push_back (nm_sr.second); + for (const auto& nm_sr : m_symbols) + retval.push_back (nm_sr.second); - return retval; - } + return retval; +} - octave_value - symbol_scope_rep::find_subfunction (const std::string& name) const - { - subfunctions_const_iterator p = m_subfunctions.find (name); +octave_value +symbol_scope_rep::find_subfunction (const std::string& name) const +{ + subfunctions_const_iterator p = m_subfunctions.find (name); - if (p != m_subfunctions.end ()) - return p->second; + if (p != m_subfunctions.end ()) + return p->second; - auto t_parent = m_parent.lock (); + auto t_parent = m_parent.lock (); - if (t_parent) - return t_parent->find_subfunction (name); + if (t_parent) + return t_parent->find_subfunction (name); - return octave_value (); - } + return octave_value (); +} - void - symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name) - { - for (auto& nm_sf : m_subfunctions) - { - octave_function *fcn = nm_sf.second.function_value (); +void +symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name) +{ + for (auto& nm_sf : m_subfunctions) + { + octave_function *fcn = nm_sf.second.function_value (); - if (fcn) - fcn->mark_as_private_function (class_name); - } - } + if (fcn) + fcn->mark_as_private_function (class_name); + } +} - std::list - symbol_scope_rep::parent_fcn_names (void) const - { - std::list retval; +std::list +symbol_scope_rep::parent_fcn_names (void) const +{ + std::list retval; - auto pscope = parent_scope_rep (); + auto pscope = parent_scope_rep (); - while (pscope) - { - retval.push_back (pscope->fcn_name ()); + while (pscope) + { + retval.push_back (pscope->fcn_name ()); - pscope = pscope->parent_scope_rep (); - } + pscope = pscope->parent_scope_rep (); + } - return retval; - } + return retval; +} - void - symbol_scope_rep::set_parent (const std::shared_ptr& parent) - { - m_parent = std::weak_ptr (parent); - } +void +symbol_scope_rep::set_parent (const std::shared_ptr& parent) +{ + m_parent = std::weak_ptr (parent); +} - void - symbol_scope_rep::set_primary_parent (const std::shared_ptr& parent) - { - m_primary_parent = std::weak_ptr (parent); - } +void +symbol_scope_rep::set_primary_parent (const std::shared_ptr& parent) +{ + m_primary_parent = std::weak_ptr (parent); +} - void - symbol_scope_rep::cache_dir_name (const std::string& name) - { - m_dir_name = sys::canonicalize_file_name (name); - } +void +symbol_scope_rep::cache_dir_name (const std::string& name) +{ + m_dir_name = sys::canonicalize_file_name (name); +} - bool - symbol_scope_rep::is_relative (const std::shared_ptr& scope) const - { - if (is_nested ()) - { - // Since is_nested is true, the following should always return a - // valid scope. +bool +symbol_scope_rep::is_relative (const std::shared_ptr& scope) const +{ + if (is_nested ()) + { + // Since is_nested is true, the following should always return a + // valid scope. - auto t_parent = m_parent.lock (); + auto t_parent = m_parent.lock (); - if (t_parent) - { - // SCOPE is the parent of this scope: this scope is a child - // of SCOPE. + if (t_parent) + { + // SCOPE is the parent of this scope: this scope is a child + // of SCOPE. - if (t_parent == scope) - return true; - } + if (t_parent == scope) + return true; + } - auto t_primary_parent = m_primary_parent.lock (); + auto t_primary_parent = m_primary_parent.lock (); - if (t_primary_parent) - { - // SCOPE is the primary parent of this scope: this scope is a - // child (or grandchild) of SCOPE. - if (t_primary_parent == scope) - return true; + if (t_primary_parent) + { + // SCOPE is the primary parent of this scope: this scope is a + // child (or grandchild) of SCOPE. + if (t_primary_parent == scope) + return true; - // SCOPE and this scope share the same primary parent: they are - // siblings (or cousins) - auto scope_primary_parent = scope->primary_parent_scope_rep (); - if (t_primary_parent == scope_primary_parent) - return true; - } - } + // SCOPE and this scope share the same primary parent: they are + // siblings (or cousins) + auto scope_primary_parent = scope->primary_parent_scope_rep (); + if (t_primary_parent == scope_primary_parent) + return true; + } + } - return false; - } + return false; +} - void symbol_scope_rep::mark_as_variable (const std::string& nm) - { - table_iterator p = m_symbols.find (nm); +void symbol_scope_rep::mark_as_variable (const std::string& nm) +{ + table_iterator p = m_symbols.find (nm); - if (p != m_symbols.end ()) - p->second.mark_as_variable (); - } + if (p != m_symbols.end ()) + p->second.mark_as_variable (); +} - void symbol_scope_rep::mark_as_variables (const std::list& lst) - { - for (const auto& nm : lst) - mark_as_variable (nm); - } +void symbol_scope_rep::mark_as_variables (const std::list& lst) +{ + for (const auto& nm : lst) + mark_as_variable (nm); +} - bool symbol_scope_rep::is_variable (const std::string& nm) const - { - table_const_iterator p = m_symbols.find (nm); +bool symbol_scope_rep::is_variable (const std::string& nm) const +{ + table_const_iterator p = m_symbols.find (nm); - // FIXME: maybe we should also mark formal parameters as variables? + // FIXME: maybe we should also mark formal parameters as variables? - if (p != m_symbols.end () && p->second.is_variable ()) - return true; + if (p != m_symbols.end () && p->second.is_variable ()) + return true; - if (is_nested ()) - { - auto t_parent = m_parent.lock (); + if (is_nested ()) + { + auto t_parent = m_parent.lock (); - return t_parent ? t_parent->is_variable (nm) : false; - } + return t_parent ? t_parent->is_variable (nm) : false; + } - return false; - } + return false; +} - void symbol_scope_rep::update_nest (void) - { - auto t_parent = m_parent.lock (); +void symbol_scope_rep::update_nest (void) +{ + auto t_parent = m_parent.lock (); - if (t_parent) - { - // fix bad symbol_records - for (auto& nm_sr : m_symbols) - { - symbol_record& ours = nm_sr.second; + if (t_parent) + { + // fix bad symbol_records + for (auto& nm_sr : m_symbols) + { + symbol_record& ours = nm_sr.second; - std::size_t offset = 0; + std::size_t offset = 0; - if (! ours.is_formal () && is_nested ()) - t_parent->look_nonlocal (nm_sr.first, offset, ours); - } + if (! ours.is_formal () && is_nested ()) + t_parent->look_nonlocal (nm_sr.first, offset, ours); + } - // The scopes of nested functions are static. - if (is_nested ()) - m_is_static = true; - } - else if (m_children.size ()) - { - // Parents of nested functions have static scopes. + // The scopes of nested functions are static. + if (is_nested ()) m_is_static = true; - } - - for (auto& scope_obj : m_children) - scope_obj.update_nest (); - } + } + else if (m_children.size ()) + { + // Parents of nested functions have static scopes. + m_is_static = true; + } - bool symbol_scope_rep::look_nonlocal (const std::string& name, - std::size_t offset, - symbol_record& result) - { - offset++; + for (auto& scope_obj : m_children) + scope_obj.update_nest (); +} + +bool symbol_scope_rep::look_nonlocal (const std::string& name, + std::size_t offset, + symbol_record& result) +{ + offset++; - table_iterator p = m_symbols.find (name); + table_iterator p = m_symbols.find (name); - if (p == m_symbols.end ()) - { - auto t_parent = m_parent.lock (); + if (p == m_symbols.end ()) + { + auto t_parent = m_parent.lock (); - if (is_nested () && t_parent) - return t_parent->look_nonlocal (name, offset, result); - } - else - { - // Add scope offsets because the one we found may be used in - // this scope but initially from another parent scope beyond - // that. The parent offset will already point to the first - // occurrence because we do the overall nesting update from the - // parent function down through the lists of all children. + if (is_nested () && t_parent) + return t_parent->look_nonlocal (name, offset, result); + } + else + { + // Add scope offsets because the one we found may be used in + // this scope but initially from another parent scope beyond + // that. The parent offset will already point to the first + // occurrence because we do the overall nesting update from the + // parent function down through the lists of all children. - std::size_t t_frame_offset = offset + p->second.frame_offset (); - std::size_t t_data_offset = p->second.data_offset (); + std::size_t t_frame_offset = offset + p->second.frame_offset (); + std::size_t t_data_offset = p->second.data_offset (); - result.set_frame_offset (t_frame_offset); - result.set_data_offset (t_data_offset); + result.set_frame_offset (t_frame_offset); + result.set_data_offset (t_data_offset); - return true; - } + return true; + } - return false; - } + return false; +} - std::list symbol_scope::localfunctions (void) const - { - if (! m_rep) - return std::list (); +std::list symbol_scope::localfunctions (void) const +{ + if (! m_rep) + return std::list (); - if (is_primary_fcn_scope ()) - return m_rep->localfunctions (); + if (is_primary_fcn_scope ()) + return m_rep->localfunctions (); - std::shared_ptr ppsr - = m_rep->primary_parent_scope_rep (); + std::shared_ptr ppsr + = m_rep->primary_parent_scope_rep (); - if (! ppsr) - return std::list (); + if (! ppsr) + return std::list (); - return ppsr->localfunctions (); - } + return ppsr->localfunctions (); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/symscope.h --- a/libinterp/corefcn/symscope.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/symscope.h Thu Dec 01 20:05:44 2022 -0800 @@ -48,683 +48,683 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; +class symbol_scope; - class symbol_scope_rep - : public std::enable_shared_from_this - { - public: +class symbol_scope_rep + : public std::enable_shared_from_this +{ +public: - typedef std::map::const_iterator - table_const_iterator; - typedef std::map::iterator - table_iterator; + typedef std::map::const_iterator + table_const_iterator; + typedef std::map::iterator + table_iterator; - typedef std::map::const_iterator - subfunctions_const_iterator; - typedef std::map::iterator - subfunctions_iterator; + typedef std::map::const_iterator + subfunctions_const_iterator; + typedef std::map::iterator + subfunctions_iterator; - symbol_scope_rep (const std::string& name = "") - : m_name (name), m_symbols (), m_subfunctions (), - m_persistent_values (), m_code (nullptr), m_fcn_name (), - m_fcn_file_name (), m_dir_name (), m_parent (), - m_primary_parent (), m_children (), m_nesting_depth (0), - m_is_static (false), m_is_primary_fcn_scope (false) - { - // All scopes have ans as the first symbol, initially undefined. + symbol_scope_rep (const std::string& name = "") + : m_name (name), m_symbols (), m_subfunctions (), + m_persistent_values (), m_code (nullptr), m_fcn_name (), + m_fcn_file_name (), m_dir_name (), m_parent (), + m_primary_parent (), m_children (), m_nesting_depth (0), + m_is_static (false), m_is_primary_fcn_scope (false) + { + // All scopes have ans as the first symbol, initially undefined. - insert_local ("ans"); - } + insert_local ("ans"); + } - // No copying! + // No copying! - symbol_scope_rep (const symbol_scope&) = delete; + symbol_scope_rep (const symbol_scope&) = delete; - symbol_scope_rep& operator = (const symbol_scope&) = delete; + symbol_scope_rep& operator = (const symbol_scope&) = delete; - ~symbol_scope_rep (void) = default; + ~symbol_scope_rep (void) = default; - std::size_t num_symbols (void) const { return m_symbols.size (); } + std::size_t num_symbols (void) const { return m_symbols.size (); } - // Simply inserts symbol. No non-local searching. + // Simply inserts symbol. No non-local searching. - symbol_record insert_local (const std::string& name); + symbol_record insert_local (const std::string& name); - void insert_symbol_record (symbol_record& sr); + void insert_symbol_record (symbol_record& sr); - bool is_nested (void) const { return m_nesting_depth > 0; } + bool is_nested (void) const { return m_nesting_depth > 0; } - std::size_t nesting_depth (void) const { return m_nesting_depth; } + std::size_t nesting_depth (void) const { return m_nesting_depth; } - void set_nesting_depth (std::size_t depth) { m_nesting_depth = depth; } + void set_nesting_depth (std::size_t depth) { m_nesting_depth = depth; } - bool is_parent (void) const { return ! m_children.empty (); } + bool is_parent (void) const { return ! m_children.empty (); } - bool is_static (void) const { return m_is_static; } + bool is_static (void) const { return m_is_static; } - void mark_static (void) { m_is_static = true; } + void mark_static (void) { m_is_static = true; } - std::shared_ptr parent_scope_rep (void) const - { - return m_parent.lock (); - } + std::shared_ptr parent_scope_rep (void) const + { + return m_parent.lock (); + } - std::shared_ptr primary_parent_scope_rep (void) const - { - return m_primary_parent.lock (); - } + std::shared_ptr primary_parent_scope_rep (void) const + { + return m_primary_parent.lock (); + } - std::shared_ptr dup (void) const - { - std::shared_ptr new_sid - = std::shared_ptr (new symbol_scope_rep (m_name)); + std::shared_ptr dup (void) const + { + std::shared_ptr new_sid + = std::shared_ptr (new symbol_scope_rep (m_name)); - for (const auto& nm_sr : m_symbols) - new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup (); + for (const auto& nm_sr : m_symbols) + new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup (); - new_sid->m_subfunctions = m_subfunctions; - new_sid->m_persistent_values = m_persistent_values; - new_sid->m_subfunction_names = m_subfunction_names; - new_sid->m_code = m_code; - new_sid->m_fcn_name = m_fcn_name; - new_sid->m_fcn_file_name = m_fcn_file_name; - new_sid->m_dir_name = m_dir_name; - new_sid->m_parent = m_parent; - new_sid->m_primary_parent = m_primary_parent; - new_sid->m_children = m_children; - new_sid->m_nesting_depth = m_nesting_depth; - new_sid->m_is_static = m_is_static; - new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope; + new_sid->m_subfunctions = m_subfunctions; + new_sid->m_persistent_values = m_persistent_values; + new_sid->m_subfunction_names = m_subfunction_names; + new_sid->m_code = m_code; + new_sid->m_fcn_name = m_fcn_name; + new_sid->m_fcn_file_name = m_fcn_file_name; + new_sid->m_dir_name = m_dir_name; + new_sid->m_parent = m_parent; + new_sid->m_primary_parent = m_primary_parent; + new_sid->m_children = m_children; + new_sid->m_nesting_depth = m_nesting_depth; + new_sid->m_is_static = m_is_static; + new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope; - return new_sid; - } + return new_sid; + } - octave_value& persistent_varref (std::size_t data_offset) - { - return m_persistent_values[data_offset]; - } + octave_value& persistent_varref (std::size_t data_offset) + { + return m_persistent_values[data_offset]; + } - octave_value persistent_varval (std::size_t data_offset) const - { - auto p = m_persistent_values.find (data_offset); + octave_value persistent_varval (std::size_t data_offset) const + { + auto p = m_persistent_values.find (data_offset); - return p == m_persistent_values.end () ? octave_value () : p->second; - } + return p == m_persistent_values.end () ? octave_value () : p->second; + } - symbol_record find_symbol (const std::string& name) - { - auto p = m_symbols.find (name); + symbol_record find_symbol (const std::string& name) + { + auto p = m_symbols.find (name); - if (p == m_symbols.end ()) - return insert (name); - else - return p->second; - } + if (p == m_symbols.end ()) + return insert (name); + else + return p->second; + } - symbol_record lookup_symbol (const std::string& name) const - { - auto p = m_symbols.find (name); + symbol_record lookup_symbol (const std::string& name) const + { + auto p = m_symbols.find (name); - return p == m_symbols.end () ? symbol_record () : p->second; - } + return p == m_symbols.end () ? symbol_record () : p->second; + } - symbol_record insert (const std::string& name); + symbol_record insert (const std::string& name); - void rename (const std::string& old_name, const std::string& new_name) - { - auto p = m_symbols.find (old_name); + void rename (const std::string& old_name, const std::string& new_name) + { + auto p = m_symbols.find (old_name); - if (p != m_symbols.end ()) - { - symbol_record sr = p->second; + if (p != m_symbols.end ()) + { + symbol_record sr = p->second; - sr.rename (new_name); + sr.rename (new_name); - m_symbols.erase (p); + m_symbols.erase (p); - m_symbols[new_name] = sr; - } - } + m_symbols[new_name] = sr; + } + } - void install_subfunction (const std::string& name, - const octave_value& fval) - { - m_subfunctions[name] = fval; - } + void install_subfunction (const std::string& name, + const octave_value& fval) + { + m_subfunctions[name] = fval; + } - void install_nestfunction (const std::string& name, - const octave_value& fval, - const symbol_scope& fcn_scope) - { - m_subfunctions[name] = fval; + void install_nestfunction (const std::string& name, + const octave_value& fval, + const symbol_scope& fcn_scope) + { + m_subfunctions[name] = fval; - m_children.push_back (fcn_scope); - } + m_children.push_back (fcn_scope); + } - octave_value find_subfunction (const std::string& name) const; + octave_value find_subfunction (const std::string& name) const; - void lock_subfunctions (void) - { - for (auto& nm_sf : m_subfunctions) - nm_sf.second.lock (); - } + void lock_subfunctions (void) + { + for (auto& nm_sf : m_subfunctions) + nm_sf.second.lock (); + } - void unlock_subfunctions (void) - { - for (auto& nm_sf : m_subfunctions) - nm_sf.second.unlock (); - } + void unlock_subfunctions (void) + { + for (auto& nm_sf : m_subfunctions) + nm_sf.second.unlock (); + } - // Pairs of name, function objects. - std::map subfunctions (void) const - { - return m_subfunctions; - } + // Pairs of name, function objects. + std::map subfunctions (void) const + { + return m_subfunctions; + } - void erase_subfunctions (void) - { - m_subfunctions.clear (); - } + void erase_subfunctions (void) + { + m_subfunctions.clear (); + } - void mark_subfunctions_in_scope_as_private (const std::string& class_name); + void mark_subfunctions_in_scope_as_private (const std::string& class_name); - bool has_subfunctions (void) const - { - return ! m_subfunction_names.empty (); - } + bool has_subfunctions (void) const + { + return ! m_subfunction_names.empty (); + } - void stash_subfunction_names (const std::list& names) - { - m_subfunction_names = names; - } + void stash_subfunction_names (const std::list& names) + { + m_subfunction_names = names; + } - std::list subfunction_names (void) const - { - return m_subfunction_names; - } + std::list subfunction_names (void) const + { + return m_subfunction_names; + } - std::list localfunctions (void) const; + std::list localfunctions (void) const; - octave_value dump (void) const; + octave_value dump (void) const; - std::string name (void) const { return m_name; } + std::string name (void) const { return m_name; } - void cache_name (const std::string& name) { m_name = name; } + void cache_name (const std::string& name) { m_name = name; } - std::string fcn_name (void) const { return m_fcn_name; } + std::string fcn_name (void) const { return m_fcn_name; } - void cache_fcn_name (const std::string& name) { m_fcn_name = name; } + void cache_fcn_name (const std::string& name) { m_fcn_name = name; } - std::list parent_fcn_names (void) const; + std::list parent_fcn_names (void) const; - octave_user_code * user_code (void) const { return m_code; } + octave_user_code * user_code (void) const { return m_code; } - void set_user_code (octave_user_code *code) { m_code = code; } + void set_user_code (octave_user_code *code) { m_code = code; } - void set_parent (const std::shared_ptr& parent); + void set_parent (const std::shared_ptr& parent); - void set_primary_parent (const std::shared_ptr& parent); + void set_primary_parent (const std::shared_ptr& parent); - void cache_fcn_file_name (const std::string& name) - { - m_fcn_file_name = name; - } + void cache_fcn_file_name (const std::string& name) + { + m_fcn_file_name = name; + } - std::string fcn_file_name (void) const { return m_fcn_file_name; } + std::string fcn_file_name (void) const { return m_fcn_file_name; } - void cache_dir_name (const std::string& name); + void cache_dir_name (const std::string& name); - std::string dir_name (void) const { return m_dir_name; } + std::string dir_name (void) const { return m_dir_name; } - void mark_primary_fcn_scope (void) { m_is_primary_fcn_scope = true; } + void mark_primary_fcn_scope (void) { m_is_primary_fcn_scope = true; } - bool is_primary_fcn_scope (void) const { return m_is_primary_fcn_scope; } + bool is_primary_fcn_scope (void) const { return m_is_primary_fcn_scope; } - bool is_relative (const std::shared_ptr& scope) const; + bool is_relative (const std::shared_ptr& scope) const; - void mark_as_variable (const std::string& nm); - void mark_as_variables (const std::list& lst); + void mark_as_variable (const std::string& nm); + void mark_as_variables (const std::list& lst); - bool is_variable (const std::string& nm) const; + bool is_variable (const std::string& nm) const; - void update_nest (void); + void update_nest (void); - bool look_nonlocal (const std::string& name, std::size_t offset, - symbol_record& result); + bool look_nonlocal (const std::string& name, std::size_t offset, + symbol_record& result); - octave_value dump_symbols_map (void) const; + octave_value dump_symbols_map (void) const; - const std::map& symbols (void) const - { - return m_symbols; - } + const std::map& symbols (void) const + { + return m_symbols; + } - std::map& symbols (void) - { - return m_symbols; - } + std::map& symbols (void) + { + return m_symbols; + } - std::list symbol_list (void) const; + std::list symbol_list (void) const; - private: +private: - //! Name for this scope (usually the corresponding filename of the - //! function corresponding to the scope). + //! Name for this scope (usually the corresponding filename of the + //! function corresponding to the scope). - std::string m_name; + std::string m_name; - //! Map from symbol names to symbol info. + //! Map from symbol names to symbol info. - std::map m_symbols; + std::map m_symbols; - //! Map from symbol names to subfunctions. + //! Map from symbol names to subfunctions. - std::map m_subfunctions; + std::map m_subfunctions; - //! Map from data offset to persistent values in this scope. - std::map m_persistent_values; + //! Map from data offset to persistent values in this scope. + std::map m_persistent_values; - //! The list of subfunctions (if any) in the order they appear in - //! the function file. + //! The list of subfunctions (if any) in the order they appear in + //! the function file. - std::list m_subfunction_names; + std::list m_subfunction_names; - //! The associated user code (may be null). + //! The associated user code (may be null). - octave_user_code *m_code; + octave_user_code *m_code; - //! Simple name of the function corresponding to this scope. + //! Simple name of the function corresponding to this scope. - std::string m_fcn_name; + std::string m_fcn_name; - //! The file name associated with m_code. + //! The file name associated with m_code. - std::string m_fcn_file_name; + std::string m_fcn_file_name; - //! The directory associated with m_code. + //! The directory associated with m_code. - std::string m_dir_name; + std::string m_dir_name; - //! Parent of nested function (may be null). + //! Parent of nested function (may be null). - std::weak_ptr m_parent; + std::weak_ptr m_parent; - //! Primary (top) parent of nested function (may be null). Used - //! to determine whether two nested functions are related. + //! Primary (top) parent of nested function (may be null). Used + //! to determine whether two nested functions are related. - std::weak_ptr m_primary_parent; + std::weak_ptr m_primary_parent; - //! Child nested functions. + //! Child nested functions. - std::vector m_children; + std::vector m_children; - //! If true, then this scope belongs to a nested function. + //! If true, then this scope belongs to a nested function. - std::size_t m_nesting_depth; + std::size_t m_nesting_depth; - //! If true then no variables can be added. + //! If true then no variables can be added. - bool m_is_static; + bool m_is_static; - //! If true, this is the scope of a primary function. - bool m_is_primary_fcn_scope; - }; + //! If true, this is the scope of a primary function. + bool m_is_primary_fcn_scope; +}; - class symbol_scope - { - public: +class symbol_scope +{ +public: - // Create a valid but possibly unnamed scope. - symbol_scope (const std::string& name) - : m_rep (new symbol_scope_rep (name)) - { } + // Create a valid but possibly unnamed scope. + symbol_scope (const std::string& name) + : m_rep (new symbol_scope_rep (name)) + { } - // NEW_REP must be dynamically allocated or nullptr. If it is - // nullptr, the scope is invalid. - symbol_scope (const std::shared_ptr new_rep = nullptr) - : m_rep (new_rep) - { } + // NEW_REP must be dynamically allocated or nullptr. If it is + // nullptr, the scope is invalid. + symbol_scope (const std::shared_ptr new_rep = nullptr) + : m_rep (new_rep) + { } - symbol_scope (const symbol_scope&) = default; + symbol_scope (const symbol_scope&) = default; - symbol_scope& operator = (const symbol_scope&) = default; + symbol_scope& operator = (const symbol_scope&) = default; - ~symbol_scope (void) = default; + ~symbol_scope (void) = default; - bool is_valid (void) const { return bool (m_rep); } + bool is_valid (void) const { return bool (m_rep); } - explicit operator bool () const { return bool (m_rep); } + explicit operator bool () const { return bool (m_rep); } - std::size_t num_symbols (void) const - { - return m_rep ? m_rep->num_symbols () : 0; - } + std::size_t num_symbols (void) const + { + return m_rep ? m_rep->num_symbols () : 0; + } - symbol_record insert_local (const std::string& name) - { - return m_rep ? m_rep->insert_local (name) : symbol_record (); - } + symbol_record insert_local (const std::string& name) + { + return m_rep ? m_rep->insert_local (name) : symbol_record (); + } - void insert_symbol_record (symbol_record& sr) - { - if (m_rep) - m_rep->insert_symbol_record (sr); - } + void insert_symbol_record (symbol_record& sr) + { + if (m_rep) + m_rep->insert_symbol_record (sr); + } - bool is_nested (void) const - { - return m_rep ? m_rep->is_nested () : false; - } + bool is_nested (void) const + { + return m_rep ? m_rep->is_nested () : false; + } - bool is_parent (void) const - { - return m_rep ? m_rep->is_parent () : false; - } + bool is_parent (void) const + { + return m_rep ? m_rep->is_parent () : false; + } - void set_nesting_depth (std::size_t depth) - { - if (m_rep) - m_rep->set_nesting_depth (depth); - } + void set_nesting_depth (std::size_t depth) + { + if (m_rep) + m_rep->set_nesting_depth (depth); + } - std::size_t nesting_depth (void) const - { - return m_rep ? m_rep->nesting_depth () : 0; - } + std::size_t nesting_depth (void) const + { + return m_rep ? m_rep->nesting_depth () : 0; + } - bool is_static (void) const - { - return m_rep ? m_rep->is_static () : false; - } + bool is_static (void) const + { + return m_rep ? m_rep->is_static () : false; + } - void mark_static (void) - { - if (m_rep) - m_rep->mark_static (); - } + void mark_static (void) + { + if (m_rep) + m_rep->mark_static (); + } - std::shared_ptr parent_scope (void) const - { - return m_rep ? m_rep->parent_scope_rep () : nullptr; - } + std::shared_ptr parent_scope (void) const + { + return m_rep ? m_rep->parent_scope_rep () : nullptr; + } - std::shared_ptr primary_parent_scope (void) const - { - return m_rep ? m_rep->primary_parent_scope_rep () : nullptr; - } + std::shared_ptr primary_parent_scope (void) const + { + return m_rep ? m_rep->primary_parent_scope_rep () : nullptr; + } - symbol_scope dup (void) const - { - return symbol_scope (m_rep ? m_rep->dup () : nullptr); - } + symbol_scope dup (void) const + { + return symbol_scope (m_rep ? m_rep->dup () : nullptr); + } - octave_value& persistent_varref (std::size_t data_offset) - { - static octave_value dummy_value; + octave_value& persistent_varref (std::size_t data_offset) + { + static octave_value dummy_value; - return m_rep ? m_rep->persistent_varref (data_offset) : dummy_value; - } + return m_rep ? m_rep->persistent_varref (data_offset) : dummy_value; + } - octave_value persistent_varval (std::size_t data_offset) const - { - return m_rep ? m_rep->persistent_varval (data_offset) : octave_value (); - } + octave_value persistent_varval (std::size_t data_offset) const + { + return m_rep ? m_rep->persistent_varval (data_offset) : octave_value (); + } - symbol_record find_symbol (const std::string& name) - { - return m_rep ? m_rep->find_symbol (name) : symbol_record (); - } + symbol_record find_symbol (const std::string& name) + { + return m_rep ? m_rep->find_symbol (name) : symbol_record (); + } - // Like find_symbol, but does not insert. - symbol_record lookup_symbol (const std::string& name) const - { - return m_rep ? m_rep->lookup_symbol (name) : symbol_record (); - } + // Like find_symbol, but does not insert. + symbol_record lookup_symbol (const std::string& name) const + { + return m_rep ? m_rep->lookup_symbol (name) : symbol_record (); + } - symbol_record insert (const std::string& name) - { - return m_rep ? m_rep->insert (name) : symbol_record (); - } + symbol_record insert (const std::string& name) + { + return m_rep ? m_rep->insert (name) : symbol_record (); + } - void rename (const std::string& old_name, const std::string& new_name) - { - if (m_rep) - m_rep->rename (old_name, new_name); - } + void rename (const std::string& old_name, const std::string& new_name) + { + if (m_rep) + m_rep->rename (old_name, new_name); + } - void install_subfunction (const std::string& name, - const octave_value& fval) - { - if (m_rep) - m_rep->install_subfunction (name, fval); - } + void install_subfunction (const std::string& name, + const octave_value& fval) + { + if (m_rep) + m_rep->install_subfunction (name, fval); + } - void install_nestfunction (const std::string& name, - const octave_value& fval, - const symbol_scope& fcn_scope) - { - if (m_rep) - m_rep->install_nestfunction (name, fval, fcn_scope); - } + void install_nestfunction (const std::string& name, + const octave_value& fval, + const symbol_scope& fcn_scope) + { + if (m_rep) + m_rep->install_nestfunction (name, fval, fcn_scope); + } - octave_value find_subfunction (const std::string& name) const - { - return m_rep ? m_rep->find_subfunction (name) : octave_value (); - } + octave_value find_subfunction (const std::string& name) const + { + return m_rep ? m_rep->find_subfunction (name) : octave_value (); + } - void lock_subfunctions (void) - { - if (m_rep) - m_rep->lock_subfunctions (); - } + void lock_subfunctions (void) + { + if (m_rep) + m_rep->lock_subfunctions (); + } - void unlock_subfunctions (void) - { - if (m_rep) - m_rep->unlock_subfunctions (); - } + void unlock_subfunctions (void) + { + if (m_rep) + m_rep->unlock_subfunctions (); + } - std::map subfunctions (void) const - { - return (m_rep - ? m_rep->subfunctions () - : std::map ()); - } + std::map subfunctions (void) const + { + return (m_rep + ? m_rep->subfunctions () + : std::map ()); + } - void erase_subfunctions (void) - { - if (m_rep) - m_rep->erase_subfunctions (); - } + void erase_subfunctions (void) + { + if (m_rep) + m_rep->erase_subfunctions (); + } - void mark_subfunctions_in_scope_as_private (const std::string& class_name) - { - if (m_rep) - m_rep->mark_subfunctions_in_scope_as_private (class_name); - } + void mark_subfunctions_in_scope_as_private (const std::string& class_name) + { + if (m_rep) + m_rep->mark_subfunctions_in_scope_as_private (class_name); + } - bool has_subfunctions (void) const - { - return m_rep ? m_rep->has_subfunctions () : false; - } + bool has_subfunctions (void) const + { + return m_rep ? m_rep->has_subfunctions () : false; + } - void stash_subfunction_names (const std::list& names) - { - if (m_rep) - m_rep->stash_subfunction_names (names); - } + void stash_subfunction_names (const std::list& names) + { + if (m_rep) + m_rep->stash_subfunction_names (names); + } - std::list subfunction_names (void) const - { - return m_rep ? m_rep->subfunction_names () : std::list (); - } + std::list subfunction_names (void) const + { + return m_rep ? m_rep->subfunction_names () : std::list (); + } - // List of function handle objects. - std::list localfunctions (void) const; + // List of function handle objects. + std::list localfunctions (void) const; - octave_value dump (void) const - { - return m_rep ? m_rep->dump () : octave_value (); - } + octave_value dump (void) const + { + return m_rep ? m_rep->dump () : octave_value (); + } - std::string name (void) const - { - return m_rep ? m_rep->name () : ""; - } + std::string name (void) const + { + return m_rep ? m_rep->name () : ""; + } - void cache_name (const std::string& name) - { - if (m_rep) - m_rep->cache_name (name); - } + void cache_name (const std::string& name) + { + if (m_rep) + m_rep->cache_name (name); + } - std::string fcn_name (void) const - { - return m_rep ? m_rep->fcn_name () : ""; - } + std::string fcn_name (void) const + { + return m_rep ? m_rep->fcn_name () : ""; + } - void cache_fcn_name (const std::string& name) - { - if (m_rep) - m_rep->cache_fcn_name (name); - } + void cache_fcn_name (const std::string& name) + { + if (m_rep) + m_rep->cache_fcn_name (name); + } - std::list parent_fcn_names (void) const - { - return m_rep ? m_rep->parent_fcn_names () : std::list (); - } + std::list parent_fcn_names (void) const + { + return m_rep ? m_rep->parent_fcn_names () : std::list (); + } - octave_user_code * user_code (void) const - { - return m_rep ? m_rep->user_code () : nullptr; - } + octave_user_code * user_code (void) const + { + return m_rep ? m_rep->user_code () : nullptr; + } - void set_user_code (octave_user_code *code) - { - if (m_rep) - m_rep->set_user_code (code); - } + void set_user_code (octave_user_code *code) + { + if (m_rep) + m_rep->set_user_code (code); + } - void set_parent (const symbol_scope& p) - { - if (m_rep) - m_rep->set_parent (p.get_rep ()); - } + void set_parent (const symbol_scope& p) + { + if (m_rep) + m_rep->set_parent (p.get_rep ()); + } - void set_primary_parent (const symbol_scope& p) - { - if (m_rep) - m_rep->set_primary_parent (p.get_rep ()); - } + void set_primary_parent (const symbol_scope& p) + { + if (m_rep) + m_rep->set_primary_parent (p.get_rep ()); + } - void cache_fcn_file_name (const std::string& name) - { - if (m_rep) - m_rep->cache_fcn_file_name (name); - } + void cache_fcn_file_name (const std::string& name) + { + if (m_rep) + m_rep->cache_fcn_file_name (name); + } - void cache_dir_name (const std::string& name) - { - if (m_rep) - m_rep->cache_dir_name (name); - } + void cache_dir_name (const std::string& name) + { + if (m_rep) + m_rep->cache_dir_name (name); + } - std::string fcn_file_name (void) const - { - return m_rep ? m_rep->fcn_file_name () : ""; - } + std::string fcn_file_name (void) const + { + return m_rep ? m_rep->fcn_file_name () : ""; + } - std::string dir_name (void) const - { - return m_rep ? m_rep->dir_name () : ""; - } + std::string dir_name (void) const + { + return m_rep ? m_rep->dir_name () : ""; + } - void mark_primary_fcn_scope (void) - { - if (m_rep) - m_rep->mark_primary_fcn_scope (); - } + void mark_primary_fcn_scope (void) + { + if (m_rep) + m_rep->mark_primary_fcn_scope (); + } - bool is_primary_fcn_scope (void) const - { - return m_rep ? m_rep->is_primary_fcn_scope () : false; - } + bool is_primary_fcn_scope (void) const + { + return m_rep ? m_rep->is_primary_fcn_scope () : false; + } - bool is_relative (const symbol_scope& scope) const - { - return m_rep ? m_rep->is_relative (scope.get_rep ()) : false; - } + bool is_relative (const symbol_scope& scope) const + { + return m_rep ? m_rep->is_relative (scope.get_rep ()) : false; + } - void mark_as_variable (const std::string& nm) - { - if (m_rep) - m_rep->mark_as_variable (nm); - } + void mark_as_variable (const std::string& nm) + { + if (m_rep) + m_rep->mark_as_variable (nm); + } - void mark_as_variables (const std::list& lst) - { - if (m_rep) - m_rep->mark_as_variables (lst); - } + void mark_as_variables (const std::list& lst) + { + if (m_rep) + m_rep->mark_as_variables (lst); + } - bool is_variable (const std::string& nm) const - { - return m_rep ? m_rep->is_variable (nm) : false; - } + bool is_variable (const std::string& nm) const + { + return m_rep ? m_rep->is_variable (nm) : false; + } - void update_nest (void) - { - if (m_rep) - m_rep->update_nest (); - } + void update_nest (void) + { + if (m_rep) + m_rep->update_nest (); + } - bool look_nonlocal (const std::string& name, std::size_t offset, - symbol_record& result) - { - return m_rep ? m_rep->look_nonlocal (name, offset, result) : false; - } + bool look_nonlocal (const std::string& name, std::size_t offset, + symbol_record& result) + { + return m_rep ? m_rep->look_nonlocal (name, offset, result) : false; + } - std::shared_ptr get_rep (void) const - { - return m_rep; - } + std::shared_ptr get_rep (void) const + { + return m_rep; + } - friend bool operator == (const symbol_scope& a, const symbol_scope& b) - { - return a.m_rep == b.m_rep; - } + friend bool operator == (const symbol_scope& a, const symbol_scope& b) + { + return a.m_rep == b.m_rep; + } - friend bool operator != (const symbol_scope& a, const symbol_scope& b) - { - return a.m_rep != b.m_rep; - } + friend bool operator != (const symbol_scope& a, const symbol_scope& b) + { + return a.m_rep != b.m_rep; + } - const std::map& symbols (void) const - { - static const std::map empty_map; + const std::map& symbols (void) const + { + static const std::map empty_map; - return m_rep ? m_rep->symbols () : empty_map; - } + return m_rep ? m_rep->symbols () : empty_map; + } - std::map& symbols (void) - { - static std::map empty_map; + std::map& symbols (void) + { + static std::map empty_map; - return m_rep ? m_rep->symbols () : empty_map; - } + return m_rep ? m_rep->symbols () : empty_map; + } - std::list symbol_list (void) const - { - static const std::list empty_list; + std::list symbol_list (void) const + { + static const std::list empty_list; - return m_rep ? m_rep->symbol_list () : empty_list; - } + return m_rep ? m_rep->symbol_list () : empty_list; + } - private: +private: - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/corefcn/symtab.cc --- a/libinterp/corefcn/symtab.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/corefcn/symtab.cc Thu Dec 01 20:05:44 2022 -0800 @@ -50,677 +50,678 @@ OCTAVE_BEGIN_NAMESPACE(octave) - symbol_table::symbol_table (interpreter& interp) - : m_interpreter (interp), m_fcn_table (), m_class_precedence_table (), - m_parent_map () - { - install_builtins (); - } +symbol_table::symbol_table (interpreter& interp) + : m_interpreter (interp), m_fcn_table (), m_class_precedence_table (), + m_parent_map () +{ + install_builtins (); +} - symbol_scope symbol_table::current_scope (void) const - { - tree_evaluator& tw = m_interpreter.get_evaluator (); +symbol_scope symbol_table::current_scope (void) const +{ + tree_evaluator& tw = m_interpreter.get_evaluator (); - return tw.get_current_scope (); - } + return tw.get_current_scope (); +} - bool symbol_table::is_built_in_function_name (const std::string& name) - { - octave_value val = find_built_in_function (name); +bool symbol_table::is_built_in_function_name (const std::string& name) +{ + octave_value val = find_built_in_function (name); - return val.is_defined (); - } + return val.is_defined (); +} - octave_value - symbol_table::find_scoped_function (const std::string& name, - const symbol_scope& search_scope) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::find_scoped_function (const std::string& name, + const symbol_scope& search_scope) +{ + if (name.empty ()) + return octave_value (); - fcn_table_const_iterator p = m_fcn_table.find (name); + fcn_table_const_iterator p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_scoped_function (search_scope); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_scoped_function (search_scope); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_scoped_function (search_scope); + octave_value fcn = finfo.find_scoped_function (search_scope); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - octave_value - symbol_table::find_private_function (const std::string& dir_name, - const std::string& name) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::find_private_function (const std::string& dir_name, + const std::string& name) +{ + if (name.empty ()) + return octave_value (); - fcn_table_const_iterator p = m_fcn_table.find (name); + fcn_table_const_iterator p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_private_function (dir_name); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_private_function (dir_name); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_private_function (dir_name); + octave_value fcn = finfo.find_private_function (dir_name); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - // FIXME: this function only finds legacy class methods, not - // classdef methods. +// FIXME: this function only finds legacy class methods, not +// classdef methods. - octave_value symbol_table::find_method (const std::string& name, - const std::string& dispatch_type) - { - if (name.empty ()) - return octave_value (); +octave_value symbol_table::find_method (const std::string& name, + const std::string& dispatch_type) +{ + if (name.empty ()) + return octave_value (); - fcn_table_const_iterator p = m_fcn_table.find (name); + fcn_table_const_iterator p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_method (dispatch_type); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_method (dispatch_type); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_method (dispatch_type); + octave_value fcn = finfo.find_method (dispatch_type); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - octave_value symbol_table::find_built_in_function (const std::string& name) - { - fcn_table_const_iterator p = m_fcn_table.find (name); +octave_value symbol_table::find_built_in_function (const std::string& name) +{ + fcn_table_const_iterator p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_built_in_function (); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_built_in_function (); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_built_in_function (); + octave_value fcn = finfo.find_built_in_function (); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - octave_value symbol_table::find_autoload (const std::string& name) - { - if (name.empty ()) - return octave_value (); +octave_value symbol_table::find_autoload (const std::string& name) +{ + if (name.empty ()) + return octave_value (); - auto p = m_fcn_table.find (name); + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_autoload (); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_autoload (); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_autoload (); + octave_value fcn = finfo.find_autoload (); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - octave_value - symbol_table::builtin_find (const std::string& name, - const symbol_scope& search_scope_arg) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::builtin_find (const std::string& name, + const symbol_scope& search_scope_arg) +{ + if (name.empty ()) + return octave_value (); - fcn_table_iterator p = m_fcn_table.find (name); + fcn_table_iterator p = m_fcn_table.find (name); - symbol_scope search_scope - = (search_scope_arg ? search_scope_arg : current_scope ()); + symbol_scope search_scope + = (search_scope_arg ? search_scope_arg : current_scope ()); - if (p != m_fcn_table.end ()) - return p->second.builtin_find (search_scope); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.builtin_find (search_scope); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.builtin_find (search_scope); + octave_value fcn = finfo.builtin_find (search_scope); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } + return fcn; + } - return octave_value (); - } + return octave_value (); +} - octave_value - symbol_table::fcn_table_find (const std::string& name, - const octave_value_list& args, - const symbol_scope& search_scope_arg) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::fcn_table_find (const std::string& name, + const octave_value_list& args, + const symbol_scope& search_scope_arg) +{ + if (name.empty ()) + return octave_value (); - fcn_table_iterator p = m_fcn_table.find (name); + fcn_table_iterator p = m_fcn_table.find (name); - symbol_scope search_scope - = (search_scope_arg ? search_scope_arg : current_scope ()); + symbol_scope search_scope + = (search_scope_arg ? search_scope_arg : current_scope ()); - if (p != m_fcn_table.end ()) - return p->second.find (search_scope, args); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find (search_scope, args); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find (search_scope, args); + octave_value fcn = finfo.find (search_scope, args); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } + return fcn; + } - return octave_value (); - } + return octave_value (); +} - octave_value - symbol_table::find_function (const std::string& name, - const symbol_scope& search_scope_arg) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::find_function (const std::string& name, + const symbol_scope& search_scope_arg) +{ + if (name.empty ()) + return octave_value (); - if (name[0] == '@') - { - std::size_t pos = name.find_first_of ('/'); + if (name[0] == '@') + { + std::size_t pos = name.find_first_of ('/'); - if (pos == std::string::npos) - return octave_value (); + if (pos == std::string::npos) + return octave_value (); - std::string method = name.substr (pos+1); - std::string dispatch_type = name.substr (1, pos-1); + std::string method = name.substr (pos+1); + std::string dispatch_type = name.substr (1, pos-1); - return find_method (method, dispatch_type); - } - else - { - symbol_scope search_scope - = (search_scope_arg ? search_scope_arg : current_scope ()); + return find_method (method, dispatch_type); + } + else + { + symbol_scope search_scope + = (search_scope_arg ? search_scope_arg : current_scope ()); - return find_function (name, ovl (), search_scope); - } - } + return find_function (name, ovl (), search_scope); + } +} - octave_value - symbol_table::find_function (const std::string& name, - const octave_value_list& args, - const symbol_scope& search_scope) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::find_function (const std::string& name, + const octave_value_list& args, + const symbol_scope& search_scope) +{ + if (name.empty ()) + return octave_value (); - return fcn_table_find (name, args, search_scope); - } + return fcn_table_find (name, args, search_scope); +} - octave_value - symbol_table::find_user_function (const std::string& name) - { - if (name.empty ()) - return octave_value (); +octave_value +symbol_table::find_user_function (const std::string& name) +{ + if (name.empty ()) + return octave_value (); - auto p = m_fcn_table.find (name); + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_user_function (); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_user_function (); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_user_function (); + octave_value fcn = finfo.find_user_function (); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - octave_value symbol_table::find_cmdline_function (const std::string& name) - { - if (name.empty ()) - return octave_value (); +octave_value symbol_table::find_cmdline_function (const std::string& name) +{ + if (name.empty ()) + return octave_value (); - auto p = m_fcn_table.find (name); + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - return p->second.find_cmdline_function (); - else - { - fcn_info finfo (name); + if (p != m_fcn_table.end ()) + return p->second.find_cmdline_function (); + else + { + fcn_info finfo (name); - octave_value fcn = finfo.find_cmdline_function (); + octave_value fcn = finfo.find_cmdline_function (); - if (fcn.is_defined ()) - m_fcn_table[name] = finfo; + if (fcn.is_defined ()) + m_fcn_table[name] = finfo; - return fcn; - } - } + return fcn; + } +} - void symbol_table::install_cmdline_function (const std::string& name, - const octave_value& fcn) - { - auto p = m_fcn_table.find (name); +void symbol_table::install_cmdline_function (const std::string& name, + const octave_value& fcn) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.install_cmdline_function (fcn); - } - else - { - fcn_info finfo (name); + finfo.install_cmdline_function (fcn); + } + else + { + fcn_info finfo (name); - finfo.install_cmdline_function (fcn); + finfo.install_cmdline_function (fcn); - m_fcn_table[name] = finfo; - } - } + m_fcn_table[name] = finfo; + } +} - // Install local function FCN named NAME. FILE_NAME is the name of - // the file containing the local function. +// Install local function FCN named NAME. FILE_NAME is the name of +// the file containing the local function. - void symbol_table::install_local_function (const std::string& name, - const octave_value& fcn, - const std::string& file_name) - { - auto p = m_fcn_table.find (name); +void symbol_table::install_local_function (const std::string& name, + const octave_value& fcn, + const std::string& file_name) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.install_local_function (fcn, file_name); - } - else - { - fcn_info finfo (name); + finfo.install_local_function (fcn, file_name); + } + else + { + fcn_info finfo (name); - finfo.install_local_function (fcn, file_name); + finfo.install_local_function (fcn, file_name); - m_fcn_table[name] = finfo; - } - } + m_fcn_table[name] = finfo; + } +} - void symbol_table::install_user_function (const std::string& name, - const octave_value& fcn) - { - auto p = m_fcn_table.find (name); +void symbol_table::install_user_function (const std::string& name, + const octave_value& fcn) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.install_user_function (fcn); - } - else - { - fcn_info finfo (name); + finfo.install_user_function (fcn); + } + else + { + fcn_info finfo (name); - finfo.install_user_function (fcn); + finfo.install_user_function (fcn); - m_fcn_table[name] = finfo; - } - } + m_fcn_table[name] = finfo; + } +} - // FIXME: should we ensure that FCN really is a built-in function - // object? - void symbol_table::install_built_in_function (const std::string& name, - const octave_value& fcn) - { - auto p = m_fcn_table.find (name); +// FIXME: should we ensure that FCN really is a built-in function +// object? +void symbol_table::install_built_in_function (const std::string& name, + const octave_value& fcn) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.install_built_in_function (fcn); - } - else - { - fcn_info finfo (name); + finfo.install_built_in_function (fcn); + } + else + { + fcn_info finfo (name); - finfo.install_built_in_function (fcn); + finfo.install_built_in_function (fcn); - m_fcn_table[name] = finfo; - } - } + m_fcn_table[name] = finfo; + } +} - // This is written as two separate functions instead of a single - // function with default values so that it will work properly with - // unwind_protect. +// This is written as two separate functions instead of a single +// function with default values so that it will work properly with +// unwind_protect. - void symbol_table::clear_functions (bool force) - { - auto p = m_fcn_table.begin (); +void symbol_table::clear_functions (bool force) +{ + auto p = m_fcn_table.begin (); - while (p != m_fcn_table.end ()) - (p++)->second.clear (force); - } + while (p != m_fcn_table.end ()) + (p++)->second.clear (force); +} - void symbol_table::clear_function (const std::string& name) - { - clear_user_function (name); - } +void symbol_table::clear_function (const std::string& name) +{ + clear_user_function (name); +} - void symbol_table::clear_function_pattern (const std::string& pat) - { - glob_match pattern (pat); +void symbol_table::clear_function_pattern (const std::string& pat) +{ + glob_match pattern (pat); - auto p = m_fcn_table.begin (); + auto p = m_fcn_table.begin (); - while (p != m_fcn_table.end ()) - { - if (pattern.match (p->first)) - (p++)->second.clear_user_function (); - else - p++; - } - } + while (p != m_fcn_table.end ()) + { + if (pattern.match (p->first)) + (p++)->second.clear_user_function (); + else + p++; + } +} - void symbol_table::clear_function_regexp (const std::string& pat) - { - regexp pattern (pat); +void symbol_table::clear_function_regexp (const std::string& pat) +{ + regexp pattern (pat); - auto p = m_fcn_table.begin (); + auto p = m_fcn_table.begin (); - while (p != m_fcn_table.end ()) - { - if (pattern.is_match (p->first)) - (p++)->second.clear_user_function (); - else - p++; - } - } + while (p != m_fcn_table.end ()) + { + if (pattern.is_match (p->first)) + (p++)->second.clear_user_function (); + else + p++; + } +} - void symbol_table::clear_user_function (const std::string& name) - { - auto p = m_fcn_table.find (name); +void symbol_table::clear_user_function (const std::string& name) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.clear_user_function (); - } - // FIXME: is this necessary, or even useful? - // else - // error ("clear: no such function '%s'", name.c_str ()); - } + finfo.clear_user_function (); + } + // FIXME: is this necessary, or even useful? + // else + // error ("clear: no such function '%s'", name.c_str ()); +} - // This clears oct and mex files, including autoloads. - void symbol_table::clear_dld_function (const std::string& name) - { - auto p = m_fcn_table.find (name); +// This clears oct and mex files, including autoloads. +void symbol_table::clear_dld_function (const std::string& name) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.clear_autoload_function (); - finfo.clear_user_function (); - } - } + finfo.clear_autoload_function (); + finfo.clear_user_function (); + } +} - void symbol_table::clear_mex_functions (void) - { - auto p = m_fcn_table.begin (); +void symbol_table::clear_mex_functions (void) +{ + auto p = m_fcn_table.begin (); - while (p != m_fcn_table.end ()) - (p++)->second.clear_mex_function (); - } + while (p != m_fcn_table.end ()) + (p++)->second.clear_mex_function (); +} - // Insert INF_CLASS in the set of class names that are considered - // inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently - // marked as superior to SUP_CLASS. +// Insert INF_CLASS in the set of class names that are considered +// inferior to SUP_CLASS. Return FALSE if INF_CLASS is currently +// marked as superior to SUP_CLASS. - bool symbol_table::set_class_relationship (const std::string& sup_class, - const std::string& inf_class) - { - if (is_superiorto (inf_class, sup_class)) - return false; +bool symbol_table::set_class_relationship (const std::string& sup_class, + const std::string& inf_class) +{ + if (is_superiorto (inf_class, sup_class)) + return false; - // If sup_class doesn't have an entry in the precedence table, - // this will automatically create it, and associate to it a - // singleton set {inf_class} of inferior classes. - m_class_precedence_table[sup_class].insert (inf_class); + // If sup_class doesn't have an entry in the precedence table, + // this will automatically create it, and associate to it a + // singleton set {inf_class} of inferior classes. + m_class_precedence_table[sup_class].insert (inf_class); - return true; - } + return true; +} - // Has class A been marked as superior to class B? Also returns - // TRUE if B has been marked as inferior to A, since we only keep - // one table, and convert inferiorto information to a superiorto - // relationship. Two calls are required to determine whether there - // is no relationship between two classes: - // - // if (symbol_table::is_superiorto (a, b)) - // // A is superior to B, or B has been marked inferior to A. - // else if (symbol_table::is_superiorto (b, a)) - // // B is superior to A, or A has been marked inferior to B. - // else - // // No relation. +// Has class A been marked as superior to class B? Also returns +// TRUE if B has been marked as inferior to A, since we only keep +// one table, and convert inferiorto information to a superiorto +// relationship. Two calls are required to determine whether there +// is no relationship between two classes: +// +// if (symbol_table::is_superiorto (a, b)) +// // A is superior to B, or B has been marked inferior to A. +// else if (symbol_table::is_superiorto (b, a)) +// // B is superior to A, or A has been marked inferior to B. +// else +// // No relation. - bool symbol_table::is_superiorto (const std::string& a, const std::string& b) - { - class_precedence_table_const_iterator p = m_class_precedence_table.find (a); - // If a has no entry in the precedence table, return false - if (p == m_class_precedence_table.end ()) - return false; +bool symbol_table::is_superiorto (const std::string& a, const std::string& b) +{ + class_precedence_table_const_iterator p = m_class_precedence_table.find (a); + // If a has no entry in the precedence table, return false + if (p == m_class_precedence_table.end ()) + return false; - const std::set& inferior_classes = p->second; - std::set::const_iterator q = inferior_classes.find (b); - return (q != inferior_classes.end ()); - } + const std::set& inferior_classes = p->second; + std::set::const_iterator q = inferior_classes.find (b); + return (q != inferior_classes.end ()); +} - void symbol_table::alias_built_in_function (const std::string& alias, - const std::string& name) - { - octave_value fcn = find_built_in_function (name); +void symbol_table::alias_built_in_function (const std::string& alias, + const std::string& name) +{ + octave_value fcn = find_built_in_function (name); - if (fcn.is_defined ()) - { - fcn_info finfo (alias); + if (fcn.is_defined ()) + { + fcn_info finfo (alias); - finfo.install_built_in_function (fcn); + finfo.install_built_in_function (fcn); - m_fcn_table[alias] = finfo; - } - else - panic ("alias: '%s' is undefined", name.c_str ()); - } + m_fcn_table[alias] = finfo; + } + else + panic ("alias: '%s' is undefined", name.c_str ()); +} - void symbol_table::install_built_in_dispatch (const std::string& name, - const std::string& klass) - { - auto p = m_fcn_table.find (name); +void symbol_table::install_built_in_dispatch (const std::string& name, + const std::string& klass) +{ + auto p = m_fcn_table.find (name); - if (p != m_fcn_table.end ()) - { - fcn_info& finfo = p->second; + if (p != m_fcn_table.end ()) + { + fcn_info& finfo = p->second; - finfo.install_built_in_dispatch (klass); - } - else - error ("install_built_in_dispatch: '%s' is undefined", name.c_str ()); - } + finfo.install_built_in_dispatch (klass); + } + else + error ("install_built_in_dispatch: '%s' is undefined", name.c_str ()); +} - std::list symbol_table::user_function_names (void) - { - std::list retval; +std::list symbol_table::user_function_names (void) +{ + std::list retval; - for (const auto& nm_finfo : m_fcn_table) - { - if (nm_finfo.second.is_user_function_defined ()) - retval.push_back (nm_finfo.first); - } + for (const auto& nm_finfo : m_fcn_table) + { + if (nm_finfo.second.is_user_function_defined ()) + retval.push_back (nm_finfo.first); + } - if (! retval.empty ()) - retval.sort (); + if (! retval.empty ()) + retval.sort (); - return retval; - } + return retval; +} - std::list symbol_table::built_in_function_names (void) - { - std::list retval; +std::list symbol_table::built_in_function_names (void) +{ + std::list retval; - for (const auto& nm_finfo : m_fcn_table) - { - octave_value fcn = nm_finfo.second.find_built_in_function (); + for (const auto& nm_finfo : m_fcn_table) + { + octave_value fcn = nm_finfo.second.find_built_in_function (); - if (fcn.is_defined ()) - retval.push_back (nm_finfo.first); - } + if (fcn.is_defined ()) + retval.push_back (nm_finfo.first); + } - if (! retval.empty ()) - retval.sort (); + if (! retval.empty ()) + retval.sort (); - return retval; - } + return retval; +} - std::list symbol_table::cmdline_function_names (void) - { - std::list retval; +std::list symbol_table::cmdline_function_names (void) +{ + std::list retval; - for (const auto& nm_finfo : m_fcn_table) - { - octave_value fcn = nm_finfo.second.find_cmdline_function (); + for (const auto& nm_finfo : m_fcn_table) + { + octave_value fcn = nm_finfo.second.find_cmdline_function (); - if (fcn.is_defined ()) - retval.push_back (nm_finfo.first); - } + if (fcn.is_defined ()) + retval.push_back (nm_finfo.first); + } - if (! retval.empty ()) - retval.sort (); + if (! retval.empty ()) + retval.sort (); - return retval; - } + return retval; +} - template All attribute validation should occur here. - //! - //! Classdef attribute values can be given in the form of - //! expressions. These expressions must be evaluated before - //! assigning them as attribute values. Evaluating them as they are - //! parsed causes trouble with possible recursion in the parser so we - //! do it here. For example - //! - //! @code - //! classdef recursion_class - //! methods (Access = ?recursion_class) - //! endmethods - //! endclassdef - //! @endcode - //! - //! will fail because each attempt to compute the metaclass of - //! recursion_class will cause recursion_class to be parsed again. + OCTINTERP_API octave_value get_method (const std::string& name) const; + + OCTINTERP_API octave_value construct (const octave_value_list& args); + + OCTINTERP_API cdef_object + construct_object (const octave_value_list& args); + + OCTINTERP_API void initialize_object (cdef_object& obj); + + OCTINTERP_API void + run_constructor (cdef_object& obj, const octave_value_list& args); + + void mark_as_handle_class (void) { m_handle_class = true; } + + bool is_handle_class (void) const { return m_handle_class; } - static OCTINTERP_API cdef_class - make_meta_class (interpreter& interp, tree_classdef *t, - bool is_at_folder = false); - - octave_value get_method (const std::string& nm) const - { - return get_rep ()->get_method (nm); - } + octave_idx_type static_count (void) const { return m_member_count; } - OCTINTERP_API octave_value get_method_function (const std::string& nm); - - octave_value get_constructor_function (void) + void destroy (void) { - return get_method_function (get_name ()); - } + if (m_member_count) + { + m_count++; + cdef_class lock (this); - octave_value construct (const octave_value_list& args) - { - return get_rep ()->construct (args); + m_member_count = 0; + m_method_map.clear (); + m_property_map.clear (); + } + else + delete this; } - cdef_object construct_object (const octave_value_list& args) - { - return get_rep ()->construct_object (args); - } - - void initialize_object (cdef_object& obj) - { - get_rep ()->initialize_object (obj); - } + void mark_as_meta_class (void) { m_meta = true; } - void run_constructor (cdef_object& obj, const octave_value_list& args) - { - get_rep ()->run_constructor (obj, args); - } + bool is_meta_class (void) const { return m_meta; } - void mark_as_handle_class (void) - { - get_rep ()->mark_as_handle_class (); - } + void doc_string (const std::string& txt) { m_doc_string = txt; } - bool is_handle_class (void) const - { - return get_rep ()->is_handle_class (); - } - - void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); } - - bool is_meta_class (void) const { return get_rep ()->is_meta_class (); } - - void doc_string (const std::string& txt) { get_rep ()->doc_string (txt); } - - std::string doc_string (void) const { return get_rep ()->doc_string (); } + std::string doc_string (void) const { return m_doc_string; } - void file_name (const std::string& nm) { get_rep ()->file_name (nm); } - - std::string file_name (void) const { return get_rep ()->file_name (); } - - public: + void file_name (const std::string& nm) { m_file_name = nm; } - enum - { - property_normal, - property_inherited, - property_all - }; + std::string file_name (void) const { return m_file_name; } private: - cdef_class_rep * get_rep (void) + OCTINTERP_API void load_all_methods (void); + + OCTINTERP_API void find_names (std::set& names, bool all); + + OCTINTERP_API void + find_properties (std::map& props, + int mode = 0); + + OCTINTERP_API void + find_methods (std::map& meths, + bool only_inherited, bool include_ctor = false); + + cdef_class wrap (void) { - return dynamic_cast (cdef_object::get_rep ()); - } - - const cdef_class_rep * get_rep (void) const - { - return dynamic_cast (cdef_object::get_rep ()); + m_count++; + return cdef_class (this); } - friend OCTINTERP_API bool operator == (const cdef_class&, const cdef_class&); - friend OCTINTERP_API bool operator != (const cdef_class&, const cdef_class&); - friend OCTINTERP_API bool operator < (const cdef_class&, const cdef_class&); + // The @-directory were this class is loaded from. + // (not used yet) + + std::string m_directory; + + std::string m_doc_string; + + std::string m_file_name; + + // The methods defined by this class. + + std::map m_method_map; + + // The properties defined by this class. + + std::map m_property_map; + + // The number of members in this class (methods, properties...) + + octave_idx_type m_member_count; - friend void install_classdef (octave::interpreter& interp); + // TRUE if this class is a handle class. A class is a handle + // class when the abstract "handle" class is one of its superclasses. + + bool m_handle_class; + + // The list of super-class constructors that are called implicitly by the + // classdef engine when creating an object. These constructors are not + // called explicitly by the class constructor. + + std::list m_implicit_ctor_list; + + // TRUE if this class is a built-in meta class. + + bool m_meta; + + // Utility iterator typedefs. + + typedef std::map::iterator method_iterator; + typedef std::map::const_iterator method_const_iterator; + typedef std::map::iterator property_iterator; + typedef std::map::const_iterator property_const_iterator; + + cdef_class_rep (const cdef_class_rep& c) = default; }; - inline bool - operator == (const cdef_class& clsa, const cdef_class& clsb) +public: + + // Create an invalid class object. + + cdef_class (void) : cdef_meta_object () { } + + cdef_class (const std::string& nm, + const std::list& superclasses) + : cdef_meta_object (new cdef_class_rep (superclasses)) + { + get_rep ()->set_name (nm); + } + + cdef_class (const cdef_class& cls) : cdef_meta_object (cls) { } + + cdef_class (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_class ()) + error ("internal error: invalid assignment from %s to meta.class object", + class_name ().c_str ()); + } + + cdef_class& operator = (const cdef_class& cls) + { + cdef_object::operator = (cls); + + return *this; + } + + ~cdef_class (void) = default; + + OCTINTERP_API cdef_method + find_method (const std::string& nm, bool local = false); + + void install_method (const cdef_method& meth) { - // FIXME: is this really the right way to check class equality? + get_rep ()->install_method (meth); + } + + Cell get_methods (bool include_ctor = false) + { + return get_rep ()->get_methods (include_ctor); + } + + std::map + get_method_map (bool only_inherited = false, bool include_ctor = false) + { + return get_rep ()->get_method_map (only_inherited, include_ctor); + } + + OCTINTERP_API cdef_property find_property (const std::string& nm); + + void install_property (const cdef_property& prop) + { + get_rep ()->install_property (prop); + } - return (clsa.get_rep () == clsb.get_rep ()); + Cell get_properties (int mode = property_normal) + { + return get_rep ()->get_properties (mode); + } + + std::map + get_property_map (int mode = property_normal) + { + return get_rep ()->get_property_map (mode); + } + + string_vector get_names (void) { return get_rep ()->get_names (); } + + bool is_abstract (void) const { return get_rep ()->is_abstract (); } + + bool is_sealed (void) const { return get_rep ()->is_sealed (); } + + void set_directory (const std::string& dir) + { + get_rep ()->set_directory (dir); } - inline bool - operator != (const cdef_class& clsa, const cdef_class& clsb) + std::string get_directory (void) const + { + return get_rep ()->get_directory (); + } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_builtin (void) const { return get_directory ().empty (); } + + void delete_object (const cdef_object& obj) { - return ! (clsa == clsb); + get_rep ()->delete_object (obj); + } + + //! Analyze the tree_classdef tree and transform it to a cdef_class + //! + //! All attribute validation should occur here. + //! + //! Classdef attribute values can be given in the form of + //! expressions. These expressions must be evaluated before + //! assigning them as attribute values. Evaluating them as they are + //! parsed causes trouble with possible recursion in the parser so we + //! do it here. For example + //! + //! @code + //! classdef recursion_class + //! methods (Access = ?recursion_class) + //! endmethods + //! endclassdef + //! @endcode + //! + //! will fail because each attempt to compute the metaclass of + //! recursion_class will cause recursion_class to be parsed again. + + static OCTINTERP_API cdef_class + make_meta_class (interpreter& interp, tree_classdef *t, + bool is_at_folder = false); + + octave_value get_method (const std::string& nm) const + { + return get_rep ()->get_method (nm); + } + + OCTINTERP_API octave_value get_method_function (const std::string& nm); + + octave_value get_constructor_function (void) + { + return get_method_function (get_name ()); + } + + octave_value construct (const octave_value_list& args) + { + return get_rep ()->construct (args); + } + + cdef_object construct_object (const octave_value_list& args) + { + return get_rep ()->construct_object (args); + } + + void initialize_object (cdef_object& obj) + { + get_rep ()->initialize_object (obj); + } + + void run_constructor (cdef_object& obj, const octave_value_list& args) + { + get_rep ()->run_constructor (obj, args); + } + + void mark_as_handle_class (void) + { + get_rep ()->mark_as_handle_class (); } - // This is only to be able to use cdef_class as map keys. + bool is_handle_class (void) const + { + return get_rep ()->is_handle_class (); + } + + void mark_as_meta_class (void) { get_rep ()->mark_as_meta_class (); } + + bool is_meta_class (void) const { return get_rep ()->is_meta_class (); } + + void doc_string (const std::string& txt) { get_rep ()->doc_string (txt); } + + std::string doc_string (void) const { return get_rep ()->doc_string (); } + + void file_name (const std::string& nm) { get_rep ()->file_name (nm); } + + std::string file_name (void) const { return get_rep ()->file_name (); } - inline bool - operator < (const cdef_class& clsa, const cdef_class& clsb) +public: + + enum { - return clsa.get_rep () < clsb.get_rep (); + property_normal, + property_inherited, + property_all + }; + +private: + + cdef_class_rep * get_rep (void) + { + return dynamic_cast (cdef_object::get_rep ()); + } + + const cdef_class_rep * get_rep (void) const + { + return dynamic_cast (cdef_object::get_rep ()); } - inline cdef_method - cdef_class::find_method (const std::string& nm, bool local) - { - return get_rep ()->find_method (nm, local); - } + friend OCTINTERP_API bool operator == (const cdef_class&, const cdef_class&); + friend OCTINTERP_API bool operator != (const cdef_class&, const cdef_class&); + friend OCTINTERP_API bool operator < (const cdef_class&, const cdef_class&); + + friend void install_classdef (octave::interpreter& interp); +}; + +inline bool +operator == (const cdef_class& clsa, const cdef_class& clsb) +{ + // FIXME: is this really the right way to check class equality? + + return (clsa.get_rep () == clsb.get_rep ()); +} - inline cdef_property - cdef_class::find_property (const std::string& nm) - { - return get_rep ()->find_property (nm); - } +inline bool +operator != (const cdef_class& clsa, const cdef_class& clsb) +{ + return ! (clsa == clsb); +} + +// This is only to be able to use cdef_class as map keys. + +inline bool +operator < (const cdef_class& clsa, const cdef_class& clsb) +{ + return clsa.get_rep () < clsb.get_rep (); +} + +inline cdef_method +cdef_class::find_method (const std::string& nm, bool local) +{ + return get_rep ()->find_method (nm, local); +} + +inline cdef_property +cdef_class::find_property (const std::string& nm) +{ + return get_rep ()->find_property (nm); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-fwd.h --- a/libinterp/octave-value/cdef-fwd.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-fwd.h Thu Dec 01 20:05:44 2022 -0800 @@ -30,9 +30,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class OCTINTERP_API cdef_class; - class OCTINTERP_API cdef_object; - class OCTINTERP_API cdef_package; +class OCTINTERP_API cdef_class; +class OCTINTERP_API cdef_object; +class OCTINTERP_API cdef_package; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-manager.cc --- a/libinterp/octave-value/cdef-manager.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-manager.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,143 +34,143 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static octave_value - make_fcn_handle (octave_builtin::fcn ff, const std::string& nm) - { - octave_value fcn (new octave_builtin (ff, nm)); +static octave_value +make_fcn_handle (octave_builtin::fcn ff, const std::string& nm) +{ + octave_value fcn (new octave_builtin (ff, nm)); - return octave_value (new octave_fcn_handle (fcn)); - } + return octave_value (new octave_fcn_handle (fcn)); +} - static octave_value_list - class_get_properties (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +class_get_properties (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () == 1 && args(0).type_name () == "object") - { - cdef_class cls (to_cdef (args(0))); + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); - retval(0) = cls.get_properties (); - } + retval(0) = cls.get_properties (); + } - return retval; - } + return retval; +} - static octave_value_list - class_get_methods (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +class_get_methods (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () == 1 && args(0).type_name () == "object") - { - cdef_class cls (to_cdef (args(0))); + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_class cls (to_cdef (args(0))); - retval(0) = cls.get_methods (); - } + retval(0) = cls.get_methods (); + } - return retval; - } + return retval; +} - static octave_value_list - class_get_superclasses (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +class_get_superclasses (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () == 1 && args(0).type_name () == "object" - && args(0).class_name () == "meta.class") - { - cdef_class cls (to_cdef (args(0))); + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls (to_cdef (args(0))); - Cell classes = cls.get ("SuperClasses").cell_value (); + Cell classes = cls.get ("SuperClasses").cell_value (); - retval(0) = to_ov (lookup_classes (classes)); - } + retval(0) = to_ov (lookup_classes (classes)); + } - return retval; - } + return retval; +} - static octave_value_list - class_get_inferiorclasses (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +class_get_inferiorclasses (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () == 1 && args(0).type_name () == "object" - && args(0).class_name () == "meta.class") - { - cdef_class cls (to_cdef (args(0))); + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.class") + { + cdef_class cls (to_cdef (args(0))); - Cell classes = cls.get ("InferiorClasses").cell_value (); + Cell classes = cls.get ("InferiorClasses").cell_value (); - retval(0) = to_ov (lookup_classes (classes)); - } + retval(0) = to_ov (lookup_classes (classes)); + } - return retval; - } + return retval; +} - static octave_value_list - class_fromName (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +class_fromName (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () != 1) - error ("fromName: invalid number of parameters"); + if (args.length () != 1) + error ("fromName: invalid number of parameters"); - std::string name = args(0).xstring_value ("fromName: CLASS_NAME must be a string"); + std::string name = args(0).xstring_value ("fromName: CLASS_NAME must be a string"); - retval(0) = to_ov (lookup_class (name, false)); + retval(0) = to_ov (lookup_class (name, false)); - return retval; - } + return retval; +} - static octave_value_list - class_fevalStatic (const octave_value_list& args, int nargout) - { - if (args.length () <= 1 || args(0).type_name () != "object") - error ("fevalStatic: first argument must be a meta.class object"); +static octave_value_list +class_fevalStatic (const octave_value_list& args, int nargout) +{ + if (args.length () <= 1 || args(0).type_name () != "object") + error ("fevalStatic: first argument must be a meta.class object"); - cdef_class cls (to_cdef (args(0))); + cdef_class cls (to_cdef (args(0))); - std::string meth_name = args(1).xstring_value ("fevalStatic: method name must be a string"); + std::string meth_name = args(1).xstring_value ("fevalStatic: method name must be a string"); - cdef_method meth = cls.find_method (meth_name); + cdef_method meth = cls.find_method (meth_name); - if (! meth.ok ()) - error ("fevalStatic: method not found: %s", meth_name.c_str ()); + if (! meth.ok ()) + error ("fevalStatic: method not found: %s", meth_name.c_str ()); - if (! meth.is_static ()) - error ("fevalStatic: method '%s' is not static", meth_name.c_str ()); + if (! meth.is_static ()) + error ("fevalStatic: method '%s' is not static", meth_name.c_str ()); - return meth.execute (args.splice (0, 2), nargout, true, "fevalStatic"); - } + return meth.execute (args.splice (0, 2), nargout, true, "fevalStatic"); +} - static octave_value_list - class_getConstant (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +class_getConstant (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () != 2 || args(0).type_name () != "object" - || args(0).class_name () != "meta.class") - error ("getConstant: first argument must be a meta.class object"); + if (args.length () != 2 || args(0).type_name () != "object" + || args(0).class_name () != "meta.class") + error ("getConstant: first argument must be a meta.class object"); - cdef_class cls = to_cdef (args(0)); + cdef_class cls = to_cdef (args(0)); - std::string prop_name = args(1).xstring_value ("getConstant: property name must be a string"); + std::string prop_name = args(1).xstring_value ("getConstant: property name must be a string"); - cdef_property prop = cls.find_property (prop_name); + cdef_property prop = cls.find_property (prop_name); - if (! prop.ok ()) - error ("getConstant: property not found: %s", - prop_name.c_str ()); + if (! prop.ok ()) + error ("getConstant: property not found: %s", + prop_name.c_str ()); - if (! prop.is_constant ()) - error ("getConstant: property '%s' is not constant", - prop_name.c_str ()); + if (! prop.is_constant ()) + error ("getConstant: property '%s' is not constant", + prop_name.c_str ()); - retval(0) = prop.get_value (true, "getConstant"); + retval(0) = prop.get_value (true, "getConstant"); - return retval; - } + return retval; +} #define META_CLASS_CMP(OP, CLSA, CLSB, FCN) \ static octave_value_list \ @@ -194,757 +194,757 @@ return retval; \ } - META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass) - META_CLASS_CMP (le, clsb, clsa, is_superclass) - META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass) - META_CLASS_CMP (ge, clsa, clsb, is_superclass) - META_CLASS_CMP (eq, clsa, clsb, operator==) - META_CLASS_CMP (ne, clsa, clsb, operator!=) +META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass) +META_CLASS_CMP (le, clsb, clsa, is_superclass) +META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass) +META_CLASS_CMP (ge, clsa, clsb, is_superclass) +META_CLASS_CMP (eq, clsa, clsb, operator==) +META_CLASS_CMP (ne, clsa, clsb, operator!=) - static octave_value_list - property_get_defaultvalue (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +property_get_defaultvalue (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () == 1 && args(0).type_name () == "object") - { - cdef_property prop (to_cdef (args(0))); + if (args.length () == 1 && args(0).type_name () == "object") + { + cdef_property prop (to_cdef (args(0))); - retval(0) = prop.get ("DefaultValue"); + retval(0) = prop.get ("DefaultValue"); - if (! retval(0).is_defined ()) - error_with_id ("Octave:class:NoDefaultDefined", - "no default value for property '%s'", - prop.get_name ().c_str ()); - } + if (! retval(0).is_defined ()) + error_with_id ("Octave:class:NoDefaultDefined", + "no default value for property '%s'", + prop.get_name ().c_str ()); + } - return retval; - } + return retval; +} - static octave_value_list - handle_delete (const octave_value_list& /* args */, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +handle_delete (const octave_value_list& /* args */, int /* nargout */) +{ + octave_value_list retval; - // FIXME: implement this. Wait, what is this supposed to do? + // FIXME: implement this. Wait, what is this supposed to do? - return retval; - } + return retval; +} - static octave_value_list - package_get_classes (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval (1, Matrix ()); +static octave_value_list +package_get_classes (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); - if (args.length () == 1 && args(0).type_name () == "object" - && args(0).class_name () == "meta.package") - { - cdef_package pack (to_cdef (args(0))); + if (args.length () == 1 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); - retval(0) = pack.get_classes (); - } + retval(0) = pack.get_classes (); + } - return retval; - } + return retval; +} - static octave_value_list - package_get_functions (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval (1, Matrix ()); +static octave_value_list +package_get_functions (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); - if (args.length () == 0 && args(0).type_name () == "object" - && args(0).class_name () == "meta.package") - { - cdef_package pack (to_cdef (args(0))); + if (args.length () == 0 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); - retval(0) = pack.get_functions (); - } + retval(0) = pack.get_functions (); + } - return retval; - } + return retval; +} - static octave_value_list - package_get_packages (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval (1, Matrix ()); +static octave_value_list +package_get_packages (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval (1, Matrix ()); - if (args.length () == 0 && args(0).type_name () == "object" - && args(0).class_name () == "meta.package") - { - cdef_package pack (to_cdef (args(0))); + if (args.length () == 0 && args(0).type_name () == "object" + && args(0).class_name () == "meta.package") + { + cdef_package pack (to_cdef (args(0))); - retval(0) = pack.get_packages (); - } + retval(0) = pack.get_packages (); + } - return retval; - } + return retval; +} - static octave_value_list - package_getAllPackages (interpreter& interp, - const octave_value_list& /* args */, - int /* nargout */) - { - std::map toplevel_packages; +static octave_value_list +package_getAllPackages (interpreter& interp, + const octave_value_list& /* args */, + int /* nargout */) +{ + std::map toplevel_packages; - load_path& lp = interp.get_load_path (); + load_path& lp = interp.get_load_path (); - std::list names = lp.get_all_package_names (); + std::list names = lp.get_all_package_names (); - cdef_manager& cdm = interp.get_cdef_manager (); + cdef_manager& cdm = interp.get_cdef_manager (); - toplevel_packages["meta"] = cdm.find_package ("meta", false, false); + toplevel_packages["meta"] = cdm.find_package ("meta", false, false); - for (const auto& nm : names) - toplevel_packages[nm] = cdm.find_package (nm, false, true); + for (const auto& nm : names) + toplevel_packages[nm] = cdm.find_package (nm, false, true); - Cell c (toplevel_packages.size (), 1); + Cell c (toplevel_packages.size (), 1); - int i = 0; + int i = 0; - for (const auto& nm_pkg : toplevel_packages) - c(i++, 0) = to_ov (nm_pkg.second); + for (const auto& nm_pkg : toplevel_packages) + c(i++, 0) = to_ov (nm_pkg.second); - return octave_value_list (octave_value (c)); - } + return octave_value_list (octave_value (c)); +} - static octave_value_list - package_fromName (const octave_value_list& args, int /* nargout */) - { - octave_value_list retval; +static octave_value_list +package_fromName (const octave_value_list& args, int /* nargout */) +{ + octave_value_list retval; - if (args.length () != 1) - error ("fromName: invalid number of parameters"); + if (args.length () != 1) + error ("fromName: invalid number of parameters"); - std::string name = args(0).xstring_value ("fromName: PACKAGE_NAME must be a string"); + std::string name = args(0).xstring_value ("fromName: PACKAGE_NAME must be a string"); - retval(0) = to_ov (lookup_package (name, false)); + retval(0) = to_ov (lookup_package (name, false)); - return retval; - } + return retval; +} - cdef_manager::cdef_manager (interpreter& interp) - : m_interpreter (interp), m_all_classes (), m_all_packages (), - m_meta_class (), m_meta_property (), m_meta_method (), - m_meta_package (), m_meta () - { - type_info& ti = m_interpreter.get_type_info (); +cdef_manager::cdef_manager (interpreter& interp) + : m_interpreter (interp), m_all_classes (), m_all_packages (), + m_meta_class (), m_meta_property (), m_meta_method (), + m_meta_package (), m_meta () +{ + type_info& ti = m_interpreter.get_type_info (); - octave_classdef::register_type (ti); + octave_classdef::register_type (ti); - // bootstrap - cdef_class tmp_handle = make_class ("handle"); + // bootstrap + cdef_class tmp_handle = make_class ("handle"); - m_meta_class = make_meta_class ("meta.class", tmp_handle); + m_meta_class = make_meta_class ("meta.class", tmp_handle); - tmp_handle.set_class (m_meta_class); - m_meta_class.set_class (m_meta_class); + tmp_handle.set_class (m_meta_class); + m_meta_class.set_class (m_meta_class); - // meta classes - m_meta_property = make_meta_class ("meta.property", tmp_handle); + // meta classes + m_meta_property = make_meta_class ("meta.property", tmp_handle); - m_meta_method = make_meta_class ("meta.method", tmp_handle); + m_meta_method = make_meta_class ("meta.method", tmp_handle); - m_meta_package = make_meta_class ("meta.package", tmp_handle); + m_meta_package = make_meta_class ("meta.package", tmp_handle); - cdef_class tmp_meta_event - = make_meta_class ("meta.event", tmp_handle); + cdef_class tmp_meta_event + = make_meta_class ("meta.event", tmp_handle); - cdef_class tmp_meta_dynproperty - = make_meta_class ("meta.dynamicproperty", tmp_handle); + cdef_class tmp_meta_dynproperty + = make_meta_class ("meta.dynamicproperty", tmp_handle); - // meta.class properties - m_meta_class.install_property - (make_attribute (m_meta_class, "Abstract")); + // meta.class properties + m_meta_class.install_property + (make_attribute (m_meta_class, "Abstract")); - m_meta_class.install_property - (make_attribute (m_meta_class, "ConstructOnLoad")); + m_meta_class.install_property + (make_attribute (m_meta_class, "ConstructOnLoad")); - m_meta_class.install_property - (make_property (m_meta_class, "ContainingPackage")); + m_meta_class.install_property + (make_property (m_meta_class, "ContainingPackage")); - m_meta_class.install_property - (make_property (m_meta_class, "Description")); + m_meta_class.install_property + (make_property (m_meta_class, "Description")); - m_meta_class.install_property - (make_property (m_meta_class, "DetailedDescription")); + m_meta_class.install_property + (make_property (m_meta_class, "DetailedDescription")); - m_meta_class.install_property - (make_property (m_meta_class, "Events")); + m_meta_class.install_property + (make_property (m_meta_class, "Events")); - m_meta_class.install_property - (make_attribute (m_meta_class, "HandleCompatible")); + m_meta_class.install_property + (make_attribute (m_meta_class, "HandleCompatible")); - m_meta_class.install_property - (make_attribute (m_meta_class, "Hidden")); + m_meta_class.install_property + (make_attribute (m_meta_class, "Hidden")); - m_meta_class.install_property - (make_property (m_meta_class, "InferiorClasses", - make_fcn_handle (class_get_inferiorclasses, - "meta.class>get.InferiorClasses"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "InferiorClasses", + make_fcn_handle (class_get_inferiorclasses, + "meta.class>get.InferiorClasses"), + "public", Matrix (), "private")); - m_meta_class.install_property - (make_property (m_meta_class, "Methods", - make_fcn_handle (class_get_methods, - "meta.class>get.Methods"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "Methods", + make_fcn_handle (class_get_methods, + "meta.class>get.Methods"), + "public", Matrix (), "private")); - m_meta_class.install_property - (make_property (m_meta_class, "MethodList", - make_fcn_handle (class_get_methods, - "meta.class>get.MethodList"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "MethodList", + make_fcn_handle (class_get_methods, + "meta.class>get.MethodList"), + "public", Matrix (), "private")); - m_meta_class.install_property (make_attribute (m_meta_class, "Name")); + m_meta_class.install_property (make_attribute (m_meta_class, "Name")); - m_meta_class.install_property - (make_property (m_meta_class, "Properties", - make_fcn_handle (class_get_properties, - "meta.class>get.Properties"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "Properties", + make_fcn_handle (class_get_properties, + "meta.class>get.Properties"), + "public", Matrix (), "private")); - m_meta_class.install_property - (make_property (m_meta_class, "PropertyList", - make_fcn_handle (class_get_properties, - "meta.class>get.PropertyList"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "PropertyList", + make_fcn_handle (class_get_properties, + "meta.class>get.PropertyList"), + "public", Matrix (), "private")); - m_meta_class.install_property (make_attribute (m_meta_class, "Sealed")); + m_meta_class.install_property (make_attribute (m_meta_class, "Sealed")); - m_meta_class.install_property - (make_property (m_meta_class, "SuperClasses", - make_fcn_handle (class_get_superclasses, - "meta.class>get.SuperClasses"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "SuperClasses", + make_fcn_handle (class_get_superclasses, + "meta.class>get.SuperClasses"), + "public", Matrix (), "private")); - m_meta_class.install_property - (make_property (m_meta_class, "SuperclassList", - make_fcn_handle (class_get_superclasses, - "meta.class>get.SuperclassList"), - "public", Matrix (), "private")); + m_meta_class.install_property + (make_property (m_meta_class, "SuperclassList", + make_fcn_handle (class_get_superclasses, + "meta.class>get.SuperclassList"), + "public", Matrix (), "private")); - // FIXME: Matlab supports this property under "SuperclassList". - // Octave, however, has supported this under "SuperClassList". - // Alias the property. Remove in Octave version 8.1. - m_meta_class.install_property - (make_property (m_meta_class, "SuperClassList", - make_fcn_handle (class_get_superclasses, - "meta.class>get.SuperclassList"), - "public", Matrix (), "private")); + // FIXME: Matlab supports this property under "SuperclassList". + // Octave, however, has supported this under "SuperClassList". + // Alias the property. Remove in Octave version 8.1. + m_meta_class.install_property + (make_property (m_meta_class, "SuperClassList", + make_fcn_handle (class_get_superclasses, + "meta.class>get.SuperclassList"), + "public", Matrix (), "private")); - // meta.class methods - m_meta_class.install_method - (make_method (m_meta_class, "fromName", class_fromName, "public", true)); + // meta.class methods + m_meta_class.install_method + (make_method (m_meta_class, "fromName", class_fromName, "public", true)); - m_meta_class.install_method - (make_method (m_meta_class, "fevalStatic", class_fevalStatic, "public", - false)); + m_meta_class.install_method + (make_method (m_meta_class, "fevalStatic", class_fevalStatic, "public", + false)); - m_meta_class.install_method - (make_method (m_meta_class, "getConstant", class_getConstant, "public", - false)); + m_meta_class.install_method + (make_method (m_meta_class, "getConstant", class_getConstant, "public", + false)); - m_meta_class.install_method (make_method (m_meta_class, "eq", class_eq)); - m_meta_class.install_method (make_method (m_meta_class, "ne", class_ne)); - m_meta_class.install_method (make_method (m_meta_class, "lt", class_lt)); - m_meta_class.install_method (make_method (m_meta_class, "le", class_le)); - m_meta_class.install_method (make_method (m_meta_class, "gt", class_gt)); - m_meta_class.install_method (make_method (m_meta_class, "ge", class_ge)); + m_meta_class.install_method (make_method (m_meta_class, "eq", class_eq)); + m_meta_class.install_method (make_method (m_meta_class, "ne", class_ne)); + m_meta_class.install_method (make_method (m_meta_class, "lt", class_lt)); + m_meta_class.install_method (make_method (m_meta_class, "le", class_le)); + m_meta_class.install_method (make_method (m_meta_class, "gt", class_gt)); + m_meta_class.install_method (make_method (m_meta_class, "ge", class_ge)); - // meta.method properties - m_meta_method.install_property - (make_attribute (m_meta_method, "Abstract")); + // meta.method properties + m_meta_method.install_property + (make_attribute (m_meta_method, "Abstract")); - m_meta_method.install_property - (make_attribute (m_meta_method, "Access")); + m_meta_method.install_property + (make_attribute (m_meta_method, "Access")); - m_meta_method.install_property - (make_attribute (m_meta_method, "DefiningClass")); + m_meta_method.install_property + (make_attribute (m_meta_method, "DefiningClass")); - m_meta_method.install_property - (make_attribute (m_meta_method, "Description")); + m_meta_method.install_property + (make_attribute (m_meta_method, "Description")); - m_meta_method.install_property - (make_attribute (m_meta_method, "DetailedDescription")); + m_meta_method.install_property + (make_attribute (m_meta_method, "DetailedDescription")); - m_meta_method.install_property - (make_attribute (m_meta_method, "Hidden")); + m_meta_method.install_property + (make_attribute (m_meta_method, "Hidden")); - m_meta_method.install_property - (make_attribute (m_meta_method, "Name")); + m_meta_method.install_property + (make_attribute (m_meta_method, "Name")); - m_meta_method.install_property - (make_attribute (m_meta_method, "Sealed")); + m_meta_method.install_property + (make_attribute (m_meta_method, "Sealed")); - m_meta_method.install_property - (make_attribute (m_meta_method, "Static")); + m_meta_method.install_property + (make_attribute (m_meta_method, "Static")); - // meta.property properties - m_meta_property.install_property - (make_attribute (m_meta_property, "Name")); + // meta.property properties + m_meta_property.install_property + (make_attribute (m_meta_property, "Name")); - m_meta_property.install_property - (make_attribute (m_meta_property, "Description")); + m_meta_property.install_property + (make_attribute (m_meta_property, "Description")); - m_meta_property.install_property - (make_attribute (m_meta_property, "DetailedDescription")); + m_meta_property.install_property + (make_attribute (m_meta_property, "DetailedDescription")); - m_meta_property.install_property - (make_attribute (m_meta_property, "Abstract")); + m_meta_property.install_property + (make_attribute (m_meta_property, "Abstract")); - m_meta_property.install_property - (make_attribute (m_meta_property, "Constant")); + m_meta_property.install_property + (make_attribute (m_meta_property, "Constant")); - m_meta_property.install_property - (make_attribute (m_meta_property, "GetAccess")); + m_meta_property.install_property + (make_attribute (m_meta_property, "GetAccess")); - m_meta_property.install_property - (make_attribute (m_meta_property, "SetAccess")); + m_meta_property.install_property + (make_attribute (m_meta_property, "SetAccess")); - m_meta_property.install_property - (make_attribute (m_meta_property, "Dependent")); + m_meta_property.install_property + (make_attribute (m_meta_property, "Dependent")); - m_meta_property.install_property - (make_attribute (m_meta_property, "Transient")); + m_meta_property.install_property + (make_attribute (m_meta_property, "Transient")); - m_meta_property.install_property - (make_attribute (m_meta_property, "Hidden")); + m_meta_property.install_property + (make_attribute (m_meta_property, "Hidden")); - m_meta_property.install_property - (make_attribute (m_meta_property, "GetObservable")); + m_meta_property.install_property + (make_attribute (m_meta_property, "GetObservable")); - m_meta_property.install_property - (make_attribute (m_meta_property, "SetObservable")); + m_meta_property.install_property + (make_attribute (m_meta_property, "SetObservable")); - m_meta_property.install_property - (make_attribute (m_meta_property, "GetMethod")); + m_meta_property.install_property + (make_attribute (m_meta_property, "GetMethod")); - m_meta_property.install_property - (make_attribute (m_meta_property, "SetMethod")); + m_meta_property.install_property + (make_attribute (m_meta_property, "SetMethod")); - m_meta_property.install_property - (make_attribute (m_meta_property, "DefiningClass")); + m_meta_property.install_property + (make_attribute (m_meta_property, "DefiningClass")); - m_meta_property.install_property - (make_property (m_meta_property, "DefaultValue", - make_fcn_handle (property_get_defaultvalue, - "meta.property>get.DefaultValue"), - "public", Matrix (), "private")); + m_meta_property.install_property + (make_property (m_meta_property, "DefaultValue", + make_fcn_handle (property_get_defaultvalue, + "meta.property>get.DefaultValue"), + "public", Matrix (), "private")); - m_meta_property.install_property - (make_attribute (m_meta_property, "HasDefault")); + m_meta_property.install_property + (make_attribute (m_meta_property, "HasDefault")); - // meta.property events - // FIXME: add events + // meta.property events + // FIXME: add events - // handle methods + // handle methods - tmp_handle.install_method - (make_method (tmp_handle, "delete", handle_delete)); + tmp_handle.install_method + (make_method (tmp_handle, "delete", handle_delete)); - // meta.package properties + // meta.package properties - m_meta_package.install_property - (make_attribute (m_meta_package, "Name")); + m_meta_package.install_property + (make_attribute (m_meta_package, "Name")); - m_meta_package.install_property - (make_property (m_meta_package, "ContainingPackage")); + m_meta_package.install_property + (make_property (m_meta_package, "ContainingPackage")); - m_meta_package.install_property - (make_property (m_meta_package, "ClassList", - make_fcn_handle (package_get_classes, - "meta.package>get.ClassList"), - "public", Matrix (), "private")); + m_meta_package.install_property + (make_property (m_meta_package, "ClassList", + make_fcn_handle (package_get_classes, + "meta.package>get.ClassList"), + "public", Matrix (), "private")); - m_meta_package.install_property - (make_property (m_meta_package, "Classes", - make_fcn_handle (package_get_classes, - "meta.package>get.Classes"), - "public", Matrix (), "private")); + m_meta_package.install_property + (make_property (m_meta_package, "Classes", + make_fcn_handle (package_get_classes, + "meta.package>get.Classes"), + "public", Matrix (), "private")); - m_meta_package.install_property - (make_property (m_meta_package, "FunctionList", - make_fcn_handle (package_get_functions, - "meta.package>get.FunctionList"), - "public", Matrix (), "private")); + m_meta_package.install_property + (make_property (m_meta_package, "FunctionList", + make_fcn_handle (package_get_functions, + "meta.package>get.FunctionList"), + "public", Matrix (), "private")); - m_meta_package.install_property - (make_property (m_meta_package, "Functions", - make_fcn_handle (package_get_functions, - "meta.package>get.Functions"), - "public", Matrix (), "private")); + m_meta_package.install_property + (make_property (m_meta_package, "Functions", + make_fcn_handle (package_get_functions, + "meta.package>get.Functions"), + "public", Matrix (), "private")); - m_meta_package.install_property - (make_property (m_meta_package, "PackageList", - make_fcn_handle (package_get_packages, - "meta.package>get.PackageList"), - "public", Matrix (), "private")); + m_meta_package.install_property + (make_property (m_meta_package, "PackageList", + make_fcn_handle (package_get_packages, + "meta.package>get.PackageList"), + "public", Matrix (), "private")); - m_meta_package.install_property - (make_property (m_meta_package, "Packages", - make_fcn_handle (package_get_packages, - "meta.package>get.Packages"), - "public", Matrix (), "private")); + m_meta_package.install_property + (make_property (m_meta_package, "Packages", + make_fcn_handle (package_get_packages, + "meta.package>get.Packages"), + "public", Matrix (), "private")); - m_meta_package.install_method - (make_method (m_meta_package, "fromName", package_fromName, - "public", true)); + m_meta_package.install_method + (make_method (m_meta_package, "fromName", package_fromName, + "public", true)); - m_meta_package.install_method - (make_method (m_meta_package, "getAllPackages", package_getAllPackages, - "public", true)); + m_meta_package.install_method + (make_method (m_meta_package, "getAllPackages", package_getAllPackages, + "public", true)); - // create "meta" package - cdef_package package_meta - = m_meta + // create "meta" package + cdef_package package_meta + = m_meta = make_package ("meta"); - package_meta.install_class (m_meta_class, "class"); - package_meta.install_class (m_meta_property, "property"); - package_meta.install_class (m_meta_method, "method"); - package_meta.install_class (m_meta_package, "package"); - package_meta.install_class (tmp_meta_event, "event"); - package_meta.install_class (tmp_meta_dynproperty, "dynproperty"); + package_meta.install_class (m_meta_class, "class"); + package_meta.install_class (m_meta_property, "property"); + package_meta.install_class (m_meta_method, "method"); + package_meta.install_class (m_meta_package, "package"); + package_meta.install_class (tmp_meta_event, "event"); + package_meta.install_class (tmp_meta_dynproperty, "dynproperty"); - symbol_table& symtab = m_interpreter.get_symbol_table (); + symbol_table& symtab = m_interpreter.get_symbol_table (); - // install built-in classes into the symbol table - symtab.install_built_in_function - ("meta.class", m_meta_class.get_constructor_function ()); + // install built-in classes into the symbol table + symtab.install_built_in_function + ("meta.class", m_meta_class.get_constructor_function ()); - symtab.install_built_in_function - ("meta.method", m_meta_method.get_constructor_function ()); + symtab.install_built_in_function + ("meta.method", m_meta_method.get_constructor_function ()); - symtab.install_built_in_function - ("meta.property", m_meta_property.get_constructor_function ()); + symtab.install_built_in_function + ("meta.property", m_meta_property.get_constructor_function ()); - symtab.install_built_in_function - ("meta.package", m_meta_package.get_constructor_function ()); + symtab.install_built_in_function + ("meta.package", m_meta_package.get_constructor_function ()); - // FIXME: meta.event and meta.dynproperty are not implemented - // and should not be installed into symbol table. + // FIXME: meta.event and meta.dynproperty are not implemented + // and should not be installed into symbol table. - // symtab.install_built_in_function - // ("meta.event", tmp_meta_event.get_constructor_function ()); + // symtab.install_built_in_function + // ("meta.event", tmp_meta_event.get_constructor_function ()); - // symtab.install_built_in_function - // ("meta.dynproperty", tmp_meta_dynproperty.get_constructor_function ()); - } + // symtab.install_built_in_function + // ("meta.dynproperty", tmp_meta_dynproperty.get_constructor_function ()); +} - cdef_class - cdef_manager::find_class (const std::string& name, bool error_if_not_found, - bool load_if_not_found) - { - auto it = m_all_classes.find (name); +cdef_class +cdef_manager::find_class (const std::string& name, bool error_if_not_found, + bool load_if_not_found) +{ + auto it = m_all_classes.find (name); - if (it == m_all_classes.end ()) - { - if (load_if_not_found) - { - octave_value ov_cls; + if (it == m_all_classes.end ()) + { + if (load_if_not_found) + { + octave_value ov_cls; - std::size_t pos = name.rfind ('.'); + std::size_t pos = name.rfind ('.'); - if (pos == std::string::npos) - ov_cls = m_interpreter.find (name); - else - { - std::string pack_name = name.substr (0, pos); + if (pos == std::string::npos) + ov_cls = m_interpreter.find (name); + else + { + std::string pack_name = name.substr (0, pos); - cdef_package pack = find_package (pack_name, false, true); + cdef_package pack = find_package (pack_name, false, true); - if (pack.ok ()) - ov_cls = pack.find (name.substr (pos+1)); - } + if (pack.ok ()) + ov_cls = pack.find (name.substr (pos+1)); + } - if (ov_cls.is_defined ()) - it = m_all_classes.find (name); - } - } + if (ov_cls.is_defined ()) + it = m_all_classes.find (name); + } + } - if (it == m_all_classes.end ()) - { - if (error_if_not_found) - error ("class not found: %s", name.c_str ()); - } - else - { - cdef_class cls = it->second; + if (it == m_all_classes.end ()) + { + if (error_if_not_found) + error ("class not found: %s", name.c_str ()); + } + else + { + cdef_class cls = it->second; - if (! cls.is_builtin ()) - cls = lookup_class (cls); + if (! cls.is_builtin ()) + cls = lookup_class (cls); - if (cls.ok ()) - return cls; - else - m_all_classes.erase (it); - } + if (cls.ok ()) + return cls; + else + m_all_classes.erase (it); + } - return cdef_class (); - } + return cdef_class (); +} - octave_value - cdef_manager::find_method_symbol (const std::string& method_name, - const std::string& class_name) - { - cdef_class cls = find_class (class_name, false, false); +octave_value +cdef_manager::find_method_symbol (const std::string& method_name, + const std::string& class_name) +{ + cdef_class cls = find_class (class_name, false, false); - if (cls.ok ()) - { - cdef_method meth = cls.find_method (method_name); + if (cls.ok ()) + { + cdef_method meth = cls.find_method (method_name); - if (meth.ok ()) - return octave_value (new octave_classdef_meta (meth)); - } + if (meth.ok ()) + return octave_value (new octave_classdef_meta (meth)); + } - return octave_value (); - } + return octave_value (); +} - cdef_package - cdef_manager::find_package (const std::string& name, bool error_if_not_found, - bool load_if_not_found) - { - cdef_package retval; +cdef_package +cdef_manager::find_package (const std::string& name, bool error_if_not_found, + bool load_if_not_found) +{ + cdef_package retval; - std::map::const_iterator it - = m_all_packages.find (name); + std::map::const_iterator it + = m_all_packages.find (name); - if (it != m_all_packages.end ()) - { - retval = it->second; + if (it != m_all_packages.end ()) + { + retval = it->second; - if (! retval.ok ()) - error ("invalid package '%s'", name.c_str ()); - } - else - { - load_path& lp = m_interpreter.get_load_path (); + if (! retval.ok ()) + error ("invalid package '%s'", name.c_str ()); + } + else + { + load_path& lp = m_interpreter.get_load_path (); - if (load_if_not_found && lp.find_package (name)) - { - std::size_t pos = name.rfind ('.'); + if (load_if_not_found && lp.find_package (name)) + { + std::size_t pos = name.rfind ('.'); - if (pos == std::string::npos) - retval = make_package (name, ""); - else - { - std::string parent_name = name.substr (0, pos); + if (pos == std::string::npos) + retval = make_package (name, ""); + else + { + std::string parent_name = name.substr (0, pos); - retval = make_package (name, parent_name); - } - } - else if (error_if_not_found) - error ("unknown package '%s'", name.c_str ()); - } + retval = make_package (name, parent_name); + } + } + else if (error_if_not_found) + error ("unknown package '%s'", name.c_str ()); + } - return retval; - } + return retval; +} - octave_value - cdef_manager::find_package_symbol (const std::string& pack_name) - { - cdef_package pack = find_package (pack_name, false); +octave_value +cdef_manager::find_package_symbol (const std::string& pack_name) +{ + cdef_package pack = find_package (pack_name, false); - if (pack.ok ()) - return octave_value (new octave_classdef_meta (pack)); + if (pack.ok ()) + return octave_value (new octave_classdef_meta (pack)); - return octave_value (); - } + return octave_value (); +} - cdef_class - cdef_manager::make_class (const std::string& name, - const std::list& super_list) - { - cdef_class cls (name, super_list); +cdef_class +cdef_manager::make_class (const std::string& name, + const std::list& super_list) +{ + cdef_class cls (name, super_list); - cls.set_class (meta_class ()); + cls.set_class (meta_class ()); - cls.put ("Abstract", false); - cls.put ("ConstructOnLoad", false); - cls.put ("ContainingPackage", Matrix ()); - cls.put ("Description", ""); - cls.put ("DetailedDescription", ""); - cls.put ("Events", Cell ()); - cls.put ("Hidden", false); - cls.put ("InferiorClasses", Cell ()); - cls.put ("Methods", Cell ()); - cls.put ("Properties", Cell ()); - cls.put ("Sealed", false); + cls.put ("Abstract", false); + cls.put ("ConstructOnLoad", false); + cls.put ("ContainingPackage", Matrix ()); + cls.put ("Description", ""); + cls.put ("DetailedDescription", ""); + cls.put ("Events", Cell ()); + cls.put ("Hidden", false); + cls.put ("InferiorClasses", Cell ()); + cls.put ("Methods", Cell ()); + cls.put ("Properties", Cell ()); + cls.put ("Sealed", false); - if (name == "handle") - { - cls.put ("HandleCompatible", true); - cls.mark_as_handle_class (); - } - else if (super_list.empty ()) - { - cls.put ("HandleCompatible", false); - } - else - { - bool all_handle_compatible = true; - bool has_handle_class = false; + if (name == "handle") + { + cls.put ("HandleCompatible", true); + cls.mark_as_handle_class (); + } + else if (super_list.empty ()) + { + cls.put ("HandleCompatible", false); + } + else + { + bool all_handle_compatible = true; + bool has_handle_class = false; - for (const auto& cl : super_list) - { - all_handle_compatible = all_handle_compatible - && cl.get ("HandleCompatible").bool_value (); + for (const auto& cl : super_list) + { + all_handle_compatible = all_handle_compatible + && cl.get ("HandleCompatible").bool_value (); - has_handle_class = has_handle_class || cl.is_handle_class (); - } + has_handle_class = has_handle_class || cl.is_handle_class (); + } - if (has_handle_class && ! all_handle_compatible) - error ("%s: cannot mix handle and non-HandleCompatible classes", - name.c_str ()); + if (has_handle_class && ! all_handle_compatible) + error ("%s: cannot mix handle and non-HandleCompatible classes", + name.c_str ()); - cls.put ("HandleCompatible", all_handle_compatible); - if (has_handle_class) - cls.mark_as_handle_class (); - } + cls.put ("HandleCompatible", all_handle_compatible); + if (has_handle_class) + cls.mark_as_handle_class (); + } - if (! name.empty ()) - register_class (cls); + if (! name.empty ()) + register_class (cls); - return cls; - } + return cls; +} - cdef_class - cdef_manager::make_class (const std::string& name, - const cdef_class& super) - { - return make_class (name, std::list (1, super)); - } +cdef_class +cdef_manager::make_class (const std::string& name, + const cdef_class& super) +{ + return make_class (name, std::list (1, super)); +} - cdef_class - cdef_manager::make_meta_class (const std::string& name, - const cdef_class& super) - { - cdef_class cls = make_class (name, super); +cdef_class +cdef_manager::make_meta_class (const std::string& name, + const cdef_class& super) +{ + cdef_class cls = make_class (name, super); - cls.put ("Sealed", true); - cls.mark_as_meta_class (); + cls.put ("Sealed", true); + cls.mark_as_meta_class (); - return cls; - } + return cls; +} - cdef_property - cdef_manager::make_property (const cdef_class& cls, const std::string& name, - const octave_value& get_method, - const std::string& get_access, - const octave_value& set_method, - const std::string& set_access) - { - cdef_property prop (name); +cdef_property +cdef_manager::make_property (const cdef_class& cls, const std::string& name, + const octave_value& get_method, + const std::string& get_access, + const octave_value& set_method, + const std::string& set_access) +{ + cdef_property prop (name); - prop.set_class (meta_property ()); + prop.set_class (meta_property ()); - prop.put ("Description", ""); - prop.put ("DetailedDescription", ""); - prop.put ("Abstract", false); - prop.put ("Constant", false); - prop.put ("GetAccess", get_access); - prop.put ("SetAccess", set_access); - prop.put ("Dependent", false); - prop.put ("Transient", false); - prop.put ("Hidden", false); - prop.put ("GetObservable", false); - prop.put ("SetObservable", false); - prop.put ("GetMethod", get_method); - prop.put ("SetMethod", set_method); - prop.put ("DefiningClass", to_ov (cls)); - prop.put ("DefaultValue", octave_value ()); - prop.put ("HasDefault", false); + prop.put ("Description", ""); + prop.put ("DetailedDescription", ""); + prop.put ("Abstract", false); + prop.put ("Constant", false); + prop.put ("GetAccess", get_access); + prop.put ("SetAccess", set_access); + prop.put ("Dependent", false); + prop.put ("Transient", false); + prop.put ("Hidden", false); + prop.put ("GetObservable", false); + prop.put ("SetObservable", false); + prop.put ("GetMethod", get_method); + prop.put ("SetMethod", set_method); + prop.put ("DefiningClass", to_ov (cls)); + prop.put ("DefaultValue", octave_value ()); + prop.put ("HasDefault", false); - std::string class_name = cls.get_name (); + std::string class_name = cls.get_name (); - if (! get_method.isempty ()) - make_function_of_class (class_name, get_method); - if (! set_method.isempty ()) - make_function_of_class (class_name, set_method); + if (! get_method.isempty ()) + make_function_of_class (class_name, get_method); + if (! set_method.isempty ()) + make_function_of_class (class_name, set_method); - return prop; - } + return prop; +} - cdef_property - cdef_manager::make_attribute (const cdef_class& cls, const std::string& name) - { - return make_property (cls, name, Matrix (), "public", Matrix (), "private"); - } +cdef_property +cdef_manager::make_attribute (const cdef_class& cls, const std::string& name) +{ + return make_property (cls, name, Matrix (), "public", Matrix (), "private"); +} - cdef_method - cdef_manager::make_method (const cdef_class& cls, const std::string& name, - const octave_value& fcn, - const std::string& m_access, bool is_static) - { - cdef_method meth (name); +cdef_method +cdef_manager::make_method (const cdef_class& cls, const std::string& name, + const octave_value& fcn, + const std::string& m_access, bool is_static) +{ + cdef_method meth (name); - meth.set_class (meta_method ()); + meth.set_class (meta_method ()); - meth.put ("Abstract", false); - meth.put ("Access", m_access); - meth.put ("DefiningClass", to_ov (cls)); - meth.put ("Description", ""); - meth.put ("DetailedDescription", ""); - meth.put ("Hidden", false); - meth.put ("Sealed", true); - meth.put ("Static", is_static); + meth.put ("Abstract", false); + meth.put ("Access", m_access); + meth.put ("DefiningClass", to_ov (cls)); + meth.put ("Description", ""); + meth.put ("DetailedDescription", ""); + meth.put ("Hidden", false); + meth.put ("Sealed", true); + meth.put ("Static", is_static); - if (fcn.is_defined ()) - make_function_of_class (cls, fcn); + if (fcn.is_defined ()) + make_function_of_class (cls, fcn); - meth.set_function (fcn); + meth.set_function (fcn); - if (is_dummy_method (fcn)) - meth.mark_as_external (cls.get_name ()); + if (is_dummy_method (fcn)) + meth.mark_as_external (cls.get_name ()); - return meth; - } + return meth; +} - cdef_method - cdef_manager::make_method (const cdef_class& cls, const std::string& name, - octave_builtin::fcn ff, - const std::string& m_access, bool is_static) - { - octave_value fcn (new octave_builtin (ff, name)); +cdef_method +cdef_manager::make_method (const cdef_class& cls, const std::string& name, + octave_builtin::fcn ff, + const std::string& m_access, bool is_static) +{ + octave_value fcn (new octave_builtin (ff, name)); - return make_method (cls, name, fcn, m_access, is_static); - } + return make_method (cls, name, fcn, m_access, is_static); +} - cdef_method - cdef_manager::make_method (const cdef_class& cls, const std::string& name, - octave_builtin::meth mm, - const std::string& m_access, bool is_static) - { - octave_value fcn (new octave_builtin (mm, name)); +cdef_method +cdef_manager::make_method (const cdef_class& cls, const std::string& name, + octave_builtin::meth mm, + const std::string& m_access, bool is_static) +{ + octave_value fcn (new octave_builtin (mm, name)); - return make_method (cls, name, fcn, m_access, is_static); - } + return make_method (cls, name, fcn, m_access, is_static); +} - cdef_package - cdef_manager::make_package (const std::string& nm, const std::string& parent) - { - cdef_package pack (nm); +cdef_package +cdef_manager::make_package (const std::string& nm, const std::string& parent) +{ + cdef_package pack (nm); - pack.set_class (meta_package ()); + pack.set_class (meta_package ()); - if (parent.empty ()) - pack.put ("ContainingPackage", Matrix ()); - else - pack.put ("ContainingPackage", to_ov (find_package (parent))); + if (parent.empty ()) + pack.put ("ContainingPackage", Matrix ()); + else + pack.put ("ContainingPackage", to_ov (find_package (parent))); - if (! nm.empty ()) - register_package (pack); + if (! nm.empty ()) + register_package (pack); - return pack; - } + return pack; +} - octave_value - cdef_manager::find_method (const std::string& class_name, - const std::string& name) const - { - cdef_class cls = lookup_class (class_name); +octave_value +cdef_manager::find_method (const std::string& class_name, + const std::string& name) const +{ + cdef_class cls = lookup_class (class_name); - return cls.get_method (name); - } + return cls.get_method (name); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-manager.h --- a/libinterp/octave-value/cdef-manager.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-manager.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,128 +37,128 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; - class - OCTINTERP_API - cdef_manager - { - public: +class +OCTINTERP_API +cdef_manager +{ +public: - OCTINTERP_API cdef_manager (interpreter& interp); + OCTINTERP_API cdef_manager (interpreter& interp); + + // No copying! + + cdef_manager (const cdef_manager&) = delete; - // No copying! + cdef_manager& operator = (const cdef_manager&) = delete; - cdef_manager (const cdef_manager&) = delete; + ~cdef_manager (void) = default; - cdef_manager& operator = (const cdef_manager&) = delete; + OCTINTERP_API cdef_class + find_class (const std::string& name, bool error_if_not_found = true, + bool load_if_not_found = true); - ~cdef_manager (void) = default; + OCTINTERP_API octave_value + find_method_symbol (const std::string& method_name, + const std::string& class_name); - OCTINTERP_API cdef_class - find_class (const std::string& name, bool error_if_not_found = true, + OCTINTERP_API cdef_package + find_package (const std::string& name, bool error_if_not_found = true, bool load_if_not_found = true); - OCTINTERP_API octave_value - find_method_symbol (const std::string& method_name, - const std::string& class_name); + OCTINTERP_API octave_value + find_package_symbol (const std::string& pack_name); - OCTINTERP_API cdef_package - find_package (const std::string& name, bool error_if_not_found = true, - bool load_if_not_found = true); + void register_class (const cdef_class& cls) + { + m_all_classes[cls.get_name ()] = cls; + } - OCTINTERP_API octave_value - find_package_symbol (const std::string& pack_name); + void unregister_class (const cdef_class& cls) + { + m_all_classes.erase(cls.get_name ()); + } - void register_class (const cdef_class& cls) - { - m_all_classes[cls.get_name ()] = cls; - } - - void unregister_class (const cdef_class& cls) - { - m_all_classes.erase(cls.get_name ()); - } + void register_package (const cdef_package& pkg) + { + m_all_packages[pkg.get_name ()] = pkg; + } - void register_package (const cdef_package& pkg) - { - m_all_packages[pkg.get_name ()] = pkg; - } + void unregister_package (const cdef_package& pkg) + { + m_all_packages.erase (pkg.get_name ()); + } - void unregister_package (const cdef_package& pkg) - { - m_all_packages.erase (pkg.get_name ()); - } + const cdef_class& meta_class (void) const { return m_meta_class; } + const cdef_class& meta_property (void) const { return m_meta_property; } + const cdef_class& meta_method (void) const { return m_meta_method; } + const cdef_class& meta_package (void) const { return m_meta_package; } - const cdef_class& meta_class (void) const { return m_meta_class; } - const cdef_class& meta_property (void) const { return m_meta_property; } - const cdef_class& meta_method (void) const { return m_meta_method; } - const cdef_class& meta_package (void) const { return m_meta_package; } + const cdef_package& meta (void) const { return m_meta; } - const cdef_package& meta (void) const { return m_meta; } + OCTINTERP_API cdef_class + make_class (const std::string& name, + const std::list& super_list = std::list ()); - OCTINTERP_API cdef_class - make_class (const std::string& name, - const std::list& super_list = std::list ()); + OCTINTERP_API cdef_class + make_class (const std::string& name, const cdef_class& super); - OCTINTERP_API cdef_class - make_class (const std::string& name, const cdef_class& super); - - OCTINTERP_API cdef_class - make_meta_class (const std::string& name, const cdef_class& super); + OCTINTERP_API cdef_class + make_meta_class (const std::string& name, const cdef_class& super); - OCTINTERP_API cdef_property - make_property (const cdef_class& cls, const std::string& name, - const octave_value& get_method = Matrix (), - const std::string& get_access = "public", - const octave_value& set_method = Matrix (), - const std::string& set_access = "public"); + OCTINTERP_API cdef_property + make_property (const cdef_class& cls, const std::string& name, + const octave_value& get_method = Matrix (), + const std::string& get_access = "public", + const octave_value& set_method = Matrix (), + const std::string& set_access = "public"); - OCTINTERP_API cdef_property - make_attribute (const cdef_class& cls, const std::string& name); + OCTINTERP_API cdef_property + make_attribute (const cdef_class& cls, const std::string& name); - OCTINTERP_API cdef_method - make_method (const cdef_class& cls, const std::string& name, - const octave_value& fcn, - const std::string& m_access = "public", - bool is_static = false); + OCTINTERP_API cdef_method + make_method (const cdef_class& cls, const std::string& name, + const octave_value& fcn, + const std::string& m_access = "public", + bool is_static = false); - OCTINTERP_API cdef_method - make_method (const cdef_class& cls, const std::string& name, - octave_builtin::fcn ff, - const std::string& m_access = "public", - bool is_static = false); + OCTINTERP_API cdef_method + make_method (const cdef_class& cls, const std::string& name, + octave_builtin::fcn ff, + const std::string& m_access = "public", + bool is_static = false); - OCTINTERP_API cdef_method - make_method (const cdef_class& cls, const std::string& name, - octave_builtin::meth mm, - const std::string& m_access = "public", - bool is_static = false); + OCTINTERP_API cdef_method + make_method (const cdef_class& cls, const std::string& name, + octave_builtin::meth mm, + const std::string& m_access = "public", + bool is_static = false); - OCTINTERP_API cdef_package - make_package (const std::string& nm, const std::string& parent = ""); + OCTINTERP_API cdef_package + make_package (const std::string& nm, const std::string& parent = ""); - OCTINTERP_API octave_value - find_method (const std::string& class_name, - const std::string& name) const; + OCTINTERP_API octave_value + find_method (const std::string& class_name, + const std::string& name) const; - private: +private: - interpreter& m_interpreter; + interpreter& m_interpreter; - // All registered/loaded classes - std::map m_all_classes; + // All registered/loaded classes + std::map m_all_classes; - // All registered/loaded packages - std::map m_all_packages; + // All registered/loaded packages + std::map m_all_packages; - cdef_class m_meta_class; - cdef_class m_meta_property; - cdef_class m_meta_method; - cdef_class m_meta_package; + cdef_class m_meta_class; + cdef_class m_meta_property; + cdef_class m_meta_method; + cdef_class m_meta_package; - cdef_package m_meta; - }; + cdef_package m_meta; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-method.cc --- a/libinterp/octave-value/cdef-method.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-method.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,185 +51,185 @@ OCTAVE_BEGIN_NAMESPACE(octave) - OCTAVE_NORETURN static - void - err_method_access (const std::string& from, const cdef_method& meth) - { - octave_value acc = meth.get ("Access"); - std::string acc_s; +OCTAVE_NORETURN static +void +err_method_access (const std::string& from, const cdef_method& meth) +{ + octave_value acc = meth.get ("Access"); + std::string acc_s; - if (acc.is_string ()) - acc_s = acc.string_value (); - else - acc_s = "class-restricted"; + if (acc.is_string ()) + acc_s = acc.string_value (); + else + acc_s = "class-restricted"; - error ("%s: method '%s' has %s access and cannot be run in this context", - from.c_str (), meth.get_name ().c_str (), acc_s.c_str ()); - } + error ("%s: method '%s' has %s access and cannot be run in this context", + from.c_str (), meth.get_name ().c_str (), acc_s.c_str ()); +} - void - cdef_method::cdef_method_rep::check_method (void) - { - if (is_external ()) - { - if (is_dummy_method (m_function)) - { - load_path& lp = __get_load_path__ (); +void +cdef_method::cdef_method_rep::check_method (void) +{ + if (is_external ()) + { + if (is_dummy_method (m_function)) + { + load_path& lp = __get_load_path__ (); - std::string name = get_name (); - std::string cls_name = m_dispatch_type; - std::string pack_name; + std::string name = get_name (); + std::string cls_name = m_dispatch_type; + std::string pack_name; - std::size_t pos = cls_name.rfind ('.'); + std::size_t pos = cls_name.rfind ('.'); - if (pos != std::string::npos) - { - pack_name = cls_name.substr (0, pos); - cls_name = cls_name.substr (pos + 1); - } + if (pos != std::string::npos) + { + pack_name = cls_name.substr (0, pos); + cls_name = cls_name.substr (pos + 1); + } - std::string dir_name; - std::string file_name = lp.find_method (cls_name, name, - dir_name, pack_name); + std::string dir_name; + std::string file_name = lp.find_method (cls_name, name, + dir_name, pack_name); - if (! file_name.empty ()) - { - octave_value ov_fcn - = load_fcn_from_file (file_name, dir_name, - m_dispatch_type, pack_name); + if (! file_name.empty ()) + { + octave_value ov_fcn + = load_fcn_from_file (file_name, dir_name, + m_dispatch_type, pack_name); - if (ov_fcn.is_defined ()) - { - m_function = ov_fcn; + if (ov_fcn.is_defined ()) + { + m_function = ov_fcn; - make_function_of_class (m_dispatch_type, m_function); - } - } - } - else - { - // FIXME: check out-of-date status - } + make_function_of_class (m_dispatch_type, m_function); + } + } + } + else + { + // FIXME: check out-of-date status + } - if (is_dummy_method (m_function)) - error ("no definition found for method '%s' of class '%s'", - get_name ().c_str (), m_dispatch_type.c_str ()); - } - } + if (is_dummy_method (m_function)) + error ("no definition found for method '%s' of class '%s'", + get_name ().c_str (), m_dispatch_type.c_str ()); + } +} - octave_value_list - cdef_method::cdef_method_rep::execute (const octave_value_list& args, - int nargout, bool do_check_access, - const std::string& who) - { - octave_value_list retval; +octave_value_list +cdef_method::cdef_method_rep::execute (const octave_value_list& args, + int nargout, bool do_check_access, + const std::string& who) +{ + octave_value_list retval; - if (do_check_access && ! check_access ()) - err_method_access (who, wrap ()); + if (do_check_access && ! check_access ()) + err_method_access (who, wrap ()); - if (get ("Abstract").bool_value ()) - error ("%s: cannot execute abstract method", - get ("Name").string_value ().c_str ()); + if (get ("Abstract").bool_value ()) + error ("%s: cannot execute abstract method", + get ("Name").string_value ().c_str ()); - check_method (); + check_method (); - if (m_function.is_defined ()) - retval = feval (m_function, args, nargout); + if (m_function.is_defined ()) + retval = feval (m_function, args, nargout); - return retval; - } + return retval; +} - octave_value_list - cdef_method::cdef_method_rep::execute (const cdef_object& obj, - const octave_value_list& args, - int nargout, bool do_check_access, - const std::string& who) - { - octave_value_list retval; +octave_value_list +cdef_method::cdef_method_rep::execute (const cdef_object& obj, + const octave_value_list& args, + int nargout, bool do_check_access, + const std::string& who) +{ + octave_value_list retval; - if (do_check_access && ! check_access ()) - err_method_access (who, wrap ()); + if (do_check_access && ! check_access ()) + err_method_access (who, wrap ()); - if (get ("Abstract").bool_value ()) - error ("%s: cannot execute abstract method", - get ("Name").string_value ().c_str ()); + if (get ("Abstract").bool_value ()) + error ("%s: cannot execute abstract method", + get ("Name").string_value ().c_str ()); - check_method (); + check_method (); - if (m_function.is_defined ()) - { - octave_value_list new_args; + if (m_function.is_defined ()) + { + octave_value_list new_args; - new_args.resize (args.length () + 1); + new_args.resize (args.length () + 1); - new_args(0) = to_ov (obj); - for (int i = 0; i < args.length (); i++) - new_args(i+1) = args(i); + new_args(0) = to_ov (obj); + for (int i = 0; i < args.length (); i++) + new_args(i+1) = args(i); - retval = feval (m_function, new_args, nargout); - } + retval = feval (m_function, new_args, nargout); + } - return retval; - } + return retval; +} - bool - cdef_method::cdef_method_rep::is_constructor (void) const - { - if (m_function.is_function()) - return m_function.function_value ()->is_classdef_constructor (); +bool +cdef_method::cdef_method_rep::is_constructor (void) const +{ + if (m_function.is_function()) + return m_function.function_value ()->is_classdef_constructor (); - return false; - } + return false; +} - bool - cdef_method::cdef_method_rep::is_defined_in_class (const std::string& cname) const - { - return (m_function.is_function () - ? m_function.function_value ()->dispatch_class () == cname - : false); - } +bool +cdef_method::cdef_method_rep::is_defined_in_class (const std::string& cname) const +{ + return (m_function.is_function () + ? m_function.function_value ()->dispatch_class () == cname + : false); +} - std::string - cdef_method::cdef_method_rep::get_doc_string (void) - { - check_method (); +std::string +cdef_method::cdef_method_rep::get_doc_string (void) +{ + check_method (); - octave_function *fcn = m_function.function_value (); + octave_function *fcn = m_function.function_value (); - return fcn ? fcn->doc_string () : ""; - } + return fcn ? fcn->doc_string () : ""; +} - bool - cdef_method::cdef_method_rep::check_access (void) const - { - cdef_class cls (to_cdef (get ("DefiningClass"))); +bool +cdef_method::cdef_method_rep::check_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); - return octave::check_access (cls, get ("Access"), get_name ()); - } + return octave::check_access (cls, get ("Access"), get_name ()); +} - octave_value_list - cdef_method::cdef_method_rep::meta_subsref - (const std::string& type, const std::list& idx, - int nargout) - { - octave_value_list retval; +octave_value_list +cdef_method::cdef_method_rep::meta_subsref +(const std::string& type, const std::list& idx, + int nargout) +{ + octave_value_list retval; - switch (type[0]) - { - case '(': - retval = (execute (idx.front (), - type.length () > 1 ? 1 : nargout, true)); - break; + switch (type[0]) + { + case '(': + retval = (execute (idx.front (), + type.length () > 1 ? 1 : nargout, true)); + break; - default: - error ("invalid meta.method indexing"); - break; - } + default: + error ("invalid meta.method indexing"); + break; + } - if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) - retval = retval(0).next_subsref (nargout, type, idx, 1); + if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) + retval = retval(0).next_subsref (nargout, type, idx, 1); - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-method.h --- a/libinterp/octave-value/cdef-method.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-method.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,195 +39,195 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTINTERP_API - cdef_method : public cdef_meta_object - { - friend class cdef_class; - - private: - - class - cdef_method_rep : public cdef_meta_object_rep - { - public: - - cdef_method_rep (void) - : cdef_meta_object_rep (), m_function (), m_dispatch_type () - { } - - cdef_method_rep& operator = (const cdef_method_rep& m) = delete; - - ~cdef_method_rep (void) = default; - - cdef_object_rep * copy (void) const { return new cdef_method_rep(*this); } - - bool is_method (void) const { return true; } - - std::string get_name (void) const { return get("Name").string_value (); } - - void set_name (const std::string& nm) { put ("Name", nm); } - - bool is_static (void) const { return get("Static").bool_value (); } - - octave_value get_function (void) const { return m_function; } - - void set_function (const octave_value& fcn) { m_function = fcn; } - - OCTINTERP_API std::string get_doc_string (void); - - OCTINTERP_API bool check_access (void) const; - - bool is_external (void) const { return ! m_dispatch_type.empty (); } - - void mark_as_external (const std::string& dtype) - { - m_dispatch_type = dtype; - } +class +OCTINTERP_API +cdef_method : public cdef_meta_object +{ + friend class cdef_class; - OCTINTERP_API octave_value_list - execute (const octave_value_list& args, int nargout, - bool do_check_access = true, const std::string& who = ""); - - OCTINTERP_API octave_value_list - execute (const cdef_object& obj, - const octave_value_list& args, int nargout, - bool do_check_access = true, const std::string& who = ""); - - OCTINTERP_API bool is_constructor (void) const; - - OCTINTERP_API bool is_defined_in_class (const std::string& cname) const; - - octave_value_list - meta_subsref (const std::string& type, - const std::list& idx, int nargout); - - bool meta_accepts_postfix_index (char type) const - { - return (type == '(' || type == '.'); - } +private: - private: - - cdef_method_rep (const cdef_method_rep& m) - : cdef_meta_object_rep (m), m_function (m.m_function), - m_dispatch_type (m.m_dispatch_type) - { } - - OCTINTERP_API void check_method (void); - - cdef_method wrap (void) - { - m_count++; - return cdef_method (this); - } - - octave_value m_function; - - // When non-empty, the method is externally defined and this member - // is used to cache the dispatch type to look for the method. - - std::string m_dispatch_type; - }; - + class + cdef_method_rep : public cdef_meta_object_rep + { public: - cdef_method (void) : cdef_meta_object () { } + cdef_method_rep (void) + : cdef_meta_object_rep (), m_function (), m_dispatch_type () + { } - cdef_method (const std::string& nm) - : cdef_meta_object (new cdef_method_rep ()) - { - get_rep ()->set_name (nm); - } - - cdef_method (const cdef_method& meth) : cdef_meta_object (meth) { } + cdef_method_rep& operator = (const cdef_method_rep& m) = delete; - cdef_method (const cdef_object& obj) - : cdef_meta_object (obj) - { - // This should never happen... - if (! is_method ()) - error ("internal error: invalid assignment from %s to meta.method object", - class_name ().c_str ()); - } + ~cdef_method_rep (void) = default; - cdef_method& operator = (const cdef_method& meth) - { - cdef_object::operator = (meth); + cdef_object_rep * copy (void) const { return new cdef_method_rep(*this); } - return *this; - } - - ~cdef_method (void) = default; + bool is_method (void) const { return true; } - // normal invocation - octave_value_list execute (const octave_value_list& args, int nargout, - bool do_check_access = true, - const std::string& who = "") - { - return get_rep ()->execute (args, nargout, do_check_access, who); - } + std::string get_name (void) const { return get("Name").string_value (); } - // dot-invocation: object is pushed as 1st argument - octave_value_list execute (const cdef_object& obj, - const octave_value_list& args, int nargout, - bool do_check_access = true, - const std::string& who = "") - { - return get_rep ()->execute (obj, args, nargout, do_check_access, who); - } + void set_name (const std::string& nm) { put ("Name", nm); } - bool check_access (void) const { return get_rep ()->check_access (); } - - std::string get_name (void) const { return get_rep ()->get_name (); } + bool is_static (void) const { return get("Static").bool_value (); } - bool is_static (void) const { return get_rep ()->is_static (); } - - void set_function (const octave_value& fcn) - { - get_rep ()->set_function (fcn); - } + octave_value get_function (void) const { return m_function; } - octave_value get_function (void) const - { - return get_rep ()->get_function (); - } + void set_function (const octave_value& fcn) { m_function = fcn; } - std::string get_doc_string (void) - { - return get_rep ()->get_doc_string (); - } + OCTINTERP_API std::string get_doc_string (void); - bool is_constructor (void) const - { - return get_rep ()->is_constructor (); - } + OCTINTERP_API bool check_access (void) const; - bool is_defined_in_class (const std::string& cname) const - { - return get_rep ()->is_defined_in_class (cname); - } - - bool is_external (void) const { return get_rep ()->is_external (); } + bool is_external (void) const { return ! m_dispatch_type.empty (); } void mark_as_external (const std::string& dtype) { - get_rep ()->mark_as_external (dtype); + m_dispatch_type = dtype; + } + + OCTINTERP_API octave_value_list + execute (const octave_value_list& args, int nargout, + bool do_check_access = true, const std::string& who = ""); + + OCTINTERP_API octave_value_list + execute (const cdef_object& obj, + const octave_value_list& args, int nargout, + bool do_check_access = true, const std::string& who = ""); + + OCTINTERP_API bool is_constructor (void) const; + + OCTINTERP_API bool is_defined_in_class (const std::string& cname) const; + + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + bool meta_accepts_postfix_index (char type) const + { + return (type == '(' || type == '.'); } private: - cdef_method_rep * get_rep (void) + cdef_method_rep (const cdef_method_rep& m) + : cdef_meta_object_rep (m), m_function (m.m_function), + m_dispatch_type (m.m_dispatch_type) + { } + + OCTINTERP_API void check_method (void); + + cdef_method wrap (void) { - return dynamic_cast (cdef_object::get_rep ()); + m_count++; + return cdef_method (this); } - const cdef_method_rep * get_rep (void) const - { - return dynamic_cast (cdef_object::get_rep ()); - } + octave_value m_function; + + // When non-empty, the method is externally defined and this member + // is used to cache the dispatch type to look for the method. + + std::string m_dispatch_type; }; +public: + + cdef_method (void) : cdef_meta_object () { } + + cdef_method (const std::string& nm) + : cdef_meta_object (new cdef_method_rep ()) + { + get_rep ()->set_name (nm); + } + + cdef_method (const cdef_method& meth) : cdef_meta_object (meth) { } + + cdef_method (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_method ()) + error ("internal error: invalid assignment from %s to meta.method object", + class_name ().c_str ()); + } + + cdef_method& operator = (const cdef_method& meth) + { + cdef_object::operator = (meth); + + return *this; + } + + ~cdef_method (void) = default; + + // normal invocation + octave_value_list execute (const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = "") + { + return get_rep ()->execute (args, nargout, do_check_access, who); + } + + // dot-invocation: object is pushed as 1st argument + octave_value_list execute (const cdef_object& obj, + const octave_value_list& args, int nargout, + bool do_check_access = true, + const std::string& who = "") + { + return get_rep ()->execute (obj, args, nargout, do_check_access, who); + } + + bool check_access (void) const { return get_rep ()->check_access (); } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_static (void) const { return get_rep ()->is_static (); } + + void set_function (const octave_value& fcn) + { + get_rep ()->set_function (fcn); + } + + octave_value get_function (void) const + { + return get_rep ()->get_function (); + } + + std::string get_doc_string (void) + { + return get_rep ()->get_doc_string (); + } + + bool is_constructor (void) const + { + return get_rep ()->is_constructor (); + } + + bool is_defined_in_class (const std::string& cname) const + { + return get_rep ()->is_defined_in_class (cname); + } + + bool is_external (void) const { return get_rep ()->is_external (); } + + void mark_as_external (const std::string& dtype) + { + get_rep ()->mark_as_external (dtype); + } + +private: + + cdef_method_rep * get_rep (void) + { + return dynamic_cast (cdef_object::get_rep ()); + } + + const cdef_method_rep * get_rep (void) const + { + return dynamic_cast (cdef_object::get_rep ()); + } +}; + OCTAVE_END_NAMESPACE(octave) #endif diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-object.cc --- a/libinterp/octave-value/cdef-object.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-object.cc Thu Dec 01 20:05:44 2022 -0800 @@ -40,201 +40,298 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - cdef_object_rep::release (const cdef_object& obj) - { - // We need to be careful to keep a reference to the object if we are - // calling the delete method. The object is passed to the delete - // method as an argument and if the count is already zero when we - // do that, then we will increment the count while creating the - // argument list for the delete method and then it will be decremented - // back to zero and we'll find ourselves in an infinite loop. +void +cdef_object_rep::release (const cdef_object& obj) +{ + // We need to be careful to keep a reference to the object if we are + // calling the delete method. The object is passed to the delete + // method as an argument and if the count is already zero when we + // do that, then we will increment the count while creating the + // argument list for the delete method and then it will be decremented + // back to zero and we'll find ourselves in an infinite loop. + + if (m_count - 1 > static_count ()) + { + --m_count; + return; + } + + if (is_handle_object () && ! is_meta_object ()) + { + unwind_protect frame; + + // Clear interrupts. + frame.protect_var (octave_interrupt_state); + octave_interrupt_state = 0; + + // Disallow quit(). + frame.protect_var (quit_allowed); + quit_allowed = false; + + interpreter& interp = __get_interpreter__ (); + + interpreter_try (frame); + + try + { + // Call classdef "delete()" method on object + get_class ().delete_object (obj); + } + catch (const interrupt_exception&) + { + interp.recover_from_exception (); + + warning ("interrupt occurred in handle class delete method"); + } + catch (const execution_exception& ee) + { + interp.recover_from_exception (); + + std::string msg = ee.message (); - if (m_count - 1 > static_count ()) - { - --m_count; - return; - } + warning ("error caught while executing handle class delete method:\n%s\n", + msg.c_str ()); + } + catch (const exit_exception&) + { + // This shouldn't happen since we disabled quit above. + warning ("exit disabled while executing handle class delete method"); + } + catch (...) // Yes, the black hole. We're in a d-tor. + { + // This shouldn't happen, in theory. + warning ("internal error: unhandled exception in handle class delete method"); + } + } - if (is_handle_object () && ! is_meta_object ()) - { - unwind_protect frame; + // Now it is safe to set the count to zero. + m_count--; + + destroy (); +} + +cdef_class +cdef_object_rep::get_class (void) const +{ + err_invalid_object ("get_class"); +} - // Clear interrupts. - frame.protect_var (octave_interrupt_state); - octave_interrupt_state = 0; +std::string +cdef_object_rep::class_name (void) const +{ + return get_class ().get_name (); +} + +string_vector +cdef_object_rep::map_keys (void) const +{ + cdef_class cls = get_class (); + + if (cls.ok ()) + return cls.get_names (); + + return string_vector (); +} - // Disallow quit(). - frame.protect_var (quit_allowed); - quit_allowed = false; +octave_map +cdef_object::map_value (void) const +{ + octave_map retval; - interpreter& interp = __get_interpreter__ (); + warning_with_id ("Octave:classdef-to-struct", + "struct: converting a classdef object into a struct " + "overrides the access restrictions defined for properties. " + "All properties are returned, including private and " + "protected ones."); + + cdef_class cls = get_class (); + + if (cls.ok ()) + { + std::map props; + + props = cls.get_property_map (cdef_class::property_all); - interpreter_try (frame); + // FIXME: Why not const here? + for (auto& prop_val : props) + { + if (is_array ()) + { + Array a_obj = array_value (); + + Cell cvalue (a_obj.dims ()); + + for (octave_idx_type i = 0; i < a_obj.numel (); i++) + cvalue (i) = prop_val.second.get_value (a_obj(i), false); + + retval.setfield (prop_val.first, cvalue); + } + else + { + Cell cvalue (dim_vector (1, 1), + prop_val.second.get_value (*this, false)); + + retval.setfield (prop_val.first, cvalue); + } + } + } + + return retval; +} + +cdef_class +cdef_object::get_class (void) const +{ + return m_rep->get_class (); +} + +cdef_class +cdef_object_base::get_class (void) const +{ + return cdef_class (m_klass); +} - try - { - // Call classdef "delete()" method on object - get_class ().delete_object (obj); - } - catch (const interrupt_exception&) - { - interp.recover_from_exception (); +void +cdef_object_base::set_class (const cdef_class& cls) +{ + if ((m_klass.ok () && cls.ok () && cls != get_class ()) + || (m_klass.ok () && ! cls.ok ()) + || (! m_klass.ok () && cls.ok ())) + { + m_klass = cls; + } +} + +cdef_object_rep * +cdef_object_base::make_array (void) const +{ + cdef_object_rep *r = new cdef_object_array (); + + r->set_class (get_class ()); - warning ("interrupt occurred in handle class delete method"); - } - catch (const execution_exception& ee) + return r; +} + +octave_value_list +cdef_object_array::subsref (const std::string& type, + const std::list& idx, + int /* nargout */, std::size_t& skip, + const cdef_class& /* context */, bool auto_add) +{ + octave_value_list retval; + + skip = 1; + + switch (type[0]) + { + case '(': + { + const octave_value_list& ival = idx.front (); + + if (ival.empty ()) { - interp.recover_from_exception (); - - std::string msg = ee.message (); - - warning ("error caught while executing handle class delete method:\n%s\n", - msg.c_str ()); + m_count++; + retval(0) = to_ov (cdef_object (this)); + break; } - catch (const exit_exception&) + + bool is_scalar = true; + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; i < ival.length (); i++) { - // This shouldn't happen since we disabled quit above. - warning ("exit disabled while executing handle class delete method"); + try + { + iv(i) = ival(i).index_vector (); + } + catch (index_exception& ie) + { + // Rethrow to allow more info to be reported later. + ie.set_pos_if_unset (ival.length (), i+1); + throw; + } + + is_scalar = is_scalar && iv(i).is_scalar (); } - catch (...) // Yes, the black hole. We're in a d-tor. + + Array ires = m_array.index (iv, auto_add); + + // If resizing is enabled (auto_add = true), it's possible + // indexing was out-of-bound and the result array contains + // invalid cdef_objects. + + if (auto_add) + fill_empty_values (ires); + + if (is_scalar) + retval(0) = to_ov (ires(0)); + else { - // This shouldn't happen, in theory. - warning ("internal error: unhandled exception in handle class delete method"); + cdef_object array_obj (new cdef_object_array (ires)); + + array_obj.set_class (get_class ()); + + retval(0) = to_ov (array_obj); } } - - // Now it is safe to set the count to zero. - m_count--; - - destroy (); - } - - cdef_class - cdef_object_rep::get_class (void) const - { - err_invalid_object ("get_class"); - } - - std::string - cdef_object_rep::class_name (void) const - { - return get_class ().get_name (); - } - - string_vector - cdef_object_rep::map_keys (void) const - { - cdef_class cls = get_class (); - - if (cls.ok ()) - return cls.get_names (); - - return string_vector (); - } + break; - octave_map - cdef_object::map_value (void) const - { - octave_map retval; - - warning_with_id ("Octave:classdef-to-struct", - "struct: converting a classdef object into a struct " - "overrides the access restrictions defined for properties. " - "All properties are returned, including private and " - "protected ones."); - - cdef_class cls = get_class (); + case '.': + if (type.size () == 1 && idx.size () == 1) + { + Cell c (dims ()); - if (cls.ok ()) - { - std::map props; - - props = cls.get_property_map (cdef_class::property_all); - - // FIXME: Why not const here? - for (auto& prop_val : props) - { - if (is_array ()) - { - Array a_obj = array_value (); - - Cell cvalue (a_obj.dims ()); - - for (octave_idx_type i = 0; i < a_obj.numel (); i++) - cvalue (i) = prop_val.second.get_value (a_obj(i), false); + octave_idx_type n = m_array.numel (); - retval.setfield (prop_val.first, cvalue); - } - else - { - Cell cvalue (dim_vector (1, 1), - prop_val.second.get_value (*this, false)); - - retval.setfield (prop_val.first, cvalue); - } - } - } - - return retval; - } - - cdef_class - cdef_object::get_class (void) const - { - return m_rep->get_class (); - } - - cdef_class - cdef_object_base::get_class (void) const - { - return cdef_class (m_klass); - } + // dummy variables + std::size_t dummy_skip; + cdef_class dummy_cls; - void - cdef_object_base::set_class (const cdef_class& cls) - { - if ((m_klass.ok () && cls.ok () && cls != get_class ()) - || (m_klass.ok () && ! cls.ok ()) - || (! m_klass.ok () && cls.ok ())) - { - m_klass = cls; - } - } - - cdef_object_rep * - cdef_object_base::make_array (void) const - { - cdef_object_rep *r = new cdef_object_array (); - - r->set_class (get_class ()); - - return r; - } + for (octave_idx_type i = 0; i < n; i++) + { + octave_value_list r = m_array(i).subsref (type, idx, 1, + dummy_skip, + dummy_cls); - octave_value_list - cdef_object_array::subsref (const std::string& type, - const std::list& idx, - int /* nargout */, std::size_t& skip, - const cdef_class& /* context */, bool auto_add) - { - octave_value_list retval; - - skip = 1; - - switch (type[0]) - { - case '(': - { - const octave_value_list& ival = idx.front (); - - if (ival.empty ()) - { - m_count++; - retval(0) = to_ov (cdef_object (this)); - break; + if (r.length () > 0) + c(i) = r(0); } + retval(0) = octave_value (c, true); + + break; + } + OCTAVE_FALLTHROUGH; + + default: + error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } + + return retval; +} + +octave_value +cdef_object_array::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + switch (type[0]) + { + case '(': + if (type.length () == 1) + { + cdef_object rhs_obj = to_cdef (rhs); + + if (rhs_obj.get_class () != get_class ()) + error ("can't assign %s object into array of %s objects", + rhs_obj.class_name ().c_str (), + class_name ().c_str ()); + + const octave_value_list& ival = idx.front (); bool is_scalar = true; Array iv (dim_vector (1, ival.length ())); @@ -246,509 +343,412 @@ } catch (index_exception& ie) { + ie.set_pos_if_unset (ival.length (), i+1); + throw; // var name set in pt-idx.cc / pt-assign.cc + } + + is_scalar = is_scalar && iv(i).is_scalar (); + } + + Array rhs_mat; + + if (! rhs_obj.is_array ()) + { + rhs_mat = Array (dim_vector (1, 1)); + rhs_mat(0) = rhs_obj; + } + else + rhs_mat = rhs_obj.array_value (); + + octave_idx_type n = m_array.numel (); + + m_array.assign (iv, rhs_mat, cdef_object ()); + + if (m_array.numel () > n) + fill_empty_values (); + + m_count++; + retval = to_ov (cdef_object (this)); + } + else + { + const octave_value_list& ivl = idx.front (); + + // Fill in trailing singleton dimensions so that + // array.index doesn't create a new blank entry (bug #46660). + const octave_idx_type one = static_cast (1); + const octave_value_list& ival = ivl.length () >= 2 + ? ivl : ((m_array.dims ()(0) == 1) + ? ovl (one, ivl(0)) + : ovl (ivl(0), one)); + + bool is_scalar = true; + + Array iv (dim_vector (1, ival.length ())); + + for (int i = 0; i < ival.length (); i++) + { + try + { + iv(i) = ival(i).index_vector (); + } + catch (index_exception& ie) + { // Rethrow to allow more info to be reported later. ie.set_pos_if_unset (ival.length (), i+1); throw; } is_scalar = is_scalar && iv(i).is_scalar (); + + if (! is_scalar) + error ("subsasgn: invalid indexing for object array assignment" + ", the index must reference a single object in the " + "array."); + } + + Array a = m_array.index (iv, true); + + if (a.numel () != 1) + error ("subsasgn: invalid indexing for object array assignment"); + + cdef_object obj = a(0); + + int ignore_copies = 0; + + // If the object in 'a' is not valid, this means the index + // was out-of-bound and we need to create a new object. + + if (! obj.ok ()) + obj = get_class ().construct_object (octave_value_list ()); + else + // Optimize the subsasgn call to come. There are 2 copies + // that we can safely ignore: + // - 1 in "array" + // - 1 in "a" + ignore_copies = 2; + + std::list next_idx (idx); + + next_idx.erase (next_idx.begin ()); + + octave_value tmp = obj.subsasgn (type.substr (1), next_idx, + rhs, ignore_copies); + + cdef_object robj = to_cdef (tmp); + + if (! robj.ok () + || robj.is_array () + || robj.get_class () != get_class ()) + error ("subsasgn: invalid assignment into array of %s objects", + class_name ().c_str ()); + + // Small optimization, when dealing with handle + // objects, we don't need to re-assign the result + // of subsasgn back into the array. + + if (! robj.is (a(0))) + { + Array rhs_a (dim_vector (1, 1), + robj); + + octave_idx_type n = m_array.numel (); + + m_array.assign (iv, rhs_a); + + if (m_array.numel () > n) + fill_empty_values (); } - Array ires = m_array.index (iv, auto_add); + m_count++; - // If resizing is enabled (auto_add = true), it's possible - // indexing was out-of-bound and the result array contains - // invalid cdef_objects. - - if (auto_add) - fill_empty_values (ires); + retval = to_ov (cdef_object (this)); + } + break; - if (is_scalar) - retval(0) = to_ov (ires(0)); - else - { - cdef_object array_obj (new cdef_object_array (ires)); + default: + error ("can't perform indexing operation on array of %s objects", + class_name ().c_str ()); + break; + } - array_obj.set_class (get_class ()); + return retval; +} - retval(0) = to_ov (array_obj); - } - } - break; +void +cdef_object_array::fill_empty_values (Array& arr) +{ + cdef_class cls = get_class (); - case '.': - if (type.size () == 1 && idx.size () == 1) - { - Cell c (dims ()); + cdef_object obj; - octave_idx_type n = m_array.numel (); - - // dummy variables - std::size_t dummy_skip; - cdef_class dummy_cls; + int n = arr.numel (); - for (octave_idx_type i = 0; i < n; i++) - { - octave_value_list r = m_array(i).subsref (type, idx, 1, - dummy_skip, - dummy_cls); + for (int i = 0; i < n; i++) + { + if (! arr.xelem (i).ok ()) + { + if (! obj.ok ()) + { + obj = cls.construct_object (octave_value_list ()); - if (r.length () > 0) - c(i) = r(0); - } - - retval(0) = octave_value (c, true); + arr.xelem (i) = obj; + } + else + arr.xelem (i) = obj.copy (); + } + } +} - break; - } - OCTAVE_FALLTHROUGH; +void +cdef_object_scalar::break_closure_cycles (const std::shared_ptr& frame) +{ + for (octave_idx_type i = 0; i < m_map.nfields (); i++) + m_map.contents(i).break_closure_cycles (frame); +} - default: - error ("can't perform indexing operation on array of %s objects", - class_name ().c_str ()); - break; - } +octave_value_list +cdef_object_scalar::subsref (const std::string& type, + const std::list& idx, + int nargout, std::size_t& skip, + const cdef_class& context, bool auto_add) +{ + skip = 0; + cdef_class cls = (context.ok () ? context : get_class ()); + + octave_value_list retval; + + if (! cls.ok ()) return retval; - } - octave_value - cdef_object_array::subsasgn (const std::string& type, - const std::list& idx, - const octave_value& rhs) - { - octave_value retval; + switch (type[0]) + { + case '.': + { + std::string name = (idx.front ())(0).string_value (); - switch (type[0]) - { - case '(': - if (type.length () == 1) + cdef_method meth = cls.find_method (name); + + if (meth.ok ()) { - cdef_object rhs_obj = to_cdef (rhs); + int _nargout = (type.length () > 2 ? 1 : nargout); - if (rhs_obj.get_class () != get_class ()) - error ("can't assign %s object into array of %s objects", - rhs_obj.class_name ().c_str (), - class_name ().c_str ()); + octave_value_list args; - const octave_value_list& ival = idx.front (); - bool is_scalar = true; - Array iv (dim_vector (1, ival.length ())); + skip = 1; - for (int i = 0; i < ival.length (); i++) + if (type.length () > 1 && type[1] == '(') { - try - { - iv(i) = ival(i).index_vector (); - } - catch (index_exception& ie) - { - ie.set_pos_if_unset (ival.length (), i+1); - throw; // var name set in pt-idx.cc / pt-assign.cc - } + auto it = idx.begin (); - is_scalar = is_scalar && iv(i).is_scalar (); + args = *++it; + + skip++; } - Array rhs_mat; - - if (! rhs_obj.is_array ()) - { - rhs_mat = Array (dim_vector (1, 1)); - rhs_mat(0) = rhs_obj; - } + if (meth.is_static ()) + retval = meth.execute (args, _nargout, true, "subsref"); else - rhs_mat = rhs_obj.array_value (); - - octave_idx_type n = m_array.numel (); - - m_array.assign (iv, rhs_mat, cdef_object ()); - - if (m_array.numel () > n) - fill_empty_values (); - - m_count++; - retval = to_ov (cdef_object (this)); + { + m_count++; + retval = meth.execute (cdef_object (this), args, _nargout, + true, "subsref"); + } } - else - { - const octave_value_list& ivl = idx.front (); - // Fill in trailing singleton dimensions so that - // array.index doesn't create a new blank entry (bug #46660). - const octave_idx_type one = static_cast (1); - const octave_value_list& ival = ivl.length () >= 2 - ? ivl : ((m_array.dims ()(0) == 1) - ? ovl (one, ivl(0)) - : ovl (ivl(0), one)); + if (skip == 0) + { + cdef_property prop = cls.find_property (name); - bool is_scalar = true; + if (! prop.ok ()) + error ("subsref: unknown method or property: %s", name.c_str ()); - Array iv (dim_vector (1, ival.length ())); - - for (int i = 0; i < ival.length (); i++) + if (prop.is_constant ()) + retval(0) = prop.get_value (true, "subsref"); + else { - try - { - iv(i) = ival(i).index_vector (); - } - catch (index_exception& ie) - { - // Rethrow to allow more info to be reported later. - ie.set_pos_if_unset (ival.length (), i+1); - throw; - } - - is_scalar = is_scalar && iv(i).is_scalar (); - - if (! is_scalar) - error ("subsasgn: invalid indexing for object array assignment" - ", the index must reference a single object in the " - "array."); + m_count++; + retval(0) = prop.get_value (cdef_object (this), + true, "subsref"); } - Array a = m_array.index (iv, true); - - if (a.numel () != 1) - error ("subsasgn: invalid indexing for object array assignment"); - - cdef_object obj = a(0); - - int ignore_copies = 0; - - // If the object in 'a' is not valid, this means the index - // was out-of-bound and we need to create a new object. - - if (! obj.ok ()) - obj = get_class ().construct_object (octave_value_list ()); - else - // Optimize the subsasgn call to come. There are 2 copies - // that we can safely ignore: - // - 1 in "array" - // - 1 in "a" - ignore_copies = 2; - - std::list next_idx (idx); - - next_idx.erase (next_idx.begin ()); - - octave_value tmp = obj.subsasgn (type.substr (1), next_idx, - rhs, ignore_copies); - - cdef_object robj = to_cdef (tmp); - - if (! robj.ok () - || robj.is_array () - || robj.get_class () != get_class ()) - error ("subsasgn: invalid assignment into array of %s objects", - class_name ().c_str ()); - - // Small optimization, when dealing with handle - // objects, we don't need to re-assign the result - // of subsasgn back into the array. - - if (! robj.is (a(0))) - { - Array rhs_a (dim_vector (1, 1), - robj); - - octave_idx_type n = m_array.numel (); - - m_array.assign (iv, rhs_a); - - if (m_array.numel () > n) - fill_empty_values (); - } - - m_count++; - - retval = to_ov (cdef_object (this)); + skip = 1; } break; - - default: - error ("can't perform indexing operation on array of %s objects", - class_name ().c_str ()); - break; } - return retval; - } + case '(': + { + const octave_value_list& ival = idx.front (); + + m_count++; + cdef_object this_obj (this); + + if (ival.empty ()) + { + skip++; + retval(0) = to_ov (this_obj); + } + else + { + Array arr (dim_vector (1, 1), this_obj); + + cdef_object new_obj = cdef_object (new cdef_object_array (arr)); + + new_obj.set_class (get_class ()); - void - cdef_object_array::fill_empty_values (Array& arr) - { - cdef_class cls = get_class (); + retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add); + } + } + break; + + default: + error ("object cannot be indexed with '%c'", type[0]); + break; + } - cdef_object obj; + return retval; +} - int n = arr.numel (); +octave_value +cdef_object_scalar::subsasgn (const std::string& type, + const std::list& idx, + const octave_value& rhs) +{ + octave_value retval; + + cdef_class cls = get_class (); - for (int i = 0; i < n; i++) + switch (type[0]) + { + case '.': { - if (! arr.xelem (i).ok ()) + std::string name = (idx.front ())(0).string_value (); + + cdef_property prop = cls.find_property (name); + + if (! prop.ok ()) + error ("subsasgn: unknown property: %s", name.c_str ()); + + if (prop.is_constant ()) + error ("subsasgn: cannot assign constant property: %s", + name.c_str ()); + + m_count++; + + cdef_object obj (this); + + if (type.length () == 1) { - if (! obj.ok ()) - { - obj = cls.construct_object (octave_value_list ()); + prop.set_value (obj, rhs, true, "subsasgn"); + + retval = to_ov (obj); + } + else + { + octave_value val = prop.get_value (obj, true, "subsasgn"); + + std::list args (idx); - arr.xelem (i) = obj; - } - else - arr.xelem (i) = obj.copy (); + args.erase (args.begin ()); + + val = val.assign (octave_value::op_asn_eq, + type.substr (1), args, rhs); + + if (val.class_name () != "object" + || ! to_cdef (val).is_handle_object ()) + prop.set_value (obj, val, true, "subsasgn"); + + retval = to_ov (obj); } } - } - - void - cdef_object_scalar::break_closure_cycles (const std::shared_ptr& frame) - { - for (octave_idx_type i = 0; i < m_map.nfields (); i++) - m_map.contents(i).break_closure_cycles (frame); - } + break; - octave_value_list - cdef_object_scalar::subsref (const std::string& type, - const std::list& idx, - int nargout, std::size_t& skip, - const cdef_class& context, bool auto_add) - { - skip = 0; - - cdef_class cls = (context.ok () ? context : get_class ()); - - octave_value_list retval; - - if (! cls.ok ()) - return retval; + case '(': + { + m_count++; - switch (type[0]) - { - case '.': - { - std::string name = (idx.front ())(0).string_value (); - - cdef_method meth = cls.find_method (name); - - if (meth.ok ()) - { - int _nargout = (type.length () > 2 ? 1 : nargout); + cdef_object this_obj (this); - octave_value_list args; - - skip = 1; + Array arr (dim_vector (1, 1), this_obj); - if (type.length () > 1 && type[1] == '(') - { - auto it = idx.begin (); - - args = *++it; - - skip++; - } + cdef_object new_obj = cdef_object (new cdef_object_array (arr)); - if (meth.is_static ()) - retval = meth.execute (args, _nargout, true, "subsref"); - else - { - m_count++; - retval = meth.execute (cdef_object (this), args, _nargout, - true, "subsref"); - } - } + new_obj.set_class (get_class ()); - if (skip == 0) - { - cdef_property prop = cls.find_property (name); - - if (! prop.ok ()) - error ("subsref: unknown method or property: %s", name.c_str ()); - - if (prop.is_constant ()) - retval(0) = prop.get_value (true, "subsref"); - else - { - m_count++; - retval(0) = prop.get_value (cdef_object (this), - true, "subsref"); - } + octave_value tmp = new_obj.subsasgn (type, idx, rhs); - skip = 1; - } - break; - } - - case '(': - { - const octave_value_list& ival = idx.front (); - - m_count++; - cdef_object this_obj (this); + retval = tmp; + } + break; - if (ival.empty ()) - { - skip++; - retval(0) = to_ov (this_obj); - } - else - { - Array arr (dim_vector (1, 1), this_obj); - - cdef_object new_obj = cdef_object (new cdef_object_array (arr)); - - new_obj.set_class (get_class ()); - - retval = new_obj.subsref (type, idx, nargout, skip, cls, auto_add); - } - } - break; - - default: - error ("object cannot be indexed with '%c'", type[0]); - break; - } + default: + error ("subsasgn: object cannot be index with '%c'", type[0]); + break; + } - return retval; - } - - octave_value - cdef_object_scalar::subsasgn (const std::string& type, - const std::list& idx, - const octave_value& rhs) - { - octave_value retval; - - cdef_class cls = get_class (); - - switch (type[0]) - { - case '.': - { - std::string name = (idx.front ())(0).string_value (); - - cdef_property prop = cls.find_property (name); - - if (! prop.ok ()) - error ("subsasgn: unknown property: %s", name.c_str ()); + return retval; +} - if (prop.is_constant ()) - error ("subsasgn: cannot assign constant property: %s", - name.c_str ()); - - m_count++; - - cdef_object obj (this); - - if (type.length () == 1) - { - prop.set_value (obj, rhs, true, "subsasgn"); +void +cdef_object_scalar::mark_for_construction (const cdef_class& cls) +{ + std::string cls_name = cls.get_name (); - retval = to_ov (obj); - } - else - { - octave_value val = prop.get_value (obj, true, "subsasgn"); - - std::list args (idx); + Cell supcls = cls.get ("SuperClasses").cell_value (); - args.erase (args.begin ()); + std::list supcls_list = lookup_classes (supcls); - val = val.assign (octave_value::op_asn_eq, - type.substr (1), args, rhs); - - if (val.class_name () != "object" - || ! to_cdef (val).is_handle_object ()) - prop.set_value (obj, val, true, "subsasgn"); + m_ctor_list[cls] = supcls_list; +} - retval = to_ov (obj); - } - } - break; - - case '(': - { - m_count++; - - cdef_object this_obj (this); - - Array arr (dim_vector (1, 1), this_obj); - - cdef_object new_obj = cdef_object (new cdef_object_array (arr)); - - new_obj.set_class (get_class ()); - - octave_value tmp = new_obj.subsasgn (type, idx, rhs); - - retval = tmp; - } - break; - - default: - error ("subsasgn: object cannot be index with '%c'", type[0]); - break; - } +bool +cdef_object_scalar::is_constructed_for (const cdef_class& cls) const +{ + return (is_constructed () + || m_ctor_list.find (cls) == m_ctor_list.end ()); +} - return retval; - } - - void - cdef_object_scalar::mark_for_construction (const cdef_class& cls) - { - std::string cls_name = cls.get_name (); - - Cell supcls = cls.get ("SuperClasses").cell_value (); - - std::list supcls_list = lookup_classes (supcls); - - m_ctor_list[cls] = supcls_list; - } +bool +cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const +{ + if (is_constructed ()) + return true; - bool - cdef_object_scalar::is_constructed_for (const cdef_class& cls) const - { - return (is_constructed () - || m_ctor_list.find (cls) == m_ctor_list.end ()); - } - - bool - cdef_object_scalar::is_partially_constructed_for (const cdef_class& cls) const - { - if (is_constructed ()) - return true; - - std::map>::const_iterator it + std::map>::const_iterator it = m_ctor_list.find (cls); - if (it == m_ctor_list.end () || it->second.empty ()) - return true; - - for (const auto& cdef_cls : it->second) - if (! is_partially_constructed_for (cdef_cls)) - return false; - + if (it == m_ctor_list.end () || it->second.empty ()) return true; - } + + for (const auto& cdef_cls : it->second) + if (! is_partially_constructed_for (cdef_cls)) + return false; - void - cdef_object_scalar::mark_as_constructed (const cdef_class& cls) - { - m_ctor_list.erase (cls); - } + return true; +} + +void +cdef_object_scalar::mark_as_constructed (const cdef_class& cls) +{ + m_ctor_list.erase (cls); +} - handle_cdef_object::~handle_cdef_object (void) - { +handle_cdef_object::~handle_cdef_object (void) +{ #if DEBUG_TRACE - std::cerr << "deleting " << get_class ().get_name () - << " object (handle)" << std::endl; + std::cerr << "deleting " << get_class ().get_name () + << " object (handle)" << std::endl; #endif - } +} - value_cdef_object::~value_cdef_object (void) - { +value_cdef_object::~value_cdef_object (void) +{ #if DEBUG_TRACE - std::cerr << "deleting " << get_class ().get_name () - << " object (value)" << std::endl; + std::cerr << "deleting " << get_class ().get_name () + << " object (value)" << std::endl; #endif - } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-object.h --- a/libinterp/octave-value/cdef-object.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-object.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,676 +41,676 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // This is mainly a bootstrap class to declare the expected interface. - // The actual base class is cdef_class_base, which is declared after - // cdef_object, such that it can contain cdef_object objects. +// This is mainly a bootstrap class to declare the expected interface. +// The actual base class is cdef_class_base, which is declared after +// cdef_object, such that it can contain cdef_object objects. - class - OCTINTERP_API - cdef_object_rep - { - public: +class +OCTINTERP_API +cdef_object_rep +{ +public: - friend class cdef_object; + friend class cdef_object; - cdef_object_rep (void) : m_count (1) { } + cdef_object_rep (void) : m_count (1) { } - cdef_object_rep& operator = (const cdef_object_rep&) = delete; + cdef_object_rep& operator = (const cdef_object_rep&) = delete; - virtual ~cdef_object_rep (void) = default; + virtual ~cdef_object_rep (void) = default; - virtual cdef_class get_class (void) const; + virtual cdef_class get_class (void) const; - virtual void set_class (const cdef_class&) - { - err_invalid_object ("set_class"); - } + virtual void set_class (const cdef_class&) + { + err_invalid_object ("set_class"); + } - virtual cdef_object_rep * clone (void) const - { - err_invalid_object ("clone"); - } + virtual cdef_object_rep * clone (void) const + { + err_invalid_object ("clone"); + } - virtual cdef_object_rep * empty_clone (void) const - { - err_invalid_object ("empty_clone"); - } + virtual cdef_object_rep * empty_clone (void) const + { + err_invalid_object ("empty_clone"); + } - virtual cdef_object_rep * copy (void) const - { - err_invalid_object ("copy"); - } + virtual cdef_object_rep * copy (void) const + { + err_invalid_object ("copy"); + } - virtual cdef_object_rep * make_array (void) const - { - err_invalid_object ("make_array"); - } + virtual cdef_object_rep * make_array (void) const + { + err_invalid_object ("make_array"); + } - virtual bool is_array (void) const { return false; } + virtual bool is_array (void) const { return false; } - virtual bool is_value_object (void) const { return false; } + virtual bool is_value_object (void) const { return false; } - virtual bool is_handle_object (void) const { return false; } + virtual bool is_handle_object (void) const { return false; } - virtual bool is_meta_object (void) const { return false; } + virtual bool is_meta_object (void) const { return false; } - virtual Array array_value (void) const - { - err_invalid_object ("array_value"); - } + virtual Array array_value (void) const + { + err_invalid_object ("array_value"); + } - virtual void put (const std::string&, const octave_value&) - { err_invalid_object ("put"); } + virtual void put (const std::string&, const octave_value&) + { err_invalid_object ("put"); } - virtual octave_value get (const std::string&) const - { - err_invalid_object ("get"); - } + virtual octave_value get (const std::string&) const + { + err_invalid_object ("get"); + } - virtual void set_property (octave_idx_type, const std::string&, - const octave_value&) - { - err_invalid_object ("set_property"); - } + virtual void set_property (octave_idx_type, const std::string&, + const octave_value&) + { + err_invalid_object ("set_property"); + } - virtual octave_value get_property (octave_idx_type, const std::string&) const - { - err_invalid_object ("get_property"); - } + virtual octave_value get_property (octave_idx_type, const std::string&) const + { + err_invalid_object ("get_property"); + } - virtual void break_closure_cycles (const std::shared_ptr&) - { - err_invalid_object ("break_closure_cycles"); - } + virtual void break_closure_cycles (const std::shared_ptr&) + { + err_invalid_object ("break_closure_cycles"); + } - virtual octave_value_list - subsref (const std::string&, const std::list&, - int, std::size_t&, const cdef_class&, bool) - { - err_invalid_object ("subsref"); - } + virtual octave_value_list + subsref (const std::string&, const std::list&, + int, std::size_t&, const cdef_class&, bool) + { + err_invalid_object ("subsref"); + } - virtual octave_value - subsasgn (const std::string&, const std::list&, - const octave_value&) - { - err_invalid_object ("subsasgn"); - } + virtual octave_value + subsasgn (const std::string&, const std::list&, + const octave_value&) + { + err_invalid_object ("subsasgn"); + } - virtual string_vector map_keys (void) const; + virtual string_vector map_keys (void) const; - virtual bool is_valid (void) const { return false; } + virtual bool is_valid (void) const { return false; } - OCTINTERP_API std::string class_name (void) const; + OCTINTERP_API std::string class_name (void) const; - virtual void mark_for_construction (const cdef_class&) - { - err_invalid_object ("mark_for_construction"); - } + virtual void mark_for_construction (const cdef_class&) + { + err_invalid_object ("mark_for_construction"); + } - virtual bool is_constructed_for (const cdef_class&) const - { - err_invalid_object ("is_constructed_for"); - } + virtual bool is_constructed_for (const cdef_class&) const + { + err_invalid_object ("is_constructed_for"); + } - virtual bool is_partially_constructed_for (const cdef_class&) const - { - err_invalid_object ("is_partially_constructed_for"); - } + virtual bool is_partially_constructed_for (const cdef_class&) const + { + err_invalid_object ("is_partially_constructed_for"); + } - virtual void mark_as_constructed (void) - { - err_invalid_object ("mark_as_constructed"); - } + virtual void mark_as_constructed (void) + { + err_invalid_object ("mark_as_constructed"); + } - virtual void mark_as_constructed (const cdef_class&) - { - err_invalid_object ("mark_as_constructed"); - } + virtual void mark_as_constructed (const cdef_class&) + { + err_invalid_object ("mark_as_constructed"); + } - virtual bool is_constructed (void) const - { - err_invalid_object ("is_constructed"); - } + virtual bool is_constructed (void) const + { + err_invalid_object ("is_constructed"); + } - virtual octave_idx_type static_count (void) const { return 0; } + virtual octave_idx_type static_count (void) const { return 0; } - virtual void destroy (void) { delete this; } + virtual void destroy (void) { delete this; } - OCTINTERP_API void release (const cdef_object& obj); + OCTINTERP_API void release (const cdef_object& obj); - virtual dim_vector dims (void) const { return dim_vector (); } + virtual dim_vector dims (void) const { return dim_vector (); } - protected: +protected: - // Reference count - refcount m_count; + // Reference count + refcount m_count; - // Restricted copying. + // Restricted copying. - cdef_object_rep (const cdef_object_rep&) : m_count (1) { } + cdef_object_rep (const cdef_object_rep&) : m_count (1) { } - private: +private: - OCTAVE_NORETURN void err_invalid_object (const char *who) const - { - error ("%s: invalid object", who); - } - }; + OCTAVE_NORETURN void err_invalid_object (const char *who) const + { + error ("%s: invalid object", who); + } +}; - class - OCTINTERP_API - cdef_object - { - public: +class +OCTINTERP_API +cdef_object +{ +public: - // FIXME: use a null object? - cdef_object (void) : m_rep (new cdef_object_rep ()) { } + // FIXME: use a null object? + cdef_object (void) : m_rep (new cdef_object_rep ()) { } - cdef_object (const cdef_object& obj) : m_rep (obj.m_rep) - { m_rep->m_count++; } + cdef_object (const cdef_object& obj) : m_rep (obj.m_rep) + { m_rep->m_count++; } - cdef_object (cdef_object_rep *r) : m_rep (r) { } + cdef_object (cdef_object_rep *r) : m_rep (r) { } - virtual ~cdef_object (void) { m_rep->release (*this); } + virtual ~cdef_object (void) { m_rep->release (*this); } - cdef_object& operator = (const cdef_object& obj) - { - if (m_rep != obj.m_rep) - { - m_rep->release (*this); + cdef_object& operator = (const cdef_object& obj) + { + if (m_rep != obj.m_rep) + { + m_rep->release (*this); - m_rep = obj.m_rep; - m_rep->m_count++; - } + m_rep = obj.m_rep; + m_rep->m_count++; + } - return *this; - } + return *this; + } - OCTINTERP_API cdef_class get_class (void) const; + OCTINTERP_API cdef_class get_class (void) const; - void set_class (const cdef_class& cls) { m_rep->set_class (cls); } + void set_class (const cdef_class& cls) { m_rep->set_class (cls); } - std::string class_name (void) const { return m_rep->class_name (); } + std::string class_name (void) const { return m_rep->class_name (); } - cdef_object clone (void) const { return cdef_object (m_rep->clone ()); } + cdef_object clone (void) const { return cdef_object (m_rep->clone ()); } - cdef_object empty_clone (void) const - { - return cdef_object (m_rep->empty_clone ()); - } + cdef_object empty_clone (void) const + { + return cdef_object (m_rep->empty_clone ()); + } - dim_vector dims (void) const { return m_rep->dims (); } + dim_vector dims (void) const { return m_rep->dims (); } - cdef_object make_array (void) const - { - return cdef_object (m_rep->make_array ()); - } + cdef_object make_array (void) const + { + return cdef_object (m_rep->make_array ()); + } - cdef_object copy (void) const { return cdef_object (m_rep->copy ()); } + cdef_object copy (void) const { return cdef_object (m_rep->copy ()); } - bool is_array (void) const { return m_rep->is_array (); } + bool is_array (void) const { return m_rep->is_array (); } - bool is_value_object (void) const { return m_rep->is_value_object (); } + bool is_value_object (void) const { return m_rep->is_value_object (); } - bool is_handle_object (void) const { return m_rep->is_handle_object (); } + bool is_handle_object (void) const { return m_rep->is_handle_object (); } - bool is_meta_object (void) const { return m_rep->is_meta_object (); } + bool is_meta_object (void) const { return m_rep->is_meta_object (); } - Array array_value (void) const - { return m_rep->array_value (); } + Array array_value (void) const + { return m_rep->array_value (); } - void put (const std::string& pname, const octave_value& val) - { - m_rep->put (pname, val); - } + void put (const std::string& pname, const octave_value& val) + { + m_rep->put (pname, val); + } - octave_value get (const std::string& pname) const - { - return m_rep->get (pname); - } + octave_value get (const std::string& pname) const + { + return m_rep->get (pname); + } - void set_property (octave_idx_type idx, const std::string& pname, - const octave_value& pval) - { - return m_rep->set_property (idx, pname, pval); - } + void set_property (octave_idx_type idx, const std::string& pname, + const octave_value& pval) + { + return m_rep->set_property (idx, pname, pval); + } - octave_value - get_property (octave_idx_type idx, const std::string& pname) const - { - return m_rep->get_property (idx, pname); - } + octave_value + get_property (octave_idx_type idx, const std::string& pname) const + { + return m_rep->get_property (idx, pname); + } - void break_closure_cycles (const std::shared_ptr& frame) - { - m_rep->break_closure_cycles (frame); - } + void break_closure_cycles (const std::shared_ptr& frame) + { + m_rep->break_closure_cycles (frame); + } - octave_value_list - subsref (const std::string& type, const std::list& idx, - int nargout, std::size_t& skip, const cdef_class& context, - bool auto_add = false) - { - return m_rep->subsref (type, idx, nargout, skip, context, auto_add); - } + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, std::size_t& skip, const cdef_class& context, + bool auto_add = false) + { + return m_rep->subsref (type, idx, nargout, skip, context, auto_add); + } - octave_value - subsasgn (const std::string& type, const std::list& idx, - const octave_value& rhs, int ignore_copies = 0) - { - make_unique (ignore_copies); - return m_rep->subsasgn (type, idx, rhs); - } + octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs, int ignore_copies = 0) + { + make_unique (ignore_copies); + return m_rep->subsasgn (type, idx, rhs); + } - string_vector map_keys (void) const { return m_rep->map_keys (); } + string_vector map_keys (void) const { return m_rep->map_keys (); } - OCTINTERP_API octave_map map_value (void) const; + OCTINTERP_API octave_map map_value (void) const; - const cdef_object_rep * get_rep (void) const { return m_rep; } + const cdef_object_rep * get_rep (void) const { return m_rep; } - bool ok (void) const { return m_rep->is_valid (); } + bool ok (void) const { return m_rep->is_valid (); } - void mark_for_construction (const cdef_class& cls) - { - m_rep->mark_for_construction (cls); - } + void mark_for_construction (const cdef_class& cls) + { + m_rep->mark_for_construction (cls); + } - bool is_constructed (void) const { return m_rep->is_constructed (); } + bool is_constructed (void) const { return m_rep->is_constructed (); } - bool is_constructed_for (const cdef_class& cls) const - { - return m_rep->is_constructed_for (cls); - } + bool is_constructed_for (const cdef_class& cls) const + { + return m_rep->is_constructed_for (cls); + } - bool is_partially_constructed_for (const cdef_class& cls) const - { - return m_rep->is_partially_constructed_for (cls); - } + bool is_partially_constructed_for (const cdef_class& cls) const + { + return m_rep->is_partially_constructed_for (cls); + } - void mark_as_constructed (void) { m_rep->mark_as_constructed (); } + void mark_as_constructed (void) { m_rep->mark_as_constructed (); } - void mark_as_constructed (const cdef_class& cls) - { m_rep->mark_as_constructed (cls); } + void mark_as_constructed (const cdef_class& cls) + { m_rep->mark_as_constructed (cls); } - bool is (const cdef_object& obj) const { return m_rep == obj.m_rep; } + bool is (const cdef_object& obj) const { return m_rep == obj.m_rep; } - protected: +protected: - cdef_object_rep * get_rep (void) { return m_rep; } + cdef_object_rep * get_rep (void) { return m_rep; } - void make_unique (int ignore_copies) - { - if (m_rep->m_count > ignore_copies + 1) - *this = clone (); - } + void make_unique (int ignore_copies) + { + if (m_rep->m_count > ignore_copies + 1) + *this = clone (); + } - private: +private: - cdef_object_rep *m_rep; - }; + cdef_object_rep *m_rep; +}; - class - OCTINTERP_API - cdef_object_base : public cdef_object_rep - { - public: +class +OCTINTERP_API +cdef_object_base : public cdef_object_rep +{ +public: - cdef_object_base (void) - : cdef_object_rep (), m_klass () - { } + cdef_object_base (void) + : cdef_object_rep (), m_klass () + { } - cdef_object_base& operator = (const cdef_object_base&) = delete; + cdef_object_base& operator = (const cdef_object_base&) = delete; - ~cdef_object_base (void) { } + ~cdef_object_base (void) { } - OCTINTERP_API cdef_class get_class (void) const; + OCTINTERP_API cdef_class get_class (void) const; - OCTINTERP_API void set_class (const cdef_class& cls); + OCTINTERP_API void set_class (const cdef_class& cls); - cdef_object_rep * empty_clone (void) const - { - return new cdef_object_base (*this); - } + cdef_object_rep * empty_clone (void) const + { + return new cdef_object_base (*this); + } - OCTINTERP_API cdef_object_rep * make_array (void) const; + OCTINTERP_API cdef_object_rep * make_array (void) const; - protected: +protected: - // Restricted copying! - cdef_object_base (const cdef_object_base& obj) - : cdef_object_rep (obj), m_klass (obj.m_klass) - { } + // Restricted copying! + cdef_object_base (const cdef_object_base& obj) + : cdef_object_rep (obj), m_klass (obj.m_klass) + { } - private: +private: - // The class of the object - cdef_object m_klass; - }; + // The class of the object + cdef_object m_klass; +}; - class - OCTINTERP_API - cdef_object_array : public cdef_object_base - { - public: +class +OCTINTERP_API +cdef_object_array : public cdef_object_base +{ +public: - cdef_object_array (void) : cdef_object_base () { } + cdef_object_array (void) : cdef_object_base () { } - cdef_object_array (const Array& a) - : cdef_object_base (), m_array (a) - { } + cdef_object_array (const Array& a) + : cdef_object_base (), m_array (a) + { } - cdef_object_array& operator = (const cdef_object_array&) = delete; + cdef_object_array& operator = (const cdef_object_array&) = delete; - ~cdef_object_array (void) = default; + ~cdef_object_array (void) = default; - cdef_object_rep * clone (void) const - { - return new cdef_object_array (*this); - } + cdef_object_rep * clone (void) const + { + return new cdef_object_array (*this); + } - dim_vector dims (void) const { return m_array.dims (); } + dim_vector dims (void) const { return m_array.dims (); } - bool is_valid (void) const { return true; } + bool is_valid (void) const { return true; } - bool is_array (void) const { return true; } + bool is_array (void) const { return true; } - Array array_value (void) const { return m_array; } + Array array_value (void) const { return m_array; } - OCTINTERP_API octave_value_list - subsref (const std::string& type, const std::list& idx, - int nargout, std::size_t& skip, const cdef_class& context, - bool auto_add); + OCTINTERP_API octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, std::size_t& skip, const cdef_class& context, + bool auto_add); - OCTINTERP_API octave_value - subsasgn (const std::string& type, const std::list& idx, - const octave_value& rhs); + OCTINTERP_API octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); - void set_property (octave_idx_type idx, const std::string& pname, - const octave_value& pval) - { - cdef_object& tmp = m_array.elem (idx); + void set_property (octave_idx_type idx, const std::string& pname, + const octave_value& pval) + { + cdef_object& tmp = m_array.elem (idx); - return tmp.put (pname, pval); - } + return tmp.put (pname, pval); + } - octave_value - get_property (octave_idx_type idx, const std::string& pname) const - { - cdef_object tmp = m_array.elem (idx); + octave_value + get_property (octave_idx_type idx, const std::string& pname) const + { + cdef_object tmp = m_array.elem (idx); - return tmp.get (pname); - } + return tmp.get (pname); + } - private: +private: - Array m_array; + Array m_array; - void fill_empty_values (void) { fill_empty_values (m_array); } + void fill_empty_values (void) { fill_empty_values (m_array); } - OCTINTERP_API void fill_empty_values (Array& arr); + OCTINTERP_API void fill_empty_values (Array& arr); - // Private copying! - cdef_object_array (const cdef_object_array& obj) - : cdef_object_base (obj), m_array (obj.m_array) - { } - }; + // Private copying! + cdef_object_array (const cdef_object_array& obj) + : cdef_object_base (obj), m_array (obj.m_array) + { } +}; - class - OCTINTERP_API - cdef_object_scalar : public cdef_object_base - { - public: +class +OCTINTERP_API +cdef_object_scalar : public cdef_object_base +{ +public: - cdef_object_scalar (void) : cdef_object_base () { } + cdef_object_scalar (void) : cdef_object_base () { } - cdef_object_scalar& operator = (const cdef_object_scalar&) = delete; + cdef_object_scalar& operator = (const cdef_object_scalar&) = delete; - ~cdef_object_scalar (void) = default; + ~cdef_object_scalar (void) = default; - dim_vector dims (void) const { return dim_vector (1, 1); } + dim_vector dims (void) const { return dim_vector (1, 1); } - void break_closure_cycles (const std::shared_ptr& frame); + void break_closure_cycles (const std::shared_ptr& frame); - void put (const std::string& pname, const octave_value& val) - { - m_map.assign (pname, val); - } + void put (const std::string& pname, const octave_value& val) + { + m_map.assign (pname, val); + } - octave_value get (const std::string& pname) const - { - Cell val = m_map.contents (pname); + octave_value get (const std::string& pname) const + { + Cell val = m_map.contents (pname); - if (val.numel () < 1) - error ("get: unknown slot: %s", pname.c_str ()); + if (val.numel () < 1) + error ("get: unknown slot: %s", pname.c_str ()); - return val(0, 0); - } + return val(0, 0); + } - void set_property (octave_idx_type idx, const std::string& pname, - const octave_value& pval) - { - if (idx != 0) - error ("invalid index"); // FIXME + void set_property (octave_idx_type idx, const std::string& pname, + const octave_value& pval) + { + if (idx != 0) + error ("invalid index"); // FIXME - put (pname, pval); - } + put (pname, pval); + } - octave_value - get_property (octave_idx_type idx, const std::string& pname) const - { - if (idx != 0) - error ("invalid index"); // FIXME + octave_value + get_property (octave_idx_type idx, const std::string& pname) const + { + if (idx != 0) + error ("invalid index"); // FIXME - return get (pname); - } + return get (pname); + } - OCTINTERP_API octave_value_list - subsref (const std::string& type, const std::list& idx, - int nargout, std::size_t& skip, const cdef_class& context, - bool auto_add); + OCTINTERP_API octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout, std::size_t& skip, const cdef_class& context, + bool auto_add); - OCTINTERP_API octave_value - subsasgn (const std::string& type, const std::list& idx, - const octave_value& rhs); + OCTINTERP_API octave_value + subsasgn (const std::string& type, const std::list& idx, + const octave_value& rhs); - OCTINTERP_API void mark_for_construction (const cdef_class&); + OCTINTERP_API void mark_for_construction (const cdef_class&); - OCTINTERP_API bool is_constructed_for (const cdef_class& cls) const; + OCTINTERP_API bool is_constructed_for (const cdef_class& cls) const; - OCTINTERP_API bool - is_partially_constructed_for (const cdef_class& cls) const; + OCTINTERP_API bool + is_partially_constructed_for (const cdef_class& cls) const; - void mark_as_constructed (void) { m_ctor_list.clear (); } + void mark_as_constructed (void) { m_ctor_list.clear (); } - OCTINTERP_API void mark_as_constructed (const cdef_class& cls); + OCTINTERP_API void mark_as_constructed (const cdef_class& cls); - bool is_constructed (void) const { return m_ctor_list.empty (); } + bool is_constructed (void) const { return m_ctor_list.empty (); } - protected: +protected: - // Object property values - octave_scalar_map m_map; + // Object property values + octave_scalar_map m_map; - // Internal/temporary structure used during object construction - std::map< cdef_class, std::list> m_ctor_list; + // Internal/temporary structure used during object construction + std::map< cdef_class, std::list> m_ctor_list; - protected: +protected: - // Restricted object copying! - cdef_object_scalar (const cdef_object_scalar& obj) - : cdef_object_base (obj), m_map (obj.m_map), m_ctor_list (obj.m_ctor_list) - { } - }; + // Restricted object copying! + cdef_object_scalar (const cdef_object_scalar& obj) + : cdef_object_base (obj), m_map (obj.m_map), m_ctor_list (obj.m_ctor_list) + { } +}; - class - OCTINTERP_API - handle_cdef_object : public cdef_object_scalar - { - public: +class +OCTINTERP_API +handle_cdef_object : public cdef_object_scalar +{ +public: - handle_cdef_object (void) : cdef_object_scalar () { } + handle_cdef_object (void) : cdef_object_scalar () { } - handle_cdef_object& operator = (const handle_cdef_object&) = delete; + handle_cdef_object& operator = (const handle_cdef_object&) = delete; - OCTINTERP_API ~handle_cdef_object (void); + OCTINTERP_API ~handle_cdef_object (void); - cdef_object_rep * clone (void) const - { - handle_cdef_object *obj = const_cast (this); - obj->m_count++; - return obj; - } + cdef_object_rep * clone (void) const + { + handle_cdef_object *obj = const_cast (this); + obj->m_count++; + return obj; + } - cdef_object_rep * copy (void) const - { - return new handle_cdef_object (*this); - } + cdef_object_rep * copy (void) const + { + return new handle_cdef_object (*this); + } - bool is_valid (void) const { return true; } + bool is_valid (void) const { return true; } - bool is_handle_object (void) const { return true; } + bool is_handle_object (void) const { return true; } - protected: +protected: - // Restricted copying! - handle_cdef_object (const handle_cdef_object& obj) - : cdef_object_scalar (obj) - { } - }; + // Restricted copying! + handle_cdef_object (const handle_cdef_object& obj) + : cdef_object_scalar (obj) + { } +}; - class - OCTINTERP_API - value_cdef_object : public cdef_object_scalar - { - public: +class +OCTINTERP_API +value_cdef_object : public cdef_object_scalar +{ +public: - value_cdef_object (void) : cdef_object_scalar () { } + value_cdef_object (void) : cdef_object_scalar () { } - value_cdef_object& operator = (const value_cdef_object&) = delete; + value_cdef_object& operator = (const value_cdef_object&) = delete; - OCTINTERP_API ~value_cdef_object (void); + OCTINTERP_API ~value_cdef_object (void); - cdef_object_rep * clone (void) const - { - return new value_cdef_object (*this); - } + cdef_object_rep * clone (void) const + { + return new value_cdef_object (*this); + } - cdef_object_rep * copy (void) const { return clone (); } + cdef_object_rep * copy (void) const { return clone (); } - bool is_valid (void) const { return true; } + bool is_valid (void) const { return true; } - bool is_value_object (void) const { return true; } + bool is_value_object (void) const { return true; } - private: +private: - // Private copying! - value_cdef_object (const value_cdef_object& obj) - : cdef_object_scalar (obj) - { } - }; + // Private copying! + value_cdef_object (const value_cdef_object& obj) + : cdef_object_scalar (obj) + { } +}; - class - OCTINTERP_API - cdef_meta_object_rep : public handle_cdef_object - { - public: +class +OCTINTERP_API +cdef_meta_object_rep : public handle_cdef_object +{ +public: - cdef_meta_object_rep (void) : handle_cdef_object () { } + cdef_meta_object_rep (void) : handle_cdef_object () { } - cdef_meta_object_rep& operator = (const cdef_meta_object_rep&) = delete; + cdef_meta_object_rep& operator = (const cdef_meta_object_rep&) = delete; - ~cdef_meta_object_rep (void) = default; + ~cdef_meta_object_rep (void) = default; - cdef_object_rep * copy (void) const - { return new cdef_meta_object_rep (*this); } + cdef_object_rep * copy (void) const + { return new cdef_meta_object_rep (*this); } - bool is_meta_object (void) const { return true; } + bool is_meta_object (void) const { return true; } - virtual bool is_class (void) const { return false; } + virtual bool is_class (void) const { return false; } - virtual bool is_property (void) const { return false; } + virtual bool is_property (void) const { return false; } - virtual bool is_method (void) const { return false; } + virtual bool is_method (void) const { return false; } - virtual bool is_package (void) const { return false; } + virtual bool is_package (void) const { return false; } - virtual octave_value_list - meta_subsref (const std::string& /* type */, - const std::list& /* idx */, - int /* nargout */) - { - error ("subsref: invalid meta object"); - } + virtual octave_value_list + meta_subsref (const std::string& /* type */, + const std::list& /* idx */, + int /* nargout */) + { + error ("subsref: invalid meta object"); + } - virtual void meta_release (void) { } + virtual void meta_release (void) { } - virtual bool meta_accepts_postfix_index (char /* type */) const - { - return false; - } + virtual bool meta_accepts_postfix_index (char /* type */) const + { + return false; + } - protected: +protected: - // Restricted copying! - cdef_meta_object_rep (const cdef_meta_object_rep& obj) - : handle_cdef_object (obj) - { } - }; + // Restricted copying! + cdef_meta_object_rep (const cdef_meta_object_rep& obj) + : handle_cdef_object (obj) + { } +}; - class - OCTINTERP_API - cdef_meta_object : public cdef_object - { - public: +class +OCTINTERP_API +cdef_meta_object : public cdef_object +{ +public: - cdef_meta_object (void) : cdef_object () { } + cdef_meta_object (void) : cdef_object () { } - // Object consistency is checked in sub-classes. - cdef_meta_object (const cdef_meta_object& obj) : cdef_object (obj) { } + // Object consistency is checked in sub-classes. + cdef_meta_object (const cdef_meta_object& obj) : cdef_object (obj) { } - cdef_meta_object (cdef_meta_object_rep *r) : cdef_object (r) { } + cdef_meta_object (cdef_meta_object_rep *r) : cdef_object (r) { } - cdef_meta_object (const cdef_object& obj) : cdef_object (obj) { } + cdef_meta_object (const cdef_object& obj) : cdef_object (obj) { } - cdef_meta_object& operator = (const cdef_object&) = delete; + cdef_meta_object& operator = (const cdef_object&) = delete; - ~cdef_meta_object (void) = default; + ~cdef_meta_object (void) = default; - bool is_class (void) const { return get_rep ()->is_class (); } + bool is_class (void) const { return get_rep ()->is_class (); } - bool is_property (void) const { return get_rep ()->is_property (); } + bool is_property (void) const { return get_rep ()->is_property (); } - bool is_method (void) const { return get_rep ()->is_method (); } + bool is_method (void) const { return get_rep ()->is_method (); } - bool is_package (void) const { return get_rep ()->is_package (); } + bool is_package (void) const { return get_rep ()->is_package (); } - octave_value_list - meta_subsref (const std::string& type, - const std::list& idx, int nargout) - { - return get_rep ()->meta_subsref (type, idx, nargout); - } + octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout) + { + return get_rep ()->meta_subsref (type, idx, nargout); + } - void meta_release (void) { get_rep ()->meta_release (); } + void meta_release (void) { get_rep ()->meta_release (); } - bool meta_accepts_postfix_index (char type) const - { - return get_rep ()->meta_accepts_postfix_index (type); - } + bool meta_accepts_postfix_index (char type) const + { + return get_rep ()->meta_accepts_postfix_index (type); + } - private: +private: - cdef_meta_object_rep * get_rep (void) - { - return dynamic_cast (cdef_object::get_rep ()); - } + cdef_meta_object_rep * get_rep (void) + { + return dynamic_cast (cdef_object::get_rep ()); + } - const cdef_meta_object_rep * get_rep (void) const - { - return dynamic_cast (cdef_object::get_rep ()); - } - }; + const cdef_meta_object_rep * get_rep (void) const + { + return dynamic_cast (cdef_object::get_rep ()); + } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-package.cc --- a/libinterp/octave-value/cdef-package.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-package.cc Thu Dec 01 20:05:44 2022 -0800 @@ -53,151 +53,152 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - cdef_package::cdef_package_rep::install_class (const cdef_class& cls, - const std::string& nm) - { - m_class_map[nm] = cls; +void +cdef_package::cdef_package_rep::install_class (const cdef_class& cls, + const std::string& nm) +{ + m_class_map[nm] = cls; - m_member_count++; - } + m_member_count++; +} - void - cdef_package::cdef_package_rep::install_function (const octave_value& fcn, - const std::string& nm) - { - m_function_map[nm] = fcn; - } +void +cdef_package::cdef_package_rep::install_function (const octave_value& fcn, + const std::string& nm) +{ + m_function_map[nm] = fcn; +} - void - cdef_package::cdef_package_rep::install_package (const cdef_package& pack, - const std::string& nm) - { - m_package_map[nm] = pack; +void +cdef_package::cdef_package_rep::install_package (const cdef_package& pack, + const std::string& nm) +{ + m_package_map[nm] = pack; - m_member_count++; - } + m_member_count++; +} - template - Cell - map2Cell (const std::map& m) - { - Cell retval (1, m.size ()); - int i = 0; +template +Cell +map2Cell (const std::map& m) +{ + Cell retval (1, m.size ()); + int i = 0; - for (auto it = m.begin (); it != m.end (); ++it, ++i) - retval(i) = to_ov (it->second); + for (auto it = m.begin (); it != m.end (); ++it, ++i) + retval(i) = to_ov (it->second); - return retval; - } + return retval; +} - Cell - cdef_package::cdef_package_rep::get_classes (void) const - { - return map2Cell (m_class_map); - } +Cell +cdef_package::cdef_package_rep::get_classes (void) const +{ + return map2Cell (m_class_map); +} - Cell - cdef_package::cdef_package_rep::get_functions (void) const - { - return map2Cell (m_function_map); - } +Cell +cdef_package::cdef_package_rep::get_functions (void) const +{ + return map2Cell (m_function_map); +} - Cell - cdef_package::cdef_package_rep::get_packages (void) const - { - return map2Cell (m_package_map); - } +Cell +cdef_package::cdef_package_rep::get_packages (void) const +{ + return map2Cell (m_package_map); +} - octave_value - cdef_package::cdef_package_rep::find (const std::string& nm) - { - std::string symbol_name = get_name () + '.' + nm; +octave_value +cdef_package::cdef_package_rep::find (const std::string& nm) +{ + std::string symbol_name = get_name () + '.' + nm; - interpreter& interp = __get_interpreter__ (); + interpreter& interp = __get_interpreter__ (); - return interp.find (symbol_name); - } + return interp.find (symbol_name); +} - octave_value_list - cdef_package::cdef_package_rep::meta_subsref - (const std::string& type, const std::list& idx, - int nargout) - { - octave_value_list retval; +octave_value_list +cdef_package::cdef_package_rep::meta_subsref +(const std::string& type, const std::list& idx, + int nargout) +{ + octave_value_list retval; - switch (type[0]) + switch (type[0]) + { + case '.': { - case '.': - { - if (idx.front ().length () != 1) - error ("invalid meta.package indexing"); + if (idx.front ().length () != 1) + error ("invalid meta.package indexing"); - std::string nm = idx.front ()(0).xstring_value ("invalid meta.package indexing, expected a symbol name"); + std::string nm = idx.front ()( + 0).xstring_value ("invalid meta.package indexing, expected a symbol name"); #if DEBUG_TRACE - std::cerr << "meta.package query: " << nm << std::endl; + std::cerr << "meta.package query: " << nm << std::endl; #endif - octave_value o = find (nm); + octave_value o = find (nm); - if (! o.is_defined ()) - error ("member '%s' in package '%s' does not exist", - nm.c_str (), get_name ().c_str ()); + if (! o.is_defined ()) + error ("member '%s' in package '%s' does not exist", + nm.c_str (), get_name ().c_str ()); - if (o.is_function ()) - { - octave_function *fcn = o.function_value (); + if (o.is_function ()) + { + octave_function *fcn = o.function_value (); - // NOTE: the case where the package query is the last - // part of this subsref index is handled in the parse - // tree, because there is some logic to handle magic - // "end" that makes it impossible to execute the - // function call at this stage. + // NOTE: the case where the package query is the last + // part of this subsref index is handled in the parse + // tree, because there is some logic to handle magic + // "end" that makes it impossible to execute the + // function call at this stage. - if (type.size () > 1 - && ! fcn->accepts_postfix_index (type[1])) - { - octave_value_list tmp_args; + if (type.size () > 1 + && ! fcn->accepts_postfix_index (type[1])) + { + octave_value_list tmp_args; - retval = feval (o, tmp_args, nargout); - } - else - retval(0) = o; + retval = feval (o, tmp_args, nargout); + } + else + retval(0) = o; - if (type.size () > 1 && idx.size () > 1) - retval = retval(0).next_subsref (nargout, type, - idx, 1); - } - else if (type.size () > 1 && idx.size () > 1) - retval = o.next_subsref (nargout, type, idx, 1); - else - retval(0) = o; - } - break; + if (type.size () > 1 && idx.size () > 1) + retval = retval(0).next_subsref (nargout, type, + idx, 1); + } + else if (type.size () > 1 && idx.size () > 1) + retval = o.next_subsref (nargout, type, idx, 1); + else + retval(0) = o; + } + break; - default: - error ("invalid meta.package indexing"); - break; - } + default: + error ("invalid meta.package indexing"); + break; + } - return retval; - } + return retval; +} - void - cdef_package::cdef_package_rep::meta_release (void) - { - // FIXME: Do we really want to unregister the package, as it - // could still be referenced by classes or sub-packages? - // If the package object is recreated later on, it won't - // match the one already referenced by those classes or - // sub-packages. +void +cdef_package::cdef_package_rep::meta_release (void) +{ + // FIXME: Do we really want to unregister the package, as it + // could still be referenced by classes or sub-packages? + // If the package object is recreated later on, it won't + // match the one already referenced by those classes or + // sub-packages. - cdef_manager& cdm = __get_cdef_manager__ (); + cdef_manager& cdm = __get_cdef_manager__ (); - // Don't delete the "meta" package. - if (this != cdm.meta ().get_rep ()) - cdm.unregister_package (wrap ()); - } + // Don't delete the "meta" package. + if (this != cdm.meta ().get_rep ()) + cdm.unregister_package (wrap ()); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-package.h --- a/libinterp/octave-value/cdef-package.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-package.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,195 +40,195 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; + +class +OCTINTERP_API +cdef_package : public cdef_meta_object +{ + friend class cdef_class; + +private: class - OCTINTERP_API - cdef_package : public cdef_meta_object + cdef_package_rep : public cdef_meta_object_rep { - friend class cdef_class; + public: + + cdef_package_rep (void) : cdef_meta_object_rep (), m_member_count (0) { } + + cdef_package_rep& operator = (const cdef_package_rep&) = delete; + + ~cdef_package_rep (void) = default; + + cdef_object_rep * copy (void) const + { return new cdef_package_rep (*this); } + + bool is_package (void) const { return true; } + + std::string get_name (void) const { return get("Name").string_value (); } + + void set_name (const std::string& nm) { put ("Name", nm); } + + OCTINTERP_API void + install_class (const cdef_class& cls, const std::string& nm); + + OCTINTERP_API void + install_function (const octave_value& fcn, const std::string& nm); + + OCTINTERP_API void + install_package (const cdef_package& pack, const std::string& nm); + + OCTINTERP_API Cell get_classes (void) const; + + OCTINTERP_API Cell get_functions (void) const; + + OCTINTERP_API Cell get_packages (void) const; + + octave_idx_type static_count (void) const { return m_member_count; } + + void destroy (void) + { + if (m_member_count) + { + m_count++; + cdef_package lock (this); + + m_member_count = 0; + m_class_map.clear (); + m_package_map.clear (); + } + else + delete this; + } + + OCTINTERP_API octave_value_list + meta_subsref (const std::string& type, + const std::list& idx, int nargout); + + OCTINTERP_API void meta_release (void); + + bool meta_accepts_postfix_index (char type) const + { + return (type == '.'); + } + + OCTINTERP_API octave_value find (const std::string& nm); private: - class - cdef_package_rep : public cdef_meta_object_rep - { - public: - - cdef_package_rep (void) : cdef_meta_object_rep (), m_member_count (0) { } - - cdef_package_rep& operator = (const cdef_package_rep&) = delete; + std::string m_full_name; + std::map m_class_map; + std::map m_function_map; + std::map m_package_map; - ~cdef_package_rep (void) = default; - - cdef_object_rep * copy (void) const - { return new cdef_package_rep (*this); } - - bool is_package (void) const { return true; } - - std::string get_name (void) const { return get("Name").string_value (); } + // The number of registered members in this package (classes, packages). + // This only accounts for the members that back-reference to this package. + octave_idx_type m_member_count; - void set_name (const std::string& nm) { put ("Name", nm); } - - OCTINTERP_API void - install_class (const cdef_class& cls, const std::string& nm); - - OCTINTERP_API void - install_function (const octave_value& fcn, const std::string& nm); + typedef std::map::iterator class_iterator; + typedef std::map::const_iterator class_const_iterator; + typedef std::map::iterator function_iterator; + typedef std::map::const_iterator + function_const_iterator; + typedef std::map::iterator package_iterator; + typedef std::map::const_iterator + package_const_iterator; - OCTINTERP_API void - install_package (const cdef_package& pack, const std::string& nm); - - OCTINTERP_API Cell get_classes (void) const; - - OCTINTERP_API Cell get_functions (void) const; - - OCTINTERP_API Cell get_packages (void) const; - - octave_idx_type static_count (void) const { return m_member_count; } + cdef_package_rep (const cdef_package_rep& p) + : cdef_meta_object_rep (p), m_full_name (p.m_full_name), + m_class_map (p.m_class_map), m_function_map (p.m_function_map), + m_package_map (p.m_package_map), m_member_count (p.m_member_count) + { } - void destroy (void) - { - if (m_member_count) - { - m_count++; - cdef_package lock (this); + cdef_package wrap (void) + { + m_count++; + return cdef_package (this); + } + }; - m_member_count = 0; - m_class_map.clear (); - m_package_map.clear (); - } - else - delete this; - } +public: - OCTINTERP_API octave_value_list - meta_subsref (const std::string& type, - const std::list& idx, int nargout); - - OCTINTERP_API void meta_release (void); + cdef_package (void) : cdef_meta_object () { } - bool meta_accepts_postfix_index (char type) const - { - return (type == '.'); - } + cdef_package (const std::string& nm) + : cdef_meta_object (new cdef_package_rep ()) + { + get_rep ()->set_name (nm); + } - OCTINTERP_API octave_value find (const std::string& nm); - - private: + cdef_package (const cdef_package& pack) : cdef_meta_object (pack) { } - std::string m_full_name; - std::map m_class_map; - std::map m_function_map; - std::map m_package_map; - - // The number of registered members in this package (classes, packages). - // This only accounts for the members that back-reference to this package. - octave_idx_type m_member_count; + cdef_package (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_package ()) + error ("internal error: invalid assignment from %s to meta.package object", + class_name ().c_str ()); + } - typedef std::map::iterator class_iterator; - typedef std::map::const_iterator class_const_iterator; - typedef std::map::iterator function_iterator; - typedef std::map::const_iterator - function_const_iterator; - typedef std::map::iterator package_iterator; - typedef std::map::const_iterator - package_const_iterator; + cdef_package& operator = (const cdef_package& pack) + { + cdef_object::operator = (pack); - cdef_package_rep (const cdef_package_rep& p) - : cdef_meta_object_rep (p), m_full_name (p.m_full_name), - m_class_map (p.m_class_map), m_function_map (p.m_function_map), - m_package_map (p.m_package_map), m_member_count (p.m_member_count) - { } + return *this; + } + + ~cdef_package (void) = default; - cdef_package wrap (void) - { - m_count++; - return cdef_package (this); - } - }; - - public: - - cdef_package (void) : cdef_meta_object () { } + void install_class (const cdef_class& cls, const std::string& nm) + { + get_rep ()->install_class (cls, nm); + } - cdef_package (const std::string& nm) - : cdef_meta_object (new cdef_package_rep ()) - { - get_rep ()->set_name (nm); - } - - cdef_package (const cdef_package& pack) : cdef_meta_object (pack) { } + void install_function (const octave_value& fcn, const std::string& nm) + { + get_rep ()->install_function (fcn, nm); + } - cdef_package (const cdef_object& obj) - : cdef_meta_object (obj) - { - // This should never happen... - if (! is_package ()) - error ("internal error: invalid assignment from %s to meta.package object", - class_name ().c_str ()); - } + void install_package (const cdef_package& pack, const std::string& nm) + { + get_rep ()->install_package (pack, nm); + } - cdef_package& operator = (const cdef_package& pack) - { - cdef_object::operator = (pack); - - return *this; - } - - ~cdef_package (void) = default; + Cell get_classes (void) const + { + return get_rep ()->get_classes (); + } - void install_class (const cdef_class& cls, const std::string& nm) - { - get_rep ()->install_class (cls, nm); - } - - void install_function (const octave_value& fcn, const std::string& nm) - { - get_rep ()->install_function (fcn, nm); - } + Cell get_functions (void) const + { + return get_rep ()->get_functions (); + } - void install_package (const cdef_package& pack, const std::string& nm) - { - get_rep ()->install_package (pack, nm); - } + Cell get_packages (void) const + { + return get_rep ()->get_packages (); + } - Cell get_classes (void) const - { - return get_rep ()->get_classes (); - } - - Cell get_functions (void) const - { - return get_rep ()->get_functions (); - } + std::string get_name (void) const { return get_rep ()->get_name (); } - Cell get_packages (void) const - { - return get_rep ()->get_packages (); - } + octave_value find (const std::string& nm) + { + return get_rep ()->find (nm); + } - std::string get_name (void) const { return get_rep ()->get_name (); } - - octave_value find (const std::string& nm) - { - return get_rep ()->find (nm); - } +private: - private: - - cdef_package_rep * get_rep (void) - { - return dynamic_cast (cdef_object::get_rep ()); - } + cdef_package_rep * get_rep (void) + { + return dynamic_cast (cdef_object::get_rep ()); + } - const cdef_package_rep * get_rep (void) const - { - return dynamic_cast (cdef_object::get_rep ()); - } + const cdef_package_rep * get_rep (void) const + { + return dynamic_cast (cdef_object::get_rep ()); + } - friend void install_classdef (octave::interpreter& interp); - }; + friend void install_classdef (octave::interpreter& interp); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-property.cc --- a/libinterp/octave-value/cdef-property.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-property.cc Thu Dec 01 20:05:44 2022 -0800 @@ -52,201 +52,201 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static bool - is_method_executing (const octave_value& ov, const cdef_object& obj) - { - tree_evaluator& tw = __get_evaluator__ (); +static bool +is_method_executing (const octave_value& ov, const cdef_object& obj) +{ + tree_evaluator& tw = __get_evaluator__ (); - octave_function *stack_fcn = tw.current_function (); + octave_function *stack_fcn = tw.current_function (); - octave_function *method_fcn = ov.function_value (true); + octave_function *method_fcn = ov.function_value (true); - // Does the top of the call stack match our target function? + // Does the top of the call stack match our target function? - if (stack_fcn && stack_fcn == method_fcn) - { - octave_user_function *uf = method_fcn->user_function_value (true); + if (stack_fcn && stack_fcn == method_fcn) + { + octave_user_function *uf = method_fcn->user_function_value (true); - // We can only check the context object for user-function (not builtin), - // where we have access to the parameters (arguments and return values). - // That's ok as there's no need to call this function for builtin - // methods. + // We can only check the context object for user-function (not builtin), + // where we have access to the parameters (arguments and return values). + // That's ok as there's no need to call this function for builtin + // methods. - if (uf) - { - // At this point, the method is executing, but we still need to - // check the context object for which the method is executing. For - // methods, it's the first argument of the function; for ctors, it - // is the first return value. + if (uf) + { + // At this point, the method is executing, but we still need to + // check the context object for which the method is executing. For + // methods, it's the first argument of the function; for ctors, it + // is the first return value. - tree_parameter_list *pl = uf->is_classdef_constructor () - ? uf->return_list () - : uf->parameter_list (); + tree_parameter_list *pl = uf->is_classdef_constructor () + ? uf->return_list () + : uf->parameter_list (); - if (pl && pl->size () > 0) - { - tree_decl_elt *elt = pl->front (); + if (pl && pl->size () > 0) + { + tree_decl_elt *elt = pl->front (); - octave_value arg0 = tw.evaluate (elt); + octave_value arg0 = tw.evaluate (elt); - if (arg0.is_defined () && arg0.type_name () == "object") - { - cdef_object arg0_obj = to_cdef (arg0); + if (arg0.is_defined () && arg0.type_name () == "object") + { + cdef_object arg0_obj = to_cdef (arg0); - return obj.is (arg0_obj); - } - } - } - } + return obj.is (arg0_obj); + } + } + } + } - return false; - } + return false; +} - octave_value - cdef_property::cdef_property_rep::get_value (const cdef_object& obj, - bool do_check_access, - const std::string& who) const - { - octave_value retval; +octave_value +cdef_property::cdef_property_rep::get_value (const cdef_object& obj, + bool do_check_access, + const std::string& who) const +{ + octave_value retval; - if (do_check_access && ! check_get_access ()) - err_property_access (who, false); + if (do_check_access && ! check_get_access ()) + err_property_access (who, false); - if (! obj.is_constructed ()) - { - cdef_class cls (to_cdef (get ("DefiningClass"))); + if (! obj.is_constructed ()) + { + cdef_class cls (to_cdef (get ("DefiningClass"))); - if (! obj.is_partially_constructed_for (cls)) - error ("cannot reference properties of class '%s' for non-constructed object", - cls.get_name ().c_str ()); - } + if (! obj.is_partially_constructed_for (cls)) + error ("cannot reference properties of class '%s' for non-constructed object", + cls.get_name ().c_str ()); + } - octave_value get_fcn = get ("GetMethod"); + octave_value get_fcn = get ("GetMethod"); - // FIXME: should check whether we're already in get accessor method + // FIXME: should check whether we're already in get accessor method - if (get_fcn.isempty () || is_method_executing (get_fcn, obj)) - retval = obj.get (get ("Name").string_value ()); - else - { - octave_value_list args; + if (get_fcn.isempty () || is_method_executing (get_fcn, obj)) + retval = obj.get (get ("Name").string_value ()); + else + { + octave_value_list args; - args(0) = to_ov (obj); + args(0) = to_ov (obj); - args = feval (get_fcn, args, 1); + args = feval (get_fcn, args, 1); - retval = args(0); - } + retval = args(0); + } - return retval; - } + return retval; +} - octave_value - cdef_property::cdef_property_rep::get_value (bool do_check_access, - const std::string& who) const - { - if (do_check_access && ! check_get_access ()) - err_property_access (who, false); +octave_value +cdef_property::cdef_property_rep::get_value (bool do_check_access, + const std::string& who) const +{ + if (do_check_access && ! check_get_access ()) + err_property_access (who, false); - return get ("DefaultValue"); - } + return get ("DefaultValue"); +} - bool - cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const - { - // FIXME: implement - return false; - } +bool +cdef_property::cdef_property_rep::is_recursive_set (const cdef_object& /* obj */) const +{ + // FIXME: implement + return false; +} - OCTAVE_NORETURN void - cdef_property::cdef_property_rep::err_property_access - (const std::string& from, bool is_set) const - { - octave_value acc = get (is_set ? "SetAccess" : "GetAccess"); - std::string acc_s; +OCTAVE_NORETURN void +cdef_property::cdef_property_rep::err_property_access +(const std::string& from, bool is_set) const +{ + octave_value acc = get (is_set ? "SetAccess" : "GetAccess"); + std::string acc_s; - if (acc.is_string ()) - acc_s = acc.string_value (); - else - acc_s = "class-restricted"; + if (acc.is_string ()) + acc_s = acc.string_value (); + else + acc_s = "class-restricted"; - if (is_set) - error ("%s: property '%s' has %s access and cannot be set in this context", - from.c_str (), get_name ().c_str (), acc_s.c_str ()); - else - error ("%s: property '%s' has %s access and cannot be obtained in this context", - from.c_str (), get_name ().c_str (), acc_s.c_str ()); - } + if (is_set) + error ("%s: property '%s' has %s access and cannot be set in this context", + from.c_str (), get_name ().c_str (), acc_s.c_str ()); + else + error ("%s: property '%s' has %s access and cannot be obtained in this context", + from.c_str (), get_name ().c_str (), acc_s.c_str ()); +} - void - cdef_property::cdef_property_rep::set_value (cdef_object& obj, - const octave_value& val, - bool do_check_access, - const std::string& who) - { - if (do_check_access && ! check_set_access ()) - err_property_access (who, true); +void +cdef_property::cdef_property_rep::set_value (cdef_object& obj, + const octave_value& val, + bool do_check_access, + const std::string& who) +{ + if (do_check_access && ! check_set_access ()) + err_property_access (who, true); - if (! obj.is_constructed ()) - { - cdef_class cls (to_cdef (get ("DefiningClass"))); + if (! obj.is_constructed ()) + { + cdef_class cls (to_cdef (get ("DefiningClass"))); - if (! obj.is_partially_constructed_for (cls)) - error ("cannot reference properties of class '%s' for non-constructed object", - cls.get_name ().c_str ()); - } + if (! obj.is_partially_constructed_for (cls)) + error ("cannot reference properties of class '%s' for non-constructed object", + cls.get_name ().c_str ()); + } - octave_value set_fcn = get ("SetMethod"); + octave_value set_fcn = get ("SetMethod"); - if (set_fcn.isempty () || is_method_executing (set_fcn, obj)) - obj.put (get ("Name").string_value (), val); - else - { - octave_value_list args; + if (set_fcn.isempty () || is_method_executing (set_fcn, obj)) + obj.put (get ("Name").string_value (), val); + else + { + octave_value_list args; - args(0) = to_ov (obj); - args(1) = val; + args(0) = to_ov (obj); + args(1) = val; - if (obj.is_handle_object ()) - feval (set_fcn, args, 0); - else - { - args = feval (set_fcn, args, 1); + if (obj.is_handle_object ()) + feval (set_fcn, args, 0); + else + { + args = feval (set_fcn, args, 1); - if (args.length () > 0 && args(0).is_defined ()) - { - if (args(0).is_classdef_object ()) - { - cdef_object new_obj = to_cdef (args(0)); + if (args.length () > 0 && args(0).is_defined ()) + { + if (args(0).is_classdef_object ()) + { + cdef_object new_obj = to_cdef (args(0)); - obj = new_obj; - } - else - ::warning ("set-method of property '%s' returned a non-classdef object", - get_name ().c_str ()); - } - } - } - } + obj = new_obj; + } + else + ::warning ("set-method of property '%s' returned a non-classdef object", + get_name ().c_str ()); + } + } + } +} - bool - cdef_property::cdef_property_rep::check_get_access (void) const - { - cdef_class cls (to_cdef (get ("DefiningClass"))); +bool +cdef_property::cdef_property_rep::check_get_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); - return check_access (cls, get ("GetAccess"), "", get_name (), false); + return check_access (cls, get ("GetAccess"), "", get_name (), false); - return false; - } + return false; +} - bool - cdef_property::cdef_property_rep::check_set_access (void) const - { - cdef_class cls (to_cdef (get ("DefiningClass"))); +bool +cdef_property::cdef_property_rep::check_set_access (void) const +{ + cdef_class cls (to_cdef (get ("DefiningClass"))); - return check_access (cls, get ("SetAccess"), "", get_name (), true); + return check_access (cls, get ("SetAccess"), "", get_name (), true); - return false; - } + return false; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-property.h --- a/libinterp/octave-value/cdef-property.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-property.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,146 +40,146 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTINTERP_API - cdef_property : public cdef_meta_object - { - friend class cdef_class; - - private: - - class - cdef_property_rep : public cdef_meta_object_rep - { - public: - - cdef_property_rep (void) : cdef_meta_object_rep () { } - - cdef_property_rep& operator = (const cdef_property_rep& p) = delete; - - ~cdef_property_rep (void) = default; - - cdef_object_rep * copy (void) const - { - return new cdef_property_rep (*this); - } - - bool is_property (void) const { return true; } - - std::string get_name (void) const { return get("Name").string_value (); } - - void set_name (const std::string& nm) { put ("Name", nm); } - - bool is_constant (void) const { return get("Constant").bool_value (); } +class +OCTINTERP_API +cdef_property : public cdef_meta_object +{ + friend class cdef_class; - octave_value get_value (bool do_check_access = true, - const std::string& who = "") const; - - octave_value get_value (const cdef_object& obj, - bool do_check_access = true, - const std::string& who = "") const; - - void set_value (cdef_object& obj, const octave_value& val, - bool do_check_access = true, - const std::string& who = ""); - - OCTINTERP_API bool check_get_access (void) const; - - OCTINTERP_API bool check_set_access (void) const; +private: - private: - cdef_property_rep (const cdef_property_rep& p) - : cdef_meta_object_rep (p) - { } - - OCTINTERP_API bool is_recursive_set (const cdef_object& obj) const; - - cdef_property wrap (void) - { - m_count++; - return cdef_property (this); - } - - OCTINTERP_API OCTAVE_NORETURN - void err_property_access (const std::string& from, - bool is_set = false) const; - }; - + class + cdef_property_rep : public cdef_meta_object_rep + { public: - cdef_property (void) : cdef_meta_object () { } + cdef_property_rep (void) : cdef_meta_object_rep () { } - cdef_property (const std::string& nm) - : cdef_meta_object (new cdef_property_rep ()) - { - get_rep ()->set_name (nm); - } + cdef_property_rep& operator = (const cdef_property_rep& p) = delete; - cdef_property (const cdef_property& prop) : cdef_meta_object (prop) { } + ~cdef_property_rep (void) = default; - cdef_property (const cdef_object& obj) - : cdef_meta_object (obj) + cdef_object_rep * copy (void) const { - // This should never happen... - if (! is_property ()) - error ("internal error: invalid assignment from %s to meta.property object", - class_name ().c_str ()); + return new cdef_property_rep (*this); } - cdef_property& operator = (const cdef_property& prop) - { - cdef_object::operator = (prop); + bool is_property (void) const { return true; } - return *this; - } + std::string get_name (void) const { return get("Name").string_value (); } - ~cdef_property (void) = default; + void set_name (const std::string& nm) { put ("Name", nm); } - octave_value get_value (const cdef_object& obj, bool do_check_access = true, - const std::string& who = "") const - { - return get_rep ()->get_value (obj, do_check_access, who); - } + bool is_constant (void) const { return get("Constant").bool_value (); } octave_value get_value (bool do_check_access = true, - const std::string& who = "") const - { - return get_rep ()->get_value (do_check_access, who); - } + const std::string& who = "") const; + + octave_value get_value (const cdef_object& obj, + bool do_check_access = true, + const std::string& who = "") const; void set_value (cdef_object& obj, const octave_value& val, bool do_check_access = true, - const std::string& who = "") - { - get_rep ()->set_value (obj, val, do_check_access, who); - } + const std::string& who = ""); + + OCTINTERP_API bool check_get_access (void) const; + + OCTINTERP_API bool check_set_access (void) const; - bool check_get_access (void) const + private: + cdef_property_rep (const cdef_property_rep& p) + : cdef_meta_object_rep (p) + { } + + OCTINTERP_API bool is_recursive_set (const cdef_object& obj) const; + + cdef_property wrap (void) { - return get_rep ()->check_get_access (); - } - - bool check_set_access (void) const - { - return get_rep ()->check_set_access (); + m_count++; + return cdef_property (this); } - std::string get_name (void) const { return get_rep ()->get_name (); } + OCTINTERP_API OCTAVE_NORETURN + void err_property_access (const std::string& from, + bool is_set = false) const; + }; + +public: + + cdef_property (void) : cdef_meta_object () { } + + cdef_property (const std::string& nm) + : cdef_meta_object (new cdef_property_rep ()) + { + get_rep ()->set_name (nm); + } + + cdef_property (const cdef_property& prop) : cdef_meta_object (prop) { } - bool is_constant (void) const { return get_rep ()->is_constant (); } + cdef_property (const cdef_object& obj) + : cdef_meta_object (obj) + { + // This should never happen... + if (! is_property ()) + error ("internal error: invalid assignment from %s to meta.property object", + class_name ().c_str ()); + } - private: + cdef_property& operator = (const cdef_property& prop) + { + cdef_object::operator = (prop); + + return *this; + } + + ~cdef_property (void) = default; - cdef_property_rep * get_rep (void) - { - return dynamic_cast (cdef_object::get_rep ()); - } + octave_value get_value (const cdef_object& obj, bool do_check_access = true, + const std::string& who = "") const + { + return get_rep ()->get_value (obj, do_check_access, who); + } + + octave_value get_value (bool do_check_access = true, + const std::string& who = "") const + { + return get_rep ()->get_value (do_check_access, who); + } + + void set_value (cdef_object& obj, const octave_value& val, + bool do_check_access = true, + const std::string& who = "") + { + get_rep ()->set_value (obj, val, do_check_access, who); + } - const cdef_property_rep * get_rep (void) const - { - return dynamic_cast (cdef_object::get_rep ()); - } - }; + bool check_get_access (void) const + { + return get_rep ()->check_get_access (); + } + + bool check_set_access (void) const + { + return get_rep ()->check_set_access (); + } + + std::string get_name (void) const { return get_rep ()->get_name (); } + + bool is_constant (void) const { return get_rep ()->is_constant (); } + +private: + + cdef_property_rep * get_rep (void) + { + return dynamic_cast (cdef_object::get_rep ()); + } + + const cdef_property_rep * get_rep (void) const + { + return dynamic_cast (cdef_object::get_rep ()); + } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-utils.cc --- a/libinterp/octave-value/cdef-utils.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-utils.cc Thu Dec 01 20:05:44 2022 -0800 @@ -40,367 +40,367 @@ OCTAVE_BEGIN_NAMESPACE(octave) - std::string - get_base_name (const std::string& nm) - { - std::string::size_type pos = nm.find_last_of ('.'); +std::string +get_base_name (const std::string& nm) +{ + std::string::size_type pos = nm.find_last_of ('.'); - if (pos != std::string::npos) - return nm.substr (pos + 1); + if (pos != std::string::npos) + return nm.substr (pos + 1); - return nm; - } + return nm; +} - void - make_function_of_class (const std::string& class_name, - const octave_value& fcn) - { - octave_function *of = fcn.function_value (); +void +make_function_of_class (const std::string& class_name, + const octave_value& fcn) +{ + octave_function *of = fcn.function_value (); - of->stash_dispatch_class (class_name); + of->stash_dispatch_class (class_name); - octave_user_function *uf = of->user_function_value (true); + octave_user_function *uf = of->user_function_value (true); - if (uf) - { - if (get_base_name (class_name) == uf->name ()) - uf->mark_as_classdef_constructor (); - else - uf->mark_as_classdef_method (); - } - } + if (uf) + { + if (get_base_name (class_name) == uf->name ()) + uf->mark_as_classdef_constructor (); + else + uf->mark_as_classdef_method (); + } +} - void - make_function_of_class (const cdef_class& cls, const octave_value& fcn) - { - make_function_of_class (cls.get_name (), fcn); - } +void +make_function_of_class (const cdef_class& cls, const octave_value& fcn) +{ + make_function_of_class (cls.get_name (), fcn); +} - cdef_class - lookup_class (const std::string& name, bool error_if_not_found, - bool load_if_not_found) - { - cdef_manager& cdm = __get_cdef_manager__ (); +cdef_class +lookup_class (const std::string& name, bool error_if_not_found, + bool load_if_not_found) +{ + cdef_manager& cdm = __get_cdef_manager__ (); - return cdm.find_class (name, error_if_not_found, load_if_not_found); - } + return cdm.find_class (name, error_if_not_found, load_if_not_found); +} - cdef_class - lookup_class (const cdef_class& cls) - { - // FIXME: placeholder for the time being, the purpose - // is to centralized any class update activity here. +cdef_class +lookup_class (const cdef_class& cls) +{ + // FIXME: placeholder for the time being, the purpose + // is to centralized any class update activity here. - return cls; - } + return cls; +} - cdef_class - lookup_class (const octave_value& ov) - { - if (ov.is_string()) - return lookup_class (ov.string_value ()); - else - { - cdef_class cls (to_cdef (ov)); +cdef_class +lookup_class (const octave_value& ov) +{ + if (ov.is_string()) + return lookup_class (ov.string_value ()); + else + { + cdef_class cls (to_cdef (ov)); - return lookup_class (cls); - } + return lookup_class (cls); + } - return cdef_class (); - } + return cdef_class (); +} - std::list - lookup_classes (const Cell& cls_list) - { - std::list retval; +std::list +lookup_classes (const Cell& cls_list) +{ + std::list retval; - for (int i = 0; i < cls_list.numel (); i++) - { - cdef_class c = lookup_class (cls_list(i)); + for (int i = 0; i < cls_list.numel (); i++) + { + cdef_class c = lookup_class (cls_list(i)); - retval.push_back (c); - } + retval.push_back (c); + } - return retval; - } + return retval; +} - octave_value - to_ov (const cdef_object& obj) - { - if (obj.ok ()) - return octave_value (new octave_classdef (obj)); - else - return octave_value (Matrix ()); - } +octave_value +to_ov (const cdef_object& obj) +{ + if (obj.ok ()) + return octave_value (new octave_classdef (obj)); + else + return octave_value (Matrix ()); +} - octave_value - to_ov (const octave_value& ov) - { - return ov; - } +octave_value +to_ov (const octave_value& ov) +{ + return ov; +} - cdef_object - to_cdef (const octave_value& val) - { - if (val.type_name () != "object") - error ("cannot convert '%s' into 'object'", val.type_name().c_str ()); +cdef_object +to_cdef (const octave_value& val) +{ + if (val.type_name () != "object") + error ("cannot convert '%s' into 'object'", val.type_name().c_str ()); - return dynamic_cast (val.internal_rep ())->get_object (); - } + return dynamic_cast (val.internal_rep ())->get_object (); +} - cdef_object& - to_cdef_ref (const octave_value& val) - { - if (val.type_name () != "object") - error ("cannot convert '%s' into 'object'", val.type_name().c_str ()); +cdef_object& +to_cdef_ref (const octave_value& val) +{ + if (val.type_name () != "object") + error ("cannot convert '%s' into 'object'", val.type_name().c_str ()); - return dynamic_cast (val.internal_rep ())->get_object_ref (); - } + return dynamic_cast (val.internal_rep ())->get_object_ref (); +} - cdef_object - to_cdef (const cdef_object& obj) - { - return obj; - } +cdef_object +to_cdef (const cdef_object& obj) +{ + return obj; +} - octave_value - to_ov (const std::list& class_list) - { - Cell cls (class_list.size (), 1); - int i = 0; +octave_value +to_ov (const std::list& class_list) +{ + Cell cls (class_list.size (), 1); + int i = 0; - for (const auto& cdef_cls : class_list) - cls(i++) = to_ov (cdef_cls); + for (const auto& cdef_cls : class_list) + cls(i++) = to_ov (cdef_cls); - return octave_value (cls); - } + return octave_value (cls); +} - bool - is_dummy_method (const octave_value& fcn) - { - bool retval = false; +bool +is_dummy_method (const octave_value& fcn) +{ + bool retval = false; - if (fcn.is_defined ()) - { - if (fcn.is_user_function ()) - { - octave_user_function *uf = fcn.user_function_value (true); + if (fcn.is_defined ()) + { + if (fcn.is_user_function ()) + { + octave_user_function *uf = fcn.user_function_value (true); - if (! uf || ! uf->body ()) - retval = true; - } - } - else - retval = true; + if (! uf || ! uf->body ()) + retval = true; + } + } + else + retval = true; - return retval; - } + return retval; +} - bool - is_superclass (const cdef_class& clsa, const cdef_class& clsb, - bool allow_equal, int max_depth) - { - bool retval = false; +bool +is_superclass (const cdef_class& clsa, const cdef_class& clsb, + bool allow_equal, int max_depth) +{ + bool retval = false; - if (allow_equal && clsa == clsb) - retval = true; - else if (max_depth != 0) - { - Cell c = clsb.get ("SuperClasses").cell_value (); + if (allow_equal && clsa == clsb) + retval = true; + else if (max_depth != 0) + { + Cell c = clsb.get ("SuperClasses").cell_value (); - for (int i = 0; ! retval && i < c.numel (); i++) - { - octave_classdef *metacls = c(i).classdef_object_value (); - std::string clsname = metacls->get_property (0, "Name").string_value (); - cdef_class cls = lookup_class (clsname); + for (int i = 0; ! retval && i < c.numel (); i++) + { + octave_classdef *metacls = c(i).classdef_object_value (); + std::string clsname = metacls->get_property (0, "Name").string_value (); + cdef_class cls = lookup_class (clsname); - retval = is_superclass (clsa, cls, true, - max_depth < 0 ? max_depth : max_depth-1); - } - } + retval = is_superclass (clsa, cls, true, + max_depth < 0 ? max_depth : max_depth-1); + } + } - return retval; - } + return retval; +} - bool - is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb) - { - return is_superclass (clsa, clsb, false); - } +bool +is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb) +{ + return is_superclass (clsa, clsb, false); +} - bool - is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb) - { - return is_superclass (clsa, clsb, false, 1); - } +bool +is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb) +{ + return is_superclass (clsa, clsb, false, 1); +} - cdef_package - lookup_package (const std::string& name, bool error_if_not_found, - bool load_if_not_found) - { - cdef_manager& cdm = __get_cdef_manager__ (); +cdef_package +lookup_package (const std::string& name, bool error_if_not_found, + bool load_if_not_found) +{ + cdef_manager& cdm = __get_cdef_manager__ (); - return cdm.find_package (name, error_if_not_found, load_if_not_found); - } + return cdm.find_package (name, error_if_not_found, load_if_not_found); +} - cdef_class - get_class_context (std::string& name, bool& in_constructor) - { - name = ""; - in_constructor = false; +cdef_class +get_class_context (std::string& name, bool& in_constructor) +{ + name = ""; + in_constructor = false; - cdef_class cls; + cdef_class cls; - // If the dispatch class is set in the current stack frame it - // overrides whatever dispatch class there is for the currently - // executing function so that function handles returned from class - // methods will use the dispatch class of the class in which they - // are defined instead of the class in which they are executing. + // If the dispatch class is set in the current stack frame it + // overrides whatever dispatch class there is for the currently + // executing function so that function handles returned from class + // methods will use the dispatch class of the class in which they + // are defined instead of the class in which they are executing. - tree_evaluator& tw = __get_evaluator__ (); + tree_evaluator& tw = __get_evaluator__ (); - std::string dispatch_class = tw.get_dispatch_class (); + std::string dispatch_class = tw.get_dispatch_class (); - if (! dispatch_class.empty ()) - return lookup_class (dispatch_class); + if (! dispatch_class.empty ()) + return lookup_class (dispatch_class); - octave_function *fcn = tw.current_function (); + octave_function *fcn = tw.current_function (); - if (fcn && (fcn->is_class_method () - || fcn->is_classdef_constructor () - || fcn->is_anonymous_function_of_class () - || (fcn->is_private_function () - && ! fcn->dispatch_class ().empty ()))) - { - cls = lookup_class (fcn->dispatch_class ()); + if (fcn && (fcn->is_class_method () + || fcn->is_classdef_constructor () + || fcn->is_anonymous_function_of_class () + || (fcn->is_private_function () + && ! fcn->dispatch_class ().empty ()))) + { + cls = lookup_class (fcn->dispatch_class ()); - name = fcn->name (); - in_constructor = fcn->is_classdef_constructor (); - } + name = fcn->name (); + in_constructor = fcn->is_classdef_constructor (); + } - return cls; - } + return cls; +} - cdef_class - get_class_context (void) - { - std::string dummy_string; - bool dummy_bool; +cdef_class +get_class_context (void) +{ + std::string dummy_string; + bool dummy_bool; - return get_class_context (dummy_string, dummy_bool); - } + return get_class_context (dummy_string, dummy_bool); +} - bool - check_access (const cdef_class& cls, const octave_value& acc, - const std::string& meth_name, const std::string& prop_name, - bool is_prop_set) - { - if (acc.is_string ()) - { - std::string acc_s = acc.string_value (); +bool +check_access (const cdef_class& cls, const octave_value& acc, + const std::string& meth_name, const std::string& prop_name, + bool is_prop_set) +{ + if (acc.is_string ()) + { + std::string acc_s = acc.string_value (); - if (acc_s == "public") - return true; + if (acc_s == "public") + return true; - cdef_class ctx = get_class_context (); + cdef_class ctx = get_class_context (); - // The access is private or protected, this requires a - // valid class context. + // The access is private or protected, this requires a + // valid class context. - if (ctx.ok ()) - { - if (acc_s == "private") - return (ctx == cls); - else if (acc_s == "protected") - { - if (is_superclass (cls, ctx)) - // Calling a protected method in a superclass. - return true; - else if (is_strict_superclass (ctx, cls)) - { - // Calling a protected method or property in a derived - // class. This is only allowed if the context class knows - // about it and has access to it. + if (ctx.ok ()) + { + if (acc_s == "private") + return (ctx == cls); + else if (acc_s == "protected") + { + if (is_superclass (cls, ctx)) + // Calling a protected method in a superclass. + return true; + else if (is_strict_superclass (ctx, cls)) + { + // Calling a protected method or property in a derived + // class. This is only allowed if the context class knows + // about it and has access to it. - if (! meth_name.empty ()) - { - cdef_method m = ctx.find_method (meth_name); + if (! meth_name.empty ()) + { + cdef_method m = ctx.find_method (meth_name); - if (m.ok ()) - return check_access (ctx, - m.get ("Access"), meth_name); + if (m.ok ()) + return check_access (ctx, + m.get ("Access"), meth_name); - return false; - } - else if (! prop_name.empty ()) - { - cdef_property p = ctx.find_property (prop_name); + return false; + } + else if (! prop_name.empty ()) + { + cdef_property p = ctx.find_property (prop_name); - if (p.ok ()) - { - octave_value p_access = p.get (is_prop_set ? - "SetAccess" : - "GetAccess"); + if (p.ok ()) + { + octave_value p_access = p.get (is_prop_set ? + "SetAccess" : + "GetAccess"); - return check_access (ctx, p_access, meth_name, - prop_name, is_prop_set); - } + return check_access (ctx, p_access, meth_name, + prop_name, is_prop_set); + } - return false; - } - else - panic_impossible (); - } + return false; + } + else + panic_impossible (); + } - return false; - } - else - panic_impossible (); - } - } - else if (acc.isobject ()) - { - cdef_class ctx = get_class_context (); + return false; + } + else + panic_impossible (); + } + } + else if (acc.isobject ()) + { + cdef_class ctx = get_class_context (); - // At this point, a class context is always required. - if (ctx.ok ()) - { - if (ctx == cls) - return true; + // At this point, a class context is always required. + if (ctx.ok ()) + { + if (ctx == cls) + return true; - cdef_class acc_cls (to_cdef (acc)); + cdef_class acc_cls (to_cdef (acc)); - if (is_superclass (acc_cls, ctx)) - return true; - } - } - else if (acc.iscell ()) - { - Cell acc_c = acc.cell_value (); + if (is_superclass (acc_cls, ctx)) + return true; + } + } + else if (acc.iscell ()) + { + Cell acc_c = acc.cell_value (); - cdef_class ctx = get_class_context (); + cdef_class ctx = get_class_context (); - // At this point, a class context is always required. + // At this point, a class context is always required. - if (ctx.ok ()) - { - if (ctx == cls) - return true; + if (ctx.ok ()) + { + if (ctx == cls) + return true; - for (int i = 0; i < acc.numel (); i++) - { - cdef_class acc_cls (to_cdef (acc_c(i))); + for (int i = 0; i < acc.numel (); i++) + { + cdef_class acc_cls (to_cdef (acc_c(i))); - if (is_superclass (acc_cls, ctx)) - return true; - } - } - } - else - error ("invalid property/method access in class '%s'", - cls.get_name ().c_str ()); + if (is_superclass (acc_cls, ctx)) + return true; + } + } + } + else + error ("invalid property/method access in class '%s'", + cls.get_name ().c_str ()); - return false; - } + return false; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/cdef-utils.h --- a/libinterp/octave-value/cdef-utils.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/cdef-utils.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,74 +38,74 @@ OCTAVE_BEGIN_NAMESPACE(octave) - extern OCTINTERP_API std::string - get_base_name (const std::string& nm); +extern OCTINTERP_API std::string +get_base_name (const std::string& nm); + +extern OCTINTERP_API void +make_function_of_class (const std::string& class_name, + const octave_value& fcn); + +extern OCTINTERP_API void +make_function_of_class (const cdef_class& cls, const octave_value& fcn); + +extern OCTINTERP_API cdef_class +lookup_class (const std::string& name, bool error_if_not_found = true, + bool load_if_not_found = true); + +extern OCTINTERP_API cdef_class +lookup_class (const cdef_class& cls); + +extern OCTINTERP_API cdef_class +lookup_class (const octave_value& ov); + +extern OCTINTERP_API std::list +lookup_classes (const Cell& cls_list); + +extern OCTINTERP_API octave_value +to_ov (const cdef_object& obj); - extern OCTINTERP_API void - make_function_of_class (const std::string& class_name, - const octave_value& fcn); +extern OCTINTERP_API octave_value +to_ov (const octave_value& ov); + +extern OCTINTERP_API cdef_object +to_cdef (const octave_value& val); + +extern OCTINTERP_API cdef_object& +to_cdef_ref (const octave_value& val); + +extern OCTINTERP_API cdef_object +to_cdef (const cdef_object& obj); + +extern OCTINTERP_API octave_value +to_ov (const std::list& class_list); - extern OCTINTERP_API void - make_function_of_class (const cdef_class& cls, const octave_value& fcn); +extern OCTINTERP_API bool +is_dummy_method (const octave_value& fcn); - extern OCTINTERP_API cdef_class - lookup_class (const std::string& name, bool error_if_not_found = true, +extern OCTINTERP_API bool +is_superclass (const cdef_class& clsa, const cdef_class& clsb, + bool allow_equal = true, int max_depth = -1); +extern OCTINTERP_API bool +is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb); + +extern OCTINTERP_API bool +is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb); + +extern OCTINTERP_API cdef_package +lookup_package (const std::string& name, bool error_if_not_found = true, bool load_if_not_found = true); - extern OCTINTERP_API cdef_class - lookup_class (const cdef_class& cls); - - extern OCTINTERP_API cdef_class - lookup_class (const octave_value& ov); - - extern OCTINTERP_API std::list - lookup_classes (const Cell& cls_list); - - extern OCTINTERP_API octave_value - to_ov (const cdef_object& obj); +extern OCTINTERP_API cdef_class +get_class_context (std::string& name, bool& in_constructor); - extern OCTINTERP_API octave_value - to_ov (const octave_value& ov); - - extern OCTINTERP_API cdef_object - to_cdef (const octave_value& val); - - extern OCTINTERP_API cdef_object& - to_cdef_ref (const octave_value& val); - - extern OCTINTERP_API cdef_object - to_cdef (const cdef_object& obj); - - extern OCTINTERP_API octave_value - to_ov (const std::list& class_list); +extern OCTINTERP_API cdef_class +get_class_context (void); - extern OCTINTERP_API bool - is_dummy_method (const octave_value& fcn); - - extern OCTINTERP_API bool - is_superclass (const cdef_class& clsa, const cdef_class& clsb, - bool allow_equal = true, int max_depth = -1); - extern OCTINTERP_API bool - is_strict_superclass (const cdef_class& clsa, const cdef_class& clsb); - - extern OCTINTERP_API bool - is_direct_superclass (const cdef_class& clsa, const cdef_class& clsb); - - extern OCTINTERP_API cdef_package - lookup_package (const std::string& name, bool error_if_not_found = true, - bool load_if_not_found = true); - - extern OCTINTERP_API cdef_class - get_class_context (std::string& name, bool& in_constructor); - - extern OCTINTERP_API cdef_class - get_class_context (void); - - extern OCTINTERP_API bool - check_access (const cdef_class& cls, const octave_value& acc, - const std::string& meth_name = "", - const std::string& prop_name = "", - bool is_prop_set = false); +extern OCTINTERP_API bool +check_access (const cdef_class& cls, const octave_value& acc, + const std::string& meth_name = "", + const std::string& prop_name = "", + bool is_prop_set = false); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base-diag.cc --- a/libinterp/octave-value/ov-base-diag.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base-diag.cc Thu Dec 01 20:05:44 2022 -0800 @@ -466,7 +466,7 @@ template octave_value octave_base_diag::convert_to_str_internal (bool pad, bool force, - char type) const + char type) const { return to_dense ().convert_to_str_internal (pad, force, type); } @@ -482,8 +482,8 @@ template std::string octave_base_diag::edit_display (const float_display_format& fmt, - octave_idx_type i, - octave_idx_type j) const + octave_idx_type i, + octave_idx_type j) const { std::ostringstream buf; octave_print_internal (buf, fmt, m_matrix(i, j)); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base-int.cc --- a/libinterp/octave-value/ov-base-int.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base-int.cc Thu Dec 01 20:05:44 2022 -0800 @@ -150,7 +150,7 @@ if (this->m_matrix.numel () == 1) retval = new typename octave_value_int_traits::scalar_type - (this->m_matrix (0)); + (this->m_matrix (0)); return retval; } @@ -276,8 +276,8 @@ template std::string octave_base_int_matrix::edit_display (const float_display_format& fmt, - octave_idx_type i, - octave_idx_type j) const + octave_idx_type i, + octave_idx_type j) const { std::ostringstream buf; octave_print_internal (buf, fmt, this->m_matrix(i, j)); @@ -426,8 +426,8 @@ template bool octave_base_int_matrix::save_hdf5_internal (octave_hdf5_id loc_id, - octave_hdf5_id save_type, - const char *name, bool) + octave_hdf5_id save_type, + const char *name, bool) { bool retval = false; @@ -485,8 +485,8 @@ template bool octave_base_int_matrix::load_hdf5_internal (octave_hdf5_id loc_id, - octave_hdf5_id save_type, - const char *name) + octave_hdf5_id save_type, + const char *name) { bool retval = false; @@ -670,8 +670,8 @@ template std::string octave_base_int_scalar::edit_display (const float_display_format& fmt, - octave_idx_type, - octave_idx_type) const + octave_idx_type, + octave_idx_type) const { std::ostringstream buf; octave_print_internal (buf, fmt, this->scalar); @@ -726,8 +726,8 @@ template bool octave_base_int_scalar::save_hdf5_internal (octave_hdf5_id loc_id, - octave_hdf5_id save_type, - const char *name, bool) + octave_hdf5_id save_type, + const char *name, bool) { bool retval = false; @@ -775,8 +775,8 @@ template bool octave_base_int_scalar::load_hdf5_internal (octave_hdf5_id loc_id, - octave_hdf5_id save_type, - const char *name) + octave_hdf5_id save_type, + const char *name) { #if defined (HAVE_HDF5) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base-mat.cc --- a/libinterp/octave-value/ov-base-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -552,7 +552,7 @@ template bool octave_base_matrix::fast_elem_insert (octave_idx_type n, - const octave_value& x) + const octave_value& x) { if (n < m_matrix.numel ()) { diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base-mat.h --- a/libinterp/octave-value/ov-base-mat.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base-mat.h Thu Dec 01 20:05:44 2022 -0800 @@ -68,7 +68,7 @@ : octave_base_value (), m_matrix (m.m_matrix), m_typ (m.m_typ ? new MatrixType (*m.m_typ) : nullptr), m_idx_cache (m.m_idx_cache ? new octave::idx_vector (*m.m_idx_cache) - : nullptr) + : nullptr) { } ~octave_base_matrix (void) { clear_cached_info (); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base-scalar.cc --- a/libinterp/octave-value/ov-base-scalar.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base-scalar.cc Thu Dec 01 20:05:44 2022 -0800 @@ -219,7 +219,7 @@ template bool octave_base_scalar::fast_elem_insert_self (void *where, - builtin_type_t btyp) const + builtin_type_t btyp) const { // Don't use builtin_type () here to avoid an extra VM call. diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base.cc Thu Dec 01 20:05:44 2022 -0800 @@ -395,7 +395,7 @@ octave_base_value::convert_to_row_or_column_vector (void) { err_wrong_type_arg - ("octave_base_value::convert_to_row_or_column_vector ()", type_name ()); + ("octave_base_value::convert_to_row_or_column_vector ()", type_name ()); } void @@ -1056,7 +1056,7 @@ } octave_value -octave_base_value::sort (Array &, +octave_base_value::sort (Array&, octave_idx_type, sortmode) const { err_wrong_type_arg ("octave_base_value::sort ()", type_name ()); @@ -1157,18 +1157,18 @@ octave_base_value::warn_load (const char *type) const { warning_with_id - ("Octave:load-save-unavailable", - "%s: loading %s files not available in this version of Octave", - t_name.c_str (), type); + ("Octave:load-save-unavailable", + "%s: loading %s files not available in this version of Octave", + t_name.c_str (), type); } void octave_base_value::warn_save (const char *type) const { warning_with_id - ("Octave:load-save-unavailable", - "%s: saving %s files not available in this version of Octave", - t_name.c_str (), type); + ("Octave:load-save-unavailable", + "%s: saving %s files not available in this version of Octave", + t_name.c_str (), type); } void @@ -1199,9 +1199,10 @@ octave_base_value::dump (void) const { std::map m - = {{ "class", this->class_name () }, - { "type", this->type_name () }, - { "dims", this->dims().as_array () }}; + = {{ "class", this->class_name () }, + { "type", this->type_name () }, + { "dims", this->dims().as_array () } + }; return octave_value (m); } @@ -1308,7 +1309,7 @@ && (ti.lookup_assign_op (octave_value::op_asn_eq, cf_this.type_id (), t_rhs) || ti.lookup_pref_assign_conv (cf_this.type_id (), - t_rhs) >= 0)) + t_rhs) >= 0)) cf_rhs = nullptr; if (cf_rhs) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-base.h Thu Dec 01 20:05:44 2022 -0800 @@ -46,21 +46,21 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class stack_frame; - class type_info; +class stack_frame; +class type_info; - // FIXME: This is not ideal, but it avoids including - // interpreter-private.h here and bringing in a lot of unnecessary - // symbols that require even more header files. Since the typeinfo - // object is required to load a user-defined octave_value object, - // maybe this function should be declared in a public header file? +// FIXME: This is not ideal, but it avoids including +// interpreter-private.h here and bringing in a lot of unnecessary +// symbols that require even more header files. Since the typeinfo +// object is required to load a user-defined octave_value object, +// maybe this function should be declared in a public header file? - extern OCTINTERP_API type_info& __get_type_info__ (void); +extern OCTINTERP_API type_info& __get_type_info__ (void); - // For now just preserve the old interface and don't mark it as deprecated. - // This function is currently an internal, private function. Additional - // changes may be made before version 8 is finally released. - inline type_info& __get_type_info__ (const std::string&) { return __get_type_info__ (); } +// For now just preserve the old interface and don't mark it as deprecated. +// This function is currently an internal, private function. Additional +// changes may be made before version 8 is finally released. +inline type_info& __get_type_info__ (const std::string&) { return __get_type_info__ (); } OCTAVE_END_NAMESPACE(octave) @@ -239,7 +239,7 @@ { public: - typedef octave_base_value * (*type_conv_fcn) (const octave_base_value&); + typedef octave_base_value *(*type_conv_fcn) (const octave_base_value&); // type conversion, including result type information class type_conv_info diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-bool-mat.cc --- a/libinterp/octave-value/ov-bool-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-bool-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -82,7 +82,7 @@ octave_bool_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } octave_base_value * @@ -160,7 +160,7 @@ octave_value octave_bool_matrix::convert_to_str_internal (bool pad, bool force, - char type) const + char type) const { octave_value tmp = octave_value (array_value ()); return tmp.convert_to_str (pad, force, type); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-bool-mat.h --- a/libinterp/octave-value/ov-bool-mat.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-bool-mat.h Thu Dec 01 20:05:44 2022 -0800 @@ -92,7 +92,7 @@ octave::idx_vector index_vector (bool /* require_integers */ = false) const { return m_idx_cache ? *m_idx_cache - : set_idx_cache (octave::idx_vector (m_matrix)); + : set_idx_cache (octave::idx_vector (m_matrix)); } builtin_type_t builtin_type (void) const { return btyp_bool; } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-bool-sparse.cc --- a/libinterp/octave-value/ov-bool-sparse.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-bool-sparse.cc Thu Dec 01 20:05:44 2022 -0800 @@ -70,7 +70,7 @@ octave_sparse_bool_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_sparse_matrix::static_type_id ()); + octave_sparse_matrix::static_type_id ()); } double @@ -101,7 +101,7 @@ octave_value octave_sparse_bool_matrix::convert_to_str_internal (bool pad, bool force, - char type) const + char type) const { octave_value tmp = octave_value (array_value ()); return tmp.convert_to_str (pad, force, type); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-bool.cc --- a/libinterp/octave-value/ov-bool.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-bool.cc Thu Dec 01 20:05:44 2022 -0800 @@ -72,7 +72,7 @@ octave_bool::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_scalar::static_type_id ()); + octave_scalar::static_type_id ()); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-builtin.h --- a/libinterp/octave-value/ov-builtin.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-builtin.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,8 +40,8 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; - class interpreter; +class tree_evaluator; +class interpreter; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-cell.cc --- a/libinterp/octave-value/ov-cell.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-cell.cc Thu Dec 01 20:05:44 2022 -0800 @@ -129,7 +129,7 @@ template <> bool octave_base_matrix::fast_elem_insert (octave_idx_type n, - const octave_value& x) + const octave_value& x) { const octave_cell *xrep = dynamic_cast (&x.get_rep ()); @@ -1336,10 +1336,11 @@ return ovl (args(0)); else { - string_vector s = args(0).xstring_vector_value ("cellstr: argument STRING must be a 2-D character array"); + string_vector s = args( + 0).xstring_vector_value ("cellstr: argument STRING must be a 2-D character array"); return ovl (s.isempty () ? Cell (octave_value ("")) - : Cell (s, true)); + : Cell (s, true)); } } @@ -1455,20 +1456,20 @@ case umap_ ## UMAP: \ return m_matrix.UMAP () - FORWARD_MAPPER (xisalnum); - FORWARD_MAPPER (xisalpha); - FORWARD_MAPPER (xisascii); - FORWARD_MAPPER (xiscntrl); - FORWARD_MAPPER (xisdigit); - FORWARD_MAPPER (xisgraph); - FORWARD_MAPPER (xislower); - FORWARD_MAPPER (xisprint); - FORWARD_MAPPER (xispunct); - FORWARD_MAPPER (xisspace); - FORWARD_MAPPER (xisupper); - FORWARD_MAPPER (xisxdigit); - FORWARD_MAPPER (xtolower); - FORWARD_MAPPER (xtoupper); + FORWARD_MAPPER (xisalnum); + FORWARD_MAPPER (xisalpha); + FORWARD_MAPPER (xisascii); + FORWARD_MAPPER (xiscntrl); + FORWARD_MAPPER (xisdigit); + FORWARD_MAPPER (xisgraph); + FORWARD_MAPPER (xislower); + FORWARD_MAPPER (xisprint); + FORWARD_MAPPER (xispunct); + FORWARD_MAPPER (xisspace); + FORWARD_MAPPER (xisupper); + FORWARD_MAPPER (xisxdigit); + FORWARD_MAPPER (xtolower); + FORWARD_MAPPER (xtoupper); default: return octave_base_value::map (umap); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-ch-mat.cc --- a/libinterp/octave-value/ov-ch-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-ch-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -263,7 +263,7 @@ case umap_ ## UMAP: \ return octave_value (m_matrix.map (FCN)) - STRING_MAPPER (xisascii, xisascii, bool); + STRING_MAPPER (xisascii, xisascii, bool); #define STRING_U8_MAPPER(UMAP,FCN) \ case umap_ ## UMAP: \ @@ -295,17 +295,17 @@ : b_array); \ } - STRING_U8_MAPPER (xisalnum, octave_uc_is_alnum_wrapper); - STRING_U8_MAPPER (xisalpha, octave_uc_is_alpha_wrapper); - STRING_U8_MAPPER (xiscntrl, octave_uc_is_cntrl_wrapper); - STRING_U8_MAPPER (xisdigit, octave_uc_is_digit_wrapper); - STRING_U8_MAPPER (xisgraph, octave_uc_is_graph_wrapper); - STRING_U8_MAPPER (xislower, octave_uc_is_lower_wrapper); - STRING_U8_MAPPER (xisprint, octave_uc_is_print_wrapper); - STRING_U8_MAPPER (xispunct, octave_uc_is_punct_wrapper); - STRING_U8_MAPPER (xisspace, octave_uc_is_space_wrapper); - STRING_U8_MAPPER (xisupper, octave_uc_is_upper_wrapper); - STRING_U8_MAPPER (xisxdigit, octave_uc_is_xdigit_wrapper); + STRING_U8_MAPPER (xisalnum, octave_uc_is_alnum_wrapper); + STRING_U8_MAPPER (xisalpha, octave_uc_is_alpha_wrapper); + STRING_U8_MAPPER (xiscntrl, octave_uc_is_cntrl_wrapper); + STRING_U8_MAPPER (xisdigit, octave_uc_is_digit_wrapper); + STRING_U8_MAPPER (xisgraph, octave_uc_is_graph_wrapper); + STRING_U8_MAPPER (xislower, octave_uc_is_lower_wrapper); + STRING_U8_MAPPER (xisprint, octave_uc_is_print_wrapper); + STRING_U8_MAPPER (xispunct, octave_uc_is_punct_wrapper); + STRING_U8_MAPPER (xisspace, octave_uc_is_space_wrapper); + STRING_U8_MAPPER (xisupper, octave_uc_is_upper_wrapper); + STRING_U8_MAPPER (xisxdigit, octave_uc_is_xdigit_wrapper); #define STRING_U8_FCN(UMAP,U8_FCN,STD_FCN) \ case umap_ ## UMAP: \ @@ -335,8 +335,8 @@ : ch_array); \ } - STRING_U8_FCN (xtolower, octave_u8_tolower_wrapper, std::tolower); - STRING_U8_FCN (xtoupper, octave_u8_toupper_wrapper, std::toupper); + STRING_U8_FCN (xtolower, octave_u8_tolower_wrapper, std::tolower); + STRING_U8_FCN (xtoupper, octave_u8_toupper_wrapper, std::toupper); // For Matlab compatibility, these should work on ASCII values // without error or warning. diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-class.cc --- a/libinterp/octave-value/ov-class.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-class.cc Thu Dec 01 20:05:44 2022 -0800 @@ -407,7 +407,7 @@ Cell t = tmp.index (idx.front ()); retval(0) = (t.numel () == 1 ? t(0) - : octave_value (t, true)); + : octave_value (t, true)); // We handled two index elements, so tell // next_subsref to skip both of them. @@ -1223,7 +1223,8 @@ if (! is) break; - Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (t2)); + Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell ( + t2)); m.assign (nm, tcell); } @@ -1347,7 +1348,8 @@ if (! is) break; - Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (t2)); + Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell ( + t2)); m.assign (nm, tcell); } @@ -1595,7 +1597,8 @@ { octave_value t2 = dsub.tc; - Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell (t2)); + Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading class elements") : Cell ( + t2)); m.assign (dsub.name, tcell); @@ -1821,7 +1824,8 @@ octave_value obj = args(0); // not const because of find_parent_class () std::string obj_cls = obj.class_name (); - Array clsnames = args(1).xcellstr_value ("isa: CLASSNAME must be a string or cell array of strings"); + Array clsnames = args( + 1).xcellstr_value ("isa: CLASSNAME must be a string or cell array of strings"); boolNDArray matches (clsnames.dims (), false); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-class.h --- a/libinterp/octave-value/ov-class.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-class.h Thu Dec 01 20:05:44 2022 -0800 @@ -42,7 +42,7 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class type_info; +class type_info; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-classdef.cc --- a/libinterp/octave-value/ov-classdef.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-classdef.cc Thu Dec 01 20:05:44 2022 -0800 @@ -259,9 +259,9 @@ octave::tree_evaluator& tw = interp.get_evaluator(); octave::unwind_action act ([&tw] (const std::list *lvl) - { - tw.set_lvalue_list (lvl); - }, tw.lvalue_list ()); + { + tw.set_lvalue_list (lvl); + }, tw.lvalue_list ()); tw.set_lvalue_list (nullptr); octave_value_list lv = meth.execute (args, 1, true, "numel"); @@ -473,8 +473,8 @@ octave_value_list octave_classdef_superclass_ref::execute (octave::tree_evaluator& tw, - int nargout, - const octave_value_list& idx) + int nargout, + const octave_value_list& idx) { octave_value_list retval; @@ -579,7 +579,7 @@ } bool octave_classdef_superclass_ref::is_constructed_object (octave::tree_evaluator& tw, - const std::string& nm) + const std::string& nm) { octave_function *of = tw.current_function (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-classdef.h --- a/libinterp/octave-value/ov-classdef.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-classdef.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,10 +36,10 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class cdef_object; - class interpreter; - class tree_evaluator; - class type_info; +class cdef_object; +class interpreter; +class tree_evaluator; +class type_info; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-complex.cc --- a/libinterp/octave-value/ov-complex.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-complex.cc Thu Dec 01 20:05:44 2022 -0800 @@ -67,33 +67,33 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Complain if a complex value is used as a subscript. +// Complain if a complex value is used as a subscript. - class complex_index_exception : public index_exception - { - public: +class complex_index_exception : public index_exception +{ +public: - complex_index_exception (const std::string& value) - : index_exception (value) - { - // Virtual, but the one we want to call is defined in this class. - update_message (); - } + complex_index_exception (const std::string& value) + : index_exception (value) + { + // Virtual, but the one we want to call is defined in this class. + update_message (); + } - ~complex_index_exception (void) = default; + ~complex_index_exception (void) = default; - void update_message (void) - { - set_message (expression () - + ": subscripts must be real (forgot to initialize i or j?)"); - } + void update_message (void) + { + set_message (expression () + + ": subscripts must be real (forgot to initialize i or j?)"); + } - // ID of error to throw. - const char * err_id (void) const - { - return "Octave:invalid-index"; - } - }; + // ID of error to throw. + const char * err_id (void) const + { + return "Octave:invalid-index"; + } +}; OCTAVE_END_NAMESPACE(octave) @@ -507,46 +507,46 @@ case umap_ ## UMAP: \ return octave_value (FCN (scalar)) - SCALAR_MAPPER (abs, std::abs); - SCALAR_MAPPER (acos, octave::math::acos); - SCALAR_MAPPER (acosh, octave::math::acosh); - SCALAR_MAPPER (angle, std::arg); - SCALAR_MAPPER (arg, std::arg); - SCALAR_MAPPER (asin, octave::math::asin); - SCALAR_MAPPER (asinh, octave::math::asinh); - SCALAR_MAPPER (atan, octave::math::atan); - SCALAR_MAPPER (atanh, octave::math::atanh); - SCALAR_MAPPER (erf, octave::math::erf); - SCALAR_MAPPER (erfc, octave::math::erfc); - SCALAR_MAPPER (erfcx, octave::math::erfcx); - SCALAR_MAPPER (erfi, octave::math::erfi); - SCALAR_MAPPER (dawson, octave::math::dawson); - SCALAR_MAPPER (ceil, octave::math::ceil); - SCALAR_MAPPER (conj, std::conj); - SCALAR_MAPPER (cos, std::cos); - SCALAR_MAPPER (cosh, std::cosh); - SCALAR_MAPPER (exp, std::exp); - SCALAR_MAPPER (expm1, octave::math::expm1); - SCALAR_MAPPER (fix, octave::math::fix); - SCALAR_MAPPER (floor, octave::math::floor); - SCALAR_MAPPER (imag, std::imag); - SCALAR_MAPPER (log, std::log); - SCALAR_MAPPER (log2, octave::math::log2); - SCALAR_MAPPER (log10, std::log10); - SCALAR_MAPPER (log1p, octave::math::log1p); - SCALAR_MAPPER (real, std::real); - SCALAR_MAPPER (round, octave::math::round); - SCALAR_MAPPER (roundb, octave::math::roundb); - SCALAR_MAPPER (signum, octave::math::signum); - SCALAR_MAPPER (sin, std::sin); - SCALAR_MAPPER (sinh, std::sinh); - SCALAR_MAPPER (sqrt, std::sqrt); - SCALAR_MAPPER (tan, std::tan); - SCALAR_MAPPER (tanh, std::tanh); - SCALAR_MAPPER (isfinite, octave::math::isfinite); - SCALAR_MAPPER (isinf, octave::math::isinf); - SCALAR_MAPPER (isna, octave::math::isna); - SCALAR_MAPPER (isnan, octave::math::isnan); + SCALAR_MAPPER (abs, std::abs); + SCALAR_MAPPER (acos, octave::math::acos); + SCALAR_MAPPER (acosh, octave::math::acosh); + SCALAR_MAPPER (angle, std::arg); + SCALAR_MAPPER (arg, std::arg); + SCALAR_MAPPER (asin, octave::math::asin); + SCALAR_MAPPER (asinh, octave::math::asinh); + SCALAR_MAPPER (atan, octave::math::atan); + SCALAR_MAPPER (atanh, octave::math::atanh); + SCALAR_MAPPER (erf, octave::math::erf); + SCALAR_MAPPER (erfc, octave::math::erfc); + SCALAR_MAPPER (erfcx, octave::math::erfcx); + SCALAR_MAPPER (erfi, octave::math::erfi); + SCALAR_MAPPER (dawson, octave::math::dawson); + SCALAR_MAPPER (ceil, octave::math::ceil); + SCALAR_MAPPER (conj, std::conj); + SCALAR_MAPPER (cos, std::cos); + SCALAR_MAPPER (cosh, std::cosh); + SCALAR_MAPPER (exp, std::exp); + SCALAR_MAPPER (expm1, octave::math::expm1); + SCALAR_MAPPER (fix, octave::math::fix); + SCALAR_MAPPER (floor, octave::math::floor); + SCALAR_MAPPER (imag, std::imag); + SCALAR_MAPPER (log, std::log); + SCALAR_MAPPER (log2, octave::math::log2); + SCALAR_MAPPER (log10, std::log10); + SCALAR_MAPPER (log1p, octave::math::log1p); + SCALAR_MAPPER (real, std::real); + SCALAR_MAPPER (round, octave::math::round); + SCALAR_MAPPER (roundb, octave::math::roundb); + SCALAR_MAPPER (signum, octave::math::signum); + SCALAR_MAPPER (sin, std::sin); + SCALAR_MAPPER (sinh, std::sinh); + SCALAR_MAPPER (sqrt, std::sqrt); + SCALAR_MAPPER (tan, std::tan); + SCALAR_MAPPER (tanh, std::tanh); + SCALAR_MAPPER (isfinite, octave::math::isfinite); + SCALAR_MAPPER (isinf, octave::math::isinf); + SCALAR_MAPPER (isna, octave::math::isna); + SCALAR_MAPPER (isnan, octave::math::isnan); // Special cases for Matlab compatibility. case umap_xtolower: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-cx-diag.cc --- a/libinterp/octave-value/ov-cx-diag.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-cx-diag.cc Thu Dec 01 20:05:44 2022 -0800 @@ -56,8 +56,8 @@ octave_complex_diag_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info - (default_numeric_conversion_function, - octave_complex_matrix::static_type_id ()); + (default_numeric_conversion_function, + octave_complex_matrix::static_type_id ()); } static octave_base_value * @@ -67,7 +67,7 @@ = dynamic_cast (a); return new octave_float_complex_diag_matrix - (v.float_complex_diag_matrix_value ()); + (v.float_complex_diag_matrix_value ()); } octave_base_value::type_conv_info @@ -216,7 +216,7 @@ bool octave_complex_diag_matrix::load_binary (std::istream& is, bool swap, - octave::mach_info::float_format fmt) + octave::mach_info::float_format fmt) { int32_t r, c; char tmp; @@ -246,7 +246,7 @@ bool octave_complex_diag_matrix::chk_valid_scalar (const octave_value& val, - Complex& x) const + Complex& x) const { bool retval = val.is_complex_scalar () || val.is_real_scalar (); if (retval) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-cx-mat.cc --- a/libinterp/octave-value/ov-cx-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-cx-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -82,8 +82,8 @@ octave_complex_matrix::numeric_demotion_function (void) const { return octave_base_value::type_conv_info - (default_numeric_demotion_function, - octave_float_complex_matrix::static_type_id ()); + (default_numeric_demotion_function, + octave_float_complex_matrix::static_type_id ()); } octave_base_value * @@ -366,7 +366,7 @@ std::string old_locale (prev_locale ? prev_locale : ""); std::setlocale (LC_ALL, "C"); octave::unwind_action act - ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); + ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); if (kw == "ndims") { @@ -792,48 +792,48 @@ case umap_ ## UMAP: \ return octave_value (m_matrix.FCN ()) - ARRAY_METHOD_MAPPER (abs, abs); - ARRAY_METHOD_MAPPER (isnan, isnan); - ARRAY_METHOD_MAPPER (isinf, isinf); - ARRAY_METHOD_MAPPER (isfinite, isfinite); + ARRAY_METHOD_MAPPER (abs, abs); + ARRAY_METHOD_MAPPER (isnan, isnan); + ARRAY_METHOD_MAPPER (isinf, isinf); + ARRAY_METHOD_MAPPER (isfinite, isfinite); #define ARRAY_MAPPER(UMAP, TYPE, FCN) \ case umap_ ## UMAP: \ return octave_value (m_matrix.map (FCN)) - ARRAY_MAPPER (acos, Complex, octave::math::acos); - ARRAY_MAPPER (acosh, Complex, octave::math::acosh); - ARRAY_MAPPER (angle, double, std::arg); - ARRAY_MAPPER (arg, double, std::arg); - ARRAY_MAPPER (asin, Complex, octave::math::asin); - ARRAY_MAPPER (asinh, Complex, octave::math::asinh); - ARRAY_MAPPER (atan, Complex, octave::math::atan); - ARRAY_MAPPER (atanh, Complex, octave::math::atanh); - ARRAY_MAPPER (erf, Complex, octave::math::erf); - ARRAY_MAPPER (erfc, Complex, octave::math::erfc); - ARRAY_MAPPER (erfcx, Complex, octave::math::erfcx); - ARRAY_MAPPER (erfi, Complex, octave::math::erfi); - ARRAY_MAPPER (dawson, Complex, octave::math::dawson); - ARRAY_MAPPER (ceil, Complex, octave::math::ceil); - ARRAY_MAPPER (cos, Complex, std::cos); - ARRAY_MAPPER (cosh, Complex, std::cosh); - ARRAY_MAPPER (exp, Complex, std::exp); - ARRAY_MAPPER (expm1, Complex, octave::math::expm1); - ARRAY_MAPPER (fix, Complex, octave::math::fix); - ARRAY_MAPPER (floor, Complex, octave::math::floor); - ARRAY_MAPPER (log, Complex, std::log); - ARRAY_MAPPER (log2, Complex, octave::math::log2); - ARRAY_MAPPER (log10, Complex, std::log10); - ARRAY_MAPPER (log1p, Complex, octave::math::log1p); - ARRAY_MAPPER (round, Complex, octave::math::round); - ARRAY_MAPPER (roundb, Complex, octave::math::roundb); - ARRAY_MAPPER (signum, Complex, octave::math::signum); - ARRAY_MAPPER (sin, Complex, std::sin); - ARRAY_MAPPER (sinh, Complex, std::sinh); - ARRAY_MAPPER (sqrt, Complex, std::sqrt); - ARRAY_MAPPER (tan, Complex, std::tan); - ARRAY_MAPPER (tanh, Complex, std::tanh); - ARRAY_MAPPER (isna, bool, octave::math::isna); + ARRAY_MAPPER (acos, Complex, octave::math::acos); + ARRAY_MAPPER (acosh, Complex, octave::math::acosh); + ARRAY_MAPPER (angle, double, std::arg); + ARRAY_MAPPER (arg, double, std::arg); + ARRAY_MAPPER (asin, Complex, octave::math::asin); + ARRAY_MAPPER (asinh, Complex, octave::math::asinh); + ARRAY_MAPPER (atan, Complex, octave::math::atan); + ARRAY_MAPPER (atanh, Complex, octave::math::atanh); + ARRAY_MAPPER (erf, Complex, octave::math::erf); + ARRAY_MAPPER (erfc, Complex, octave::math::erfc); + ARRAY_MAPPER (erfcx, Complex, octave::math::erfcx); + ARRAY_MAPPER (erfi, Complex, octave::math::erfi); + ARRAY_MAPPER (dawson, Complex, octave::math::dawson); + ARRAY_MAPPER (ceil, Complex, octave::math::ceil); + ARRAY_MAPPER (cos, Complex, std::cos); + ARRAY_MAPPER (cosh, Complex, std::cosh); + ARRAY_MAPPER (exp, Complex, std::exp); + ARRAY_MAPPER (expm1, Complex, octave::math::expm1); + ARRAY_MAPPER (fix, Complex, octave::math::fix); + ARRAY_MAPPER (floor, Complex, octave::math::floor); + ARRAY_MAPPER (log, Complex, std::log); + ARRAY_MAPPER (log2, Complex, octave::math::log2); + ARRAY_MAPPER (log10, Complex, std::log10); + ARRAY_MAPPER (log1p, Complex, octave::math::log1p); + ARRAY_MAPPER (round, Complex, octave::math::round); + ARRAY_MAPPER (roundb, Complex, octave::math::roundb); + ARRAY_MAPPER (signum, Complex, octave::math::signum); + ARRAY_MAPPER (sin, Complex, std::sin); + ARRAY_MAPPER (sinh, Complex, std::sinh); + ARRAY_MAPPER (sqrt, Complex, std::sqrt); + ARRAY_MAPPER (tan, Complex, std::tan); + ARRAY_MAPPER (tanh, Complex, std::tanh); + ARRAY_MAPPER (isna, bool, octave::math::isna); default: return octave_base_value::map (umap); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-cx-sparse.cc --- a/libinterp/octave-value/ov-cx-sparse.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-cx-sparse.cc Thu Dec 01 20:05:44 2022 -0800 @@ -180,7 +180,7 @@ bool octave_sparse_complex_matrix::save_binary (std::ostream& os, - bool save_as_floats) + bool save_as_floats) { dim_vector dv = this->dims (); if (dv.ndims () < 1) @@ -249,7 +249,7 @@ bool octave_sparse_complex_matrix::load_binary (std::istream& is, bool swap, - octave::mach_info::float_format fmt) + octave::mach_info::float_format fmt) { int32_t nz, nc, nr, tmp; char ctmp; @@ -320,8 +320,8 @@ bool octave_sparse_complex_matrix::save_hdf5 (octave_hdf5_id loc_id, - const char *name, - bool save_as_floats) + const char *name, + bool save_as_floats) { bool retval = false; @@ -588,7 +588,7 @@ bool octave_sparse_complex_matrix::load_hdf5 (octave_hdf5_id loc_id, - const char *name) + const char *name) { bool retval = false; @@ -905,49 +905,49 @@ case umap_ ## UMAP: \ return octave_value (matrix.FCN ()) - ARRAY_METHOD_MAPPER (abs, abs); + ARRAY_METHOD_MAPPER (abs, abs); #define ARRAY_MAPPER(UMAP, TYPE, FCN) \ case umap_ ## UMAP: \ return octave_value (matrix.map (FCN)) - ARRAY_MAPPER (acos, Complex, octave::math::acos); - ARRAY_MAPPER (acosh, Complex, octave::math::acosh); - ARRAY_MAPPER (angle, double, std::arg); - ARRAY_MAPPER (arg, double, std::arg); - ARRAY_MAPPER (asin, Complex, octave::math::asin); - ARRAY_MAPPER (asinh, Complex, octave::math::asinh); - ARRAY_MAPPER (atan, Complex, octave::math::atan); - ARRAY_MAPPER (atanh, Complex, octave::math::atanh); - ARRAY_MAPPER (erf, Complex, octave::math::erf); - ARRAY_MAPPER (erfc, Complex, octave::math::erfc); - ARRAY_MAPPER (erfcx, Complex, octave::math::erfcx); - ARRAY_MAPPER (erfi, Complex, octave::math::erfi); - ARRAY_MAPPER (dawson, Complex, octave::math::dawson); - ARRAY_MAPPER (ceil, Complex, octave::math::ceil); - ARRAY_MAPPER (conj, Complex, std::conj); - ARRAY_MAPPER (cos, Complex, std::cos); - ARRAY_MAPPER (cosh, Complex, std::cosh); - ARRAY_MAPPER (exp, Complex, std::exp); - ARRAY_MAPPER (expm1, Complex, octave::math::expm1); - ARRAY_MAPPER (fix, Complex, octave::math::fix); - ARRAY_MAPPER (floor, Complex, octave::math::floor); - ARRAY_MAPPER (log, Complex, std::log); - ARRAY_MAPPER (log2, Complex, octave::math::log2); - ARRAY_MAPPER (log10, Complex, std::log10); - ARRAY_MAPPER (log1p, Complex, octave::math::log1p); - ARRAY_MAPPER (round, Complex, octave::math::round); - ARRAY_MAPPER (roundb, Complex, octave::math::roundb); - ARRAY_MAPPER (signum, Complex, octave::math::signum); - ARRAY_MAPPER (sin, Complex, std::sin); - ARRAY_MAPPER (sinh, Complex, std::sinh); - ARRAY_MAPPER (sqrt, Complex, std::sqrt); - ARRAY_MAPPER (tan, Complex, std::tan); - ARRAY_MAPPER (tanh, Complex, std::tanh); - ARRAY_MAPPER (isnan, bool, octave::math::isnan); - ARRAY_MAPPER (isna, bool, octave::math::isna); - ARRAY_MAPPER (isinf, bool, octave::math::isinf); - ARRAY_MAPPER (isfinite, bool, octave::math::isfinite); + ARRAY_MAPPER (acos, Complex, octave::math::acos); + ARRAY_MAPPER (acosh, Complex, octave::math::acosh); + ARRAY_MAPPER (angle, double, std::arg); + ARRAY_MAPPER (arg, double, std::arg); + ARRAY_MAPPER (asin, Complex, octave::math::asin); + ARRAY_MAPPER (asinh, Complex, octave::math::asinh); + ARRAY_MAPPER (atan, Complex, octave::math::atan); + ARRAY_MAPPER (atanh, Complex, octave::math::atanh); + ARRAY_MAPPER (erf, Complex, octave::math::erf); + ARRAY_MAPPER (erfc, Complex, octave::math::erfc); + ARRAY_MAPPER (erfcx, Complex, octave::math::erfcx); + ARRAY_MAPPER (erfi, Complex, octave::math::erfi); + ARRAY_MAPPER (dawson, Complex, octave::math::dawson); + ARRAY_MAPPER (ceil, Complex, octave::math::ceil); + ARRAY_MAPPER (conj, Complex, std::conj); + ARRAY_MAPPER (cos, Complex, std::cos); + ARRAY_MAPPER (cosh, Complex, std::cosh); + ARRAY_MAPPER (exp, Complex, std::exp); + ARRAY_MAPPER (expm1, Complex, octave::math::expm1); + ARRAY_MAPPER (fix, Complex, octave::math::fix); + ARRAY_MAPPER (floor, Complex, octave::math::floor); + ARRAY_MAPPER (log, Complex, std::log); + ARRAY_MAPPER (log2, Complex, octave::math::log2); + ARRAY_MAPPER (log10, Complex, std::log10); + ARRAY_MAPPER (log1p, Complex, octave::math::log1p); + ARRAY_MAPPER (round, Complex, octave::math::round); + ARRAY_MAPPER (roundb, Complex, octave::math::roundb); + ARRAY_MAPPER (signum, Complex, octave::math::signum); + ARRAY_MAPPER (sin, Complex, std::sin); + ARRAY_MAPPER (sinh, Complex, std::sinh); + ARRAY_MAPPER (sqrt, Complex, std::sqrt); + ARRAY_MAPPER (tan, Complex, std::tan); + ARRAY_MAPPER (tanh, Complex, std::tanh); + ARRAY_MAPPER (isnan, bool, octave::math::isnan); + ARRAY_MAPPER (isna, bool, octave::math::isna); + ARRAY_MAPPER (isinf, bool, octave::math::isinf); + ARRAY_MAPPER (isfinite, bool, octave::math::isfinite); default: // Attempt to go via dense matrix. return octave_base_sparse::map (umap); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-dld-fcn.cc --- a/libinterp/octave-value/ov-dld-fcn.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-dld-fcn.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,8 +44,8 @@ "dynamically-linked function"); octave_dld_function::octave_dld_function - (octave_builtin::fcn ff, const octave::dynamic_library& shl, - const std::string& nm, const std::string& ds) +(octave_builtin::fcn ff, const octave::dynamic_library& shl, + const std::string& nm, const std::string& ds) : octave_builtin (ff, nm, ds), m_sh_lib (shl) { mark_fcn_file_up_to_date (time_parsed ()); @@ -56,7 +56,7 @@ = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ()); static const std::string oct_file_dir = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir () - : canonical_oct_file_dir; + : canonical_oct_file_dir; m_system_fcn_file = (! file_name.empty () @@ -64,8 +64,8 @@ } octave_dld_function::octave_dld_function - (octave_builtin::meth mm, const octave::dynamic_library& shl, - const std::string& nm, const std::string& ds) +(octave_builtin::meth mm, const octave::dynamic_library& shl, + const std::string& nm, const std::string& ds) : octave_builtin (mm, nm, ds), m_sh_lib (shl) { mark_fcn_file_up_to_date (time_parsed ()); @@ -76,7 +76,7 @@ = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ()); static const std::string oct_file_dir = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir () - : canonical_oct_file_dir; + : canonical_oct_file_dir; m_system_fcn_file = (! file_name.empty () diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-dld-fcn.h --- a/libinterp/octave-value/ov-dld-fcn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-dld-fcn.h Thu Dec 01 20:05:44 2022 -0800 @@ -85,14 +85,14 @@ bool is_dld_function (void) const { return true; } static octave_dld_function * create (octave_builtin::fcn ff, - const octave::dynamic_library& shl, - const std::string& nm = "", - const std::string& ds = ""); + const octave::dynamic_library& shl, + const std::string& nm = "", + const std::string& ds = ""); static octave_dld_function * create (octave_builtin::meth mm, - const octave::dynamic_library& shl, - const std::string& nm = "", - const std::string& ds = ""); + const octave::dynamic_library& shl, + const std::string& nm = "", + const std::string& ds = ""); octave::dynamic_library get_shlib (void) const { return m_sh_lib; } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-fcn-handle.cc --- a/libinterp/octave-value/ov-fcn-handle.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-fcn-handle.cc Thu Dec 01 20:05:44 2022 -0800 @@ -86,1049 +86,433 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class invalid_fcn_handle : public base_fcn_handle - { - public: - - invalid_fcn_handle (void) : base_fcn_handle ("") { } - - invalid_fcn_handle (const invalid_fcn_handle&) = default; - - ~invalid_fcn_handle (void) = default; - - invalid_fcn_handle * clone (void) const - { - return new invalid_fcn_handle (*this); - } - - std::string type (void) const { return ""; } - - octave_value_list call (int nargout, const octave_value_list& args); - }; - - // Create a handle to an unnamed internal function. There will be no - // way to save and reload it. See, for example, the F__fltk_check__ - // function in __init_fltk__.cc. - - class internal_fcn_handle : public base_fcn_handle +class invalid_fcn_handle : public base_fcn_handle +{ +public: + + invalid_fcn_handle (void) : base_fcn_handle ("") { } + + invalid_fcn_handle (const invalid_fcn_handle&) = default; + + ~invalid_fcn_handle (void) = default; + + invalid_fcn_handle * clone (void) const { - public: - - internal_fcn_handle (const octave_value& fcn) - : base_fcn_handle (""), m_fcn (fcn) - { } - - internal_fcn_handle (const internal_fcn_handle&) = default; - - ~internal_fcn_handle (void) = default; - - internal_fcn_handle * clone (void) const - { - return new internal_fcn_handle (*this); - } - - std::string type (void) const { return ""; } - - bool is_internal (void) const { return true; } - - octave_value_list call (int nargout, const octave_value_list& args); - - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - octave_function * function_value (bool = false) - { - return m_fcn.function_value (); - } - - octave_user_function * user_function_value (bool = false) - { - return m_fcn.user_function_value (); - } - - octave_value fcn_val (void) { return m_fcn; } - - // Should be const. - octave_scalar_map info (void); - - friend bool is_equal_to (const internal_fcn_handle& fh1, - const internal_fcn_handle& fh2); - - private: - - octave_value m_fcn; - }; - - class simple_fcn_handle : public base_fcn_handle + return new invalid_fcn_handle (*this); + } + + std::string type (void) const { return ""; } + + octave_value_list call (int nargout, const octave_value_list& args); +}; + +// Create a handle to an unnamed internal function. There will be no +// way to save and reload it. See, for example, the F__fltk_check__ +// function in __init_fltk__.cc. + +class internal_fcn_handle : public base_fcn_handle +{ +public: + + internal_fcn_handle (const octave_value& fcn) + : base_fcn_handle (""), m_fcn (fcn) + { } + + internal_fcn_handle (const internal_fcn_handle&) = default; + + ~internal_fcn_handle (void) = default; + + internal_fcn_handle * clone (void) const { - public: - - // FIXME: octaveroot is temporary information used when loading - // handles. Can we avoid using it in the constructor? - - simple_fcn_handle (const std::string& name = "", - const std::string& file = "", - const std::string& /*octaveroot*/ = "") - : base_fcn_handle (name, file), m_fcn () - { } - - simple_fcn_handle (const octave_value& fcn, const std::string& name) - : base_fcn_handle (name), m_fcn (fcn) - { - if (m_fcn.is_defined ()) - { - octave_function *oct_fcn = m_fcn.function_value (); - - if (oct_fcn) - m_file = oct_fcn->fcn_file_name (); - } - } - - simple_fcn_handle (const simple_fcn_handle&) = default; - - ~simple_fcn_handle (void) = default; - - simple_fcn_handle * clone (void) const - { - return new simple_fcn_handle (*this); - } - - std::string type (void) const { return "simple"; } - - bool is_simple (void) const { return true; } - - octave_value_list call (int nargout, const octave_value_list& args); - - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - octave_function * function_value (bool); - - octave_user_function * user_function_value (bool); - - octave_value fcn_val (void); - - // Should be const. - octave_scalar_map info (void); - - bool save_ascii (std::ostream& os); - - bool load_ascii (std::istream& is); - - bool save_binary (std::ostream& os, bool save_as_floats); - - bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); - - bool save_hdf5 (octave_hdf5_id loc_hid, const char *name, - bool save_as_floats); - - bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid); - - void print_raw (std::ostream& os, bool pr_as_read_syntax, - int current_print_indent_level) const; - - friend bool is_equal_to (const simple_fcn_handle& fh1, - const simple_fcn_handle& fh2); - - private: - - octave_value m_fcn; - }; - - class scoped_fcn_handle : public base_fcn_handle + return new internal_fcn_handle (*this); + } + + std::string type (void) const { return ""; } + + bool is_internal (void) const { return true; } + + octave_value_list call (int nargout, const octave_value_list& args); + + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + octave_function * function_value (bool = false) + { + return m_fcn.function_value (); + } + + octave_user_function * user_function_value (bool = false) { - public: - - // FIXME: octaveroot is temporary information used when loading - // handles. Can we avoid using it in the constructor? - - scoped_fcn_handle (const std::string& name = "", - const std::string& file = "", - const std::string& /*octaveroot*/ = "") - : base_fcn_handle (name, file) - { } - - scoped_fcn_handle (const octave_value& fcn, const std::string& name, - const std::list& parentage); - - scoped_fcn_handle (const scoped_fcn_handle&) = default; - - ~scoped_fcn_handle (void) = default; - - scoped_fcn_handle * clone (void) const - { - return new scoped_fcn_handle (*this); - } - - std::string type (void) const { return "scopedfunction"; } - - bool is_scoped (void) const { return true; } - - octave_value_list call (int nargout, const octave_value_list& args); - - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - octave_function * function_value (bool = false) - { - return m_fcn.function_value (); - } - - octave_user_function * user_function_value (bool = false) - { - return m_fcn.user_function_value (); - } - - octave_value fcn_val (void) { return m_fcn; } - - // Should be const. - octave_scalar_map info (void); - - bool save_ascii (std::ostream& os); - - bool load_ascii (std::istream& is); - - bool save_binary (std::ostream& os, bool save_as_floats); - - bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); - - bool save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool save_as_floats); - - bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid); - - void print_raw (std::ostream&, bool pr_as_read_syntax, - int current_print_indent_level) const; - - friend bool is_equal_to (const scoped_fcn_handle& fh1, - const scoped_fcn_handle& fh2); - - protected: - - void find_function (void); - - // The function we are handling. - octave_value m_fcn; - - // List of parent function names. The first element is the name of - // m_fcn. - std::list m_parentage; - }; - - class base_nested_fcn_handle : public base_fcn_handle + return m_fcn.user_function_value (); + } + + octave_value fcn_val (void) { return m_fcn; } + + // Should be const. + octave_scalar_map info (void); + + friend bool is_equal_to (const internal_fcn_handle& fh1, + const internal_fcn_handle& fh2); + +private: + + octave_value m_fcn; +}; + +class simple_fcn_handle : public base_fcn_handle +{ +public: + + // FIXME: octaveroot is temporary information used when loading + // handles. Can we avoid using it in the constructor? + + simple_fcn_handle (const std::string& name = "", + const std::string& file = "", + const std::string& /*octaveroot*/ = "") + : base_fcn_handle (name, file), m_fcn () + { } + + simple_fcn_handle (const octave_value& fcn, const std::string& name) + : base_fcn_handle (name), m_fcn (fcn) { - public: - - // FIXME: octaveroot is temporary information used when loading - // handles. Can we avoid using it in the constructor? - - base_nested_fcn_handle (const std::string& name = "", - const std::string& file = "", - const std::string& /*octaveroot*/ = "") - : base_fcn_handle (name, file) - { } - - base_nested_fcn_handle (const octave_value& fcn, const std::string& name) - : base_fcn_handle (name), m_fcn (fcn) - { } - - std::string type (void) const { return "nested"; } - - using base_fcn_handle::is_nested; - - bool is_nested (void) const { return true; } - - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - octave_function * function_value (bool = false) - { - return m_fcn.function_value (); - } - - octave_user_function * user_function_value (bool = false) - { - return m_fcn.user_function_value (); - } - - octave_value fcn_val (void) { return m_fcn; } - - virtual octave_value workspace (void) const = 0; - - // Should be const. - octave_scalar_map info (void); - - bool save_ascii (std::ostream& os); - - bool load_ascii (std::istream& is); - - bool save_binary (std::ostream& os, bool save_as_floats); - - bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); - - bool save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool save_as_floats); - - bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid); - - void print_raw (std::ostream&, bool pr_as_read_syntax, - int current_print_indent_level) const; - - protected: - - // The function we are handling. - octave_value m_fcn; - }; - - class nested_fcn_handle : public base_nested_fcn_handle - { - public: - - // FIXME: octaveroot is temporary information used when loading - // handles. Can we avoid using it in the constructor? - - nested_fcn_handle (const std::string& name = "", - const std::string& file = "", - const std::string& octaveroot = "") - : base_nested_fcn_handle (name, file, octaveroot) - { } - - nested_fcn_handle (const octave_value& fcn, const std::string& name, - const std::shared_ptr& stack_context) - : base_nested_fcn_handle (fcn, name), m_stack_context (stack_context) - { - if (m_stack_context) - m_stack_context->mark_closure_context (); - } - - nested_fcn_handle (const nested_fcn_handle&) = default; - - ~nested_fcn_handle (void) = default; - - using base_nested_fcn_handle::is_nested; - - bool is_nested (const std::shared_ptr& frame) const - { - return frame == m_stack_context; - } - - nested_fcn_handle * clone (void) const - { - return new nested_fcn_handle (*this); - } - - octave_value make_weak_nested_handle (void) const; - - octave_value_list call (int nargout, const octave_value_list& args); - - octave_value workspace (void) const; - - friend bool is_equal_to (const nested_fcn_handle& fh1, - const nested_fcn_handle& fh2); - - std::shared_ptr stack_context (void) const - { - return m_stack_context; - } - - protected: - - // Pointer to closure stack frames. - std::shared_ptr m_stack_context; - }; - - class weak_nested_fcn_handle : public base_nested_fcn_handle + if (m_fcn.is_defined ()) + { + octave_function *oct_fcn = m_fcn.function_value (); + + if (oct_fcn) + m_file = oct_fcn->fcn_file_name (); + } + } + + simple_fcn_handle (const simple_fcn_handle&) = default; + + ~simple_fcn_handle (void) = default; + + simple_fcn_handle * clone (void) const { - public: - - weak_nested_fcn_handle (const nested_fcn_handle& nfh) - : base_nested_fcn_handle (nfh), m_stack_context (nfh.stack_context ()) - { } - - weak_nested_fcn_handle (const weak_nested_fcn_handle&) = default; - - ~weak_nested_fcn_handle (void) = default; - - weak_nested_fcn_handle * clone (void) const - { - return new weak_nested_fcn_handle (*this); - } - - bool is_weak_nested (void) const { return true; } - - octave_value_list call (int nargout, const octave_value_list& args); - - octave_value workspace (void) const; - - friend bool is_equal_to (const weak_nested_fcn_handle& fh1, - const weak_nested_fcn_handle& fh2); - - protected: - - // Pointer to closure stack frames. - std::weak_ptr m_stack_context; - }; - - class class_simple_fcn_handle : public base_fcn_handle + return new simple_fcn_handle (*this); + } + + std::string type (void) const { return "simple"; } + + bool is_simple (void) const { return true; } + + octave_value_list call (int nargout, const octave_value_list& args); + + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + octave_function * function_value (bool); + + octave_user_function * user_function_value (bool); + + octave_value fcn_val (void); + + // Should be const. + octave_scalar_map info (void); + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool save_as_floats); + + bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); + + bool save_hdf5 (octave_hdf5_id loc_hid, const char *name, + bool save_as_floats); + + bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid); + + void print_raw (std::ostream& os, bool pr_as_read_syntax, + int current_print_indent_level) const; + + friend bool is_equal_to (const simple_fcn_handle& fh1, + const simple_fcn_handle& fh2); + +private: + + octave_value m_fcn; +}; + +class scoped_fcn_handle : public base_fcn_handle +{ +public: + + // FIXME: octaveroot is temporary information used when loading + // handles. Can we avoid using it in the constructor? + + scoped_fcn_handle (const std::string& name = "", + const std::string& file = "", + const std::string& /*octaveroot*/ = "") + : base_fcn_handle (name, file) + { } + + scoped_fcn_handle (const octave_value& fcn, const std::string& name, + const std::list& parentage); + + scoped_fcn_handle (const scoped_fcn_handle&) = default; + + ~scoped_fcn_handle (void) = default; + + scoped_fcn_handle * clone (void) const { - public: - - // FIXME: octaveroot is temporary information used when loading - // handles. Can we avoid using it in the constructor? - - class_simple_fcn_handle (const std::string& name, - const std::string& file, - const std::string& /*octaveroot*/) - : base_fcn_handle (name, file) - { } - - // FIXME: is the method name supposed to be just the method name or - // also contain the object name? - - class_simple_fcn_handle (const std::string& class_nm, - const std::string& meth_nm); - - class_simple_fcn_handle (const octave_value& fcn, - const std::string& class_nm, - const std::string& meth_nm); - - class_simple_fcn_handle (const octave_value& obj, const octave_value& fcn, - const std::string& class_nm, - const std::string& meth_nm); - - class_simple_fcn_handle (const class_simple_fcn_handle&) = default; - - ~class_simple_fcn_handle (void) = default; - - class_simple_fcn_handle * clone (void) const - { - return new class_simple_fcn_handle (*this); - } - - std::string type (void) const { return "classsimple"; } - - bool is_class_simple (void) const { return true; } - - octave_value_list call (int nargout, const octave_value_list& args); - - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - octave_function * function_value (bool = false) - { - // FIXME: Shouldn't the lookup rules here match those used in the - // call method? - - if (m_fcn.is_defined ()) - return m_fcn.function_value (); - - symbol_table& symtab = __get_symbol_table__ (); - - // FIXME: is caching the correct thing to do? - // Cache this value so that the pointer will be valid as long as the - // function handle object is valid. - - // FIXME: This should probably dispatch to the respective class method. - // But that breaks if a function handle is used in a class method with - // e.g. bsxfun with arguments of a different class (see bug #59661). - // m_fcn = symtab.find_method (m_name, m_dispatch_class); - m_fcn = symtab.find_function (m_name, octave_value_list ()); - - return m_fcn.is_defined () ? m_fcn.function_value () : nullptr; - } - - octave_user_function * user_function_value (bool = false) - { - return m_fcn.user_function_value (); - } - - octave_value fcn_val (void) { return m_fcn; } - - // Should be const. - octave_scalar_map info (void); - - std::string dispatch_class (void) const { return m_dispatch_class; } - - bool save_ascii (std::ostream& os); - - bool load_ascii (std::istream& is); - - bool save_binary (std::ostream& os, bool save_as_floats); - - bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); - - bool save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool save_as_floats); - - bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid); - - void print_raw (std::ostream&, bool pr_as_read_syntax, - int current_print_indent_level) const; - - friend bool is_equal_to (const class_simple_fcn_handle& fh1, - const class_simple_fcn_handle& fh2); - - protected: - - // The object containing the method we are handing. - octave_value m_obj; - - // The method we are handling. - octave_value m_fcn; - - // Name of the class that m_fcn belongs to. - std::string m_dispatch_class; - }; - - // Handles to anonymous functions are similar to handles to nested - // functions. If they are created in a context that contains nested - // functions, then they store a link to the parent call stack frames - // that are active when they are created. These call stack frames - // (closure frames) provide access to variables needed by any nested - // functions that are called from the anonymous function. Anonymous - // functions also store a list of values from their parent scope - // corresponding to the symbols in the anonymous function. This list - // of values captures the variable values that are visible in the - // scope where they are created. - // - // Note that because handles to anonymous and nested functions capture - // call stack frames when they are created, they will cause deletion - // of the values in those frames to be deferred until the handles to - // the anonymous or nested functions are deleted. - // - // Would it be possible to avoid storing the closure frames for - // handles to anonymous functions if we can determine that the - // anonymous function has no unbound variables (or parameters, which - // could be handles to nested functions?) or if it is not created in a - // context that contains nested functions? - // - // Would it be possible to define anonymous functions as a special - // type of nested function object that also has an variable - // initialization list associated with it? - - class base_anonymous_fcn_handle : public base_fcn_handle + return new scoped_fcn_handle (*this); + } + + std::string type (void) const { return "scopedfunction"; } + + bool is_scoped (void) const { return true; } + + octave_value_list call (int nargout, const octave_value_list& args); + + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + octave_function * function_value (bool = false) + { + return m_fcn.function_value (); + } + + octave_user_function * user_function_value (bool = false) { - public: - - static const std::string anonymous; - - // Setting NAME here is a bit of a kluge to cope with a bad choice - // made to append the number of local variables to the @ - // tag in the binary file format. See also the save_binary and - // load_binary functions. - - base_anonymous_fcn_handle (const std::string& name = "") - : base_fcn_handle (name) - { } - - base_anonymous_fcn_handle (const octave_value& fcn, - const stack_frame::local_vars_map& local_vars) - : base_fcn_handle (anonymous), m_fcn (fcn), m_local_vars (local_vars) - { } - - base_anonymous_fcn_handle (const base_anonymous_fcn_handle&) = default; - - ~base_anonymous_fcn_handle (void) = default; - - std::string type (void) const { return "anonymous"; } - - bool is_anonymous (void) const { return true; } - - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - octave_function * function_value (bool = false) - { - return m_fcn.function_value (); - } - - octave_user_function * user_function_value (bool = false) - { - return m_fcn.user_function_value (); - } - - octave_value fcn_val (void) { return m_fcn; } - - virtual octave_value workspace (void) const = 0; - - // Should be const. - octave_scalar_map info (void); - - bool save_ascii (std::ostream& os); - - bool load_ascii (std::istream& is); - - bool save_binary (std::ostream& os, bool save_as_floats); - - bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); - - bool save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool save_as_floats); - - bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid); - - void print_raw (std::ostream&, bool pr_as_read_syntax, - int current_print_indent_level) const; - - // Anonymous function handles are printed without a newline. - bool print_as_scalar (void) const { return false; } - - bool parse (const std::string& fcn_text); - - protected: - - // The function we are handling. - octave_value m_fcn; - - // List of captured variable values for anonymous fucntions. - stack_frame::local_vars_map m_local_vars; - }; - - class anonymous_fcn_handle : public base_anonymous_fcn_handle - { - public: - - using base_anonymous_fcn_handle::anonymous; - - // Setting NAME here is a bit of a kluge to cope with a bad choice - // made to append the number of local variables to the @ - // tag in the binary file format. See also the save_binary and - // load_binary functions. - - anonymous_fcn_handle (const std::string& name = "") - : base_anonymous_fcn_handle (name), m_stack_context () - { } - - anonymous_fcn_handle (const octave_value& fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& stack_context = std::shared_ptr ()); - - anonymous_fcn_handle (const anonymous_fcn_handle&) = default; - - ~anonymous_fcn_handle (void) = default; - - anonymous_fcn_handle * clone (void) const - { - return new anonymous_fcn_handle (*this); - } - - octave_value make_weak_anonymous_handle (void) const; - - octave_value_list call (int nargout, const octave_value_list& args); - - octave_value workspace (void) const; - - friend bool is_equal_to (const anonymous_fcn_handle& fh1, - const anonymous_fcn_handle& fh2); - - std::shared_ptr stack_context (void) const - { - return m_stack_context; - } - - protected: - - // Pointer to closure stack frames. - std::shared_ptr m_stack_context; - }; - - class weak_anonymous_fcn_handle : public base_anonymous_fcn_handle + return m_fcn.user_function_value (); + } + + octave_value fcn_val (void) { return m_fcn; } + + // Should be const. + octave_scalar_map info (void); + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool save_as_floats); + + bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); + + bool save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool save_as_floats); + + bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid); + + void print_raw (std::ostream&, bool pr_as_read_syntax, + int current_print_indent_level) const; + + friend bool is_equal_to (const scoped_fcn_handle& fh1, + const scoped_fcn_handle& fh2); + +protected: + + void find_function (void); + + // The function we are handling. + octave_value m_fcn; + + // List of parent function names. The first element is the name of + // m_fcn. + std::list m_parentage; +}; + +class base_nested_fcn_handle : public base_fcn_handle +{ +public: + + // FIXME: octaveroot is temporary information used when loading + // handles. Can we avoid using it in the constructor? + + base_nested_fcn_handle (const std::string& name = "", + const std::string& file = "", + const std::string& /*octaveroot*/ = "") + : base_fcn_handle (name, file) + { } + + base_nested_fcn_handle (const octave_value& fcn, const std::string& name) + : base_fcn_handle (name), m_fcn (fcn) + { } + + std::string type (void) const { return "nested"; } + + using base_fcn_handle::is_nested; + + bool is_nested (void) const { return true; } + + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + octave_function * function_value (bool = false) { - public: - - using base_anonymous_fcn_handle::anonymous; - - weak_anonymous_fcn_handle (const anonymous_fcn_handle& afh) - : base_anonymous_fcn_handle (afh), m_stack_context (afh.stack_context ()) - { } - - weak_anonymous_fcn_handle (const weak_anonymous_fcn_handle&) = default; - - ~weak_anonymous_fcn_handle (void) = default; - - weak_anonymous_fcn_handle * clone (void) const - { - return new weak_anonymous_fcn_handle (*this); - } - - bool is_weak_anonymous (void) const { return true; } - - octave_value_list call (int nargout, const octave_value_list& args); - - octave_value workspace (void) const; - - friend bool is_equal_to (const weak_anonymous_fcn_handle& fh1, - const weak_anonymous_fcn_handle& fh2); - - protected: - - // Pointer to closure stack frames. - std::weak_ptr m_stack_context; - }; - - extern bool is_equal_to (const anonymous_fcn_handle& fh1, - const anonymous_fcn_handle& fh2); - - static void err_invalid_fcn_handle (const std::string& name) - { - error ("invalid function handle, unable to find function for @%s", - name.c_str ()); - } - - octave_value base_fcn_handle::make_weak_nested_handle (void) const - { - std::string type_str = type (); - error ("invalid conversion from %s handle to weak nestead handle", - type_str.c_str ()); - } - - octave_value base_fcn_handle::make_weak_anonymous_handle (void) const - { - std::string type_str = type (); - error ("invalid conversion from %s handle to weak anonymous handle", - type_str.c_str ()); + return m_fcn.function_value (); } - octave_value_list - base_fcn_handle::subsref (const std::string& type, - const std::list& idx, - int nargout) - { - octave_value_list retval; - - switch (type[0]) - { - case '(': - { - int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout; - - retval = call (tmp_nargout, idx.front ()); - } - break; - - case '{': - case '.': - error ("function handle cannot be indexed with %c", type[0]); - - default: - panic_impossible (); - } - - // FIXME: perhaps there should be an - // octave_value_list::next_subsref member function? See also - // octave_builtin::subsref. - - if (idx.size () > 1) - retval = retval(0).next_subsref (nargout, type, idx); - - return retval; - } - - octave_value - base_fcn_handle::convert_to_str_internal (bool, bool, char type) const - { - std::ostringstream buf; - print_raw (buf, true, 0); - return octave_value (buf.str (), type); - } - - bool - base_fcn_handle::save_ascii (std::ostream&) - { - unimplemented ("save", "text"); - - return true; - } - - bool - base_fcn_handle::load_ascii (std::istream&) - { - unimplemented ("load", "text"); - - return true; - } - - bool - base_fcn_handle::save_binary (std::ostream&, bool) - { - unimplemented ("save", "binary"); - - return true; - } - - bool - base_fcn_handle::load_binary (std::istream&, bool, mach_info::float_format) - { - unimplemented ("load", "binary"); - - return true; - } - - bool - base_fcn_handle::save_hdf5 (octave_hdf5_id, const char *, bool) + octave_user_function * user_function_value (bool = false) { - unimplemented ("save", "hdf5"); - - return true; - } - - bool - base_fcn_handle::load_hdf5 (octave_hdf5_id&, octave_hdf5_id&, octave_hdf5_id&) - { - unimplemented ("load", "hdf5"); - - return true; + return m_fcn.user_function_value (); } - void base_fcn_handle::warn_load (const char *file_type) const - { - std::string obj_type = type (); - - warning_with_id - ("Octave:load-save-unavailable", - "%s: loading %s files not available in this version of Octave", - obj_type.c_str (), file_type); - } - - void base_fcn_handle::warn_save (const char *file_type) const - { - std::string obj_type = type (); - - warning_with_id - ("Octave:load-save-unavailable", - "%s: saving %s files not available in this version of Octave", - obj_type.c_str (), file_type); - } - - void base_fcn_handle::unimplemented (const char *op, const char *fmt) const + octave_value fcn_val (void) { return m_fcn; } + + virtual octave_value workspace (void) const = 0; + + // Should be const. + octave_scalar_map info (void); + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool save_as_floats); + + bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); + + bool save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool save_as_floats); + + bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid); + + void print_raw (std::ostream&, bool pr_as_read_syntax, + int current_print_indent_level) const; + +protected: + + // The function we are handling. + octave_value m_fcn; +}; + +class nested_fcn_handle : public base_nested_fcn_handle +{ +public: + + // FIXME: octaveroot is temporary information used when loading + // handles. Can we avoid using it in the constructor? + + nested_fcn_handle (const std::string& name = "", + const std::string& file = "", + const std::string& octaveroot = "") + : base_nested_fcn_handle (name, file, octaveroot) + { } + + nested_fcn_handle (const octave_value& fcn, const std::string& name, + const std::shared_ptr& stack_context) + : base_nested_fcn_handle (fcn, name), m_stack_context (stack_context) { - std::string htype = type (); - - warning ("%s for %s handles with %s format is not implemented", - op, htype.c_str (), fmt); - } - - octave_value_list - invalid_fcn_handle::call (int, const octave_value_list&) - { - error ("invalid call to invalid function handle"); + if (m_stack_context) + m_stack_context->mark_closure_context (); } - octave_value_list - internal_fcn_handle::call (int nargout, const octave_value_list& args) - { - interpreter& interp = __get_interpreter__ (); - - return interp.feval (m_fcn, args, nargout); - } - - octave_scalar_map internal_fcn_handle::info (void) + nested_fcn_handle (const nested_fcn_handle&) = default; + + ~nested_fcn_handle (void) = default; + + using base_nested_fcn_handle::is_nested; + + bool is_nested (const std::shared_ptr& frame) const { - octave_scalar_map m; - - m.setfield ("function", fcn_name ()); - m.setfield ("type", type ()); - m.setfield ("file", ""); - - return m; + return frame == m_stack_context; + } + + nested_fcn_handle * clone (void) const + { + return new nested_fcn_handle (*this); } - bool is_equal_to (const internal_fcn_handle& fh1, - const internal_fcn_handle& fh2) - { - if (fh1.m_name == fh2.m_name - && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } - - octave_value_list - simple_fcn_handle::call (int nargout, const octave_value_list& args) + octave_value make_weak_nested_handle (void) const; + + octave_value_list call (int nargout, const octave_value_list& args); + + octave_value workspace (void) const; + + friend bool is_equal_to (const nested_fcn_handle& fh1, + const nested_fcn_handle& fh2); + + std::shared_ptr stack_context (void) const { - // FIXME: if m_name has a '.' in the name, lookup first component. If - // it is a classdef meta object, then build TYPE and IDX arguments and - // make a subsref call using them. - - interpreter& interp = __get_interpreter__ (); - - octave_value fcn_to_call; - - // The following code is similar to part of - // tree_evaluator::visit_index_expression but simpler because it - // handles a more restricted case. - - symbol_table& symtab = interp.get_symbol_table (); - - std::size_t pos = m_name.find ('.'); - - if (pos != std::string::npos) - { - // FIXME: check to see which of these cases actually work in - // Octave and Matlab. For the last two, assume handle is - // created before object is defined as an object. - // - // We can have one of - // - // pkg-list . fcn (args) - // pkg-list . cls . meth (args) - // class-name . method (args) - // class-name . static-method (args) - // object . method (args) - // object . static-method (args) - - // Evaluate package elements until we find a function, - // classdef object, or classdef_meta object that is not a - // package. An object may only appear as the first element, - // then it must be followed directly by a function name. - - std::size_t beg = 0; - std::size_t end = pos; - - std::vector idx_elts; - - while (true) - { - end = m_name.find ('.', beg); - - idx_elts.push_back (m_name.substr (beg, end-beg)); - - if (end == std::string::npos) - break; - - beg = end+1; - } - - std::size_t n_elts = idx_elts.size (); - - bool have_object = false; - octave_value partial_expr_val; - - // Lazy evaluation. The first element was not known to be defined - // as an object in the scope where the handle was created. See if - // there is a definition in the current scope. - - partial_expr_val = interp.varval (idx_elts[0]); - - if (partial_expr_val.is_defined ()) - { - if (! partial_expr_val.is_classdef_object () || n_elts != 2) - err_invalid_fcn_handle (m_name); - - have_object = true; - } - else - partial_expr_val = symtab.find_function (idx_elts[0], ovl ()); - - std::string type; - std::list arg_list; - - for (std::size_t i = 1; i < n_elts; i++) - { - if (partial_expr_val.is_package ()) - { - if (have_object) - err_invalid_fcn_handle (m_name); - - type = "."; - arg_list.push_back (ovl (idx_elts[i])); - - try - { - // Silently ignore extra output values. - - octave_value_list tmp_list - = partial_expr_val.subsref (type, arg_list, 0); - - partial_expr_val - = tmp_list.length () ? tmp_list(0) : octave_value (); - - if (partial_expr_val.is_cs_list ()) - err_invalid_fcn_handle (m_name); - - arg_list.clear (); - } - catch (const index_exception&) - { - err_invalid_fcn_handle (m_name); - } - } - else if (have_object || partial_expr_val.is_classdef_meta ()) - { - // Object or class name must be the next to the last - // element (it was the previous one, so if this is the - // final element, it should be a classdef method, - // but we'll let the classdef or classdef_meta subsref - // function sort that out. - - if (i != n_elts-1) - err_invalid_fcn_handle (m_name); - - type = ".("; - arg_list.push_back (ovl (idx_elts[i])); - arg_list.push_back (args); - - return partial_expr_val.subsref (type, arg_list, nargout); - } - else - err_invalid_fcn_handle (m_name); - } - - // If we get here, we must have a function to call. - - if (! partial_expr_val.is_function ()) - err_invalid_fcn_handle (m_name); - - fcn_to_call = partial_expr_val; - } - else - { - // No "." in the name. - - // Perform function lookup given current arguments. We'll need - // to do this regardless of whether a function was found when - // the handle was created. - - octave_value ov_fcn = symtab.find_function (m_name, args); - - if (m_fcn.is_defined ()) - { - // A simple function was found when the handle was created. - // Use that unless we find a class method to override it. - - fcn_to_call = m_fcn; - - if (ov_fcn.is_defined ()) - { - octave_function *fcn = ov_fcn.function_value (); - - std::string dispatch_class = fcn->dispatch_class (); - - if (fcn->is_class_method ()) - { - // Function found through lookup is a class method - // so use it instead of the simple one found when - // the handle was created. - - fcn_to_call = ov_fcn; - } - } - } - else - { - // There was no simple function found when the handle was - // created so use the one found here (if any). - - fcn_to_call = ov_fcn; - } - } - - if (! fcn_to_call.is_defined ()) - err_invalid_fcn_handle (m_name); - - return interp.feval (fcn_to_call, args, nargout); + return m_stack_context; + } + +protected: + + // Pointer to closure stack frames. + std::shared_ptr m_stack_context; +}; + +class weak_nested_fcn_handle : public base_nested_fcn_handle +{ +public: + + weak_nested_fcn_handle (const nested_fcn_handle& nfh) + : base_nested_fcn_handle (nfh), m_stack_context (nfh.stack_context ()) + { } + + weak_nested_fcn_handle (const weak_nested_fcn_handle&) = default; + + ~weak_nested_fcn_handle (void) = default; + + weak_nested_fcn_handle * clone (void) const + { + return new weak_nested_fcn_handle (*this); } - octave_function * simple_fcn_handle::function_value (bool) + bool is_weak_nested (void) const { return true; } + + octave_value_list call (int nargout, const octave_value_list& args); + + octave_value workspace (void) const; + + friend bool is_equal_to (const weak_nested_fcn_handle& fh1, + const weak_nested_fcn_handle& fh2); + +protected: + + // Pointer to closure stack frames. + std::weak_ptr m_stack_context; +}; + +class class_simple_fcn_handle : public base_fcn_handle +{ +public: + + // FIXME: octaveroot is temporary information used when loading + // handles. Can we avoid using it in the constructor? + + class_simple_fcn_handle (const std::string& name, + const std::string& file, + const std::string& /*octaveroot*/) + : base_fcn_handle (name, file) + { } + + // FIXME: is the method name supposed to be just the method name or + // also contain the object name? + + class_simple_fcn_handle (const std::string& class_nm, + const std::string& meth_nm); + + class_simple_fcn_handle (const octave_value& fcn, + const std::string& class_nm, + const std::string& meth_nm); + + class_simple_fcn_handle (const octave_value& obj, const octave_value& fcn, + const std::string& class_nm, + const std::string& meth_nm); + + class_simple_fcn_handle (const class_simple_fcn_handle&) = default; + + ~class_simple_fcn_handle (void) = default; + + class_simple_fcn_handle * clone (void) const + { + return new class_simple_fcn_handle (*this); + } + + std::string type (void) const { return "classsimple"; } + + bool is_class_simple (void) const { return true; } + + octave_value_list call (int nargout, const octave_value_list& args); + + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + octave_function * function_value (bool = false) { // FIXME: Shouldn't the lookup rules here match those used in the // call method? @@ -1142,1674 +526,2290 @@ // Cache this value so that the pointer will be valid as long as the // function handle object is valid. + // FIXME: This should probably dispatch to the respective class method. + // But that breaks if a function handle is used in a class method with + // e.g. bsxfun with arguments of a different class (see bug #59661). + // m_fcn = symtab.find_method (m_name, m_dispatch_class); m_fcn = symtab.find_function (m_name, octave_value_list ()); return m_fcn.is_defined () ? m_fcn.function_value () : nullptr; } - octave_user_function * simple_fcn_handle::user_function_value (bool) + octave_user_function * user_function_value (bool = false) { - // FIXME: Shouldn't the lookup rules here match those used in the - // call method? - - if (m_fcn.is_defined ()) - return m_fcn.user_function_value (); - - symbol_table& symtab = __get_symbol_table__ (); - - // FIXME: is caching the correct thing to do? - // Cache this value so that the pointer will be valid as long as the - // function handle object is valid. - - m_fcn = symtab.find_user_function (m_name); - - return m_fcn.is_defined () ? m_fcn.user_function_value () : nullptr; + return m_fcn.user_function_value (); } - octave_value simple_fcn_handle::fcn_val (void) + octave_value fcn_val (void) { return m_fcn; } + + // Should be const. + octave_scalar_map info (void); + + std::string dispatch_class (void) const { return m_dispatch_class; } + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool save_as_floats); + + bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); + + bool save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool save_as_floats); + + bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid); + + void print_raw (std::ostream&, bool pr_as_read_syntax, + int current_print_indent_level) const; + + friend bool is_equal_to (const class_simple_fcn_handle& fh1, + const class_simple_fcn_handle& fh2); + +protected: + + // The object containing the method we are handing. + octave_value m_obj; + + // The method we are handling. + octave_value m_fcn; + + // Name of the class that m_fcn belongs to. + std::string m_dispatch_class; +}; + +// Handles to anonymous functions are similar to handles to nested +// functions. If they are created in a context that contains nested +// functions, then they store a link to the parent call stack frames +// that are active when they are created. These call stack frames +// (closure frames) provide access to variables needed by any nested +// functions that are called from the anonymous function. Anonymous +// functions also store a list of values from their parent scope +// corresponding to the symbols in the anonymous function. This list +// of values captures the variable values that are visible in the +// scope where they are created. +// +// Note that because handles to anonymous and nested functions capture +// call stack frames when they are created, they will cause deletion +// of the values in those frames to be deferred until the handles to +// the anonymous or nested functions are deleted. +// +// Would it be possible to avoid storing the closure frames for +// handles to anonymous functions if we can determine that the +// anonymous function has no unbound variables (or parameters, which +// could be handles to nested functions?) or if it is not created in a +// context that contains nested functions? +// +// Would it be possible to define anonymous functions as a special +// type of nested function object that also has an variable +// initialization list associated with it? + +class base_anonymous_fcn_handle : public base_fcn_handle +{ +public: + + static const std::string anonymous; + + // Setting NAME here is a bit of a kluge to cope with a bad choice + // made to append the number of local variables to the @ + // tag in the binary file format. See also the save_binary and + // load_binary functions. + + base_anonymous_fcn_handle (const std::string& name = "") + : base_fcn_handle (name) + { } + + base_anonymous_fcn_handle (const octave_value& fcn, + const stack_frame::local_vars_map& local_vars) + : base_fcn_handle (anonymous), m_fcn (fcn), m_local_vars (local_vars) + { } + + base_anonymous_fcn_handle (const base_anonymous_fcn_handle&) = default; + + ~base_anonymous_fcn_handle (void) = default; + + std::string type (void) const { return "anonymous"; } + + bool is_anonymous (void) const { return true; } + + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + octave_function * function_value (bool = false) { - if (m_fcn.is_defined ()) - return m_fcn; - - symbol_table& symtab = __get_symbol_table__ (); - - // FIXME: is caching the correct thing to do? - // Cache this value so that the pointer will be valid as long as the - // function handle object is valid. - - m_fcn = symtab.find_user_function (m_name); - - return m_fcn; + return m_fcn.function_value (); + } + + octave_user_function * user_function_value (bool = false) + { + return m_fcn.user_function_value (); } - octave_scalar_map simple_fcn_handle::info (void) + octave_value fcn_val (void) { return m_fcn; } + + virtual octave_value workspace (void) const = 0; + + // Should be const. + octave_scalar_map info (void); + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool save_as_floats); + + bool load_binary (std::istream& is, bool swap, mach_info::float_format fmt); + + bool save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool save_as_floats); + + bool load_hdf5 (octave_hdf5_id& group_hid, octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid); + + void print_raw (std::ostream&, bool pr_as_read_syntax, + int current_print_indent_level) const; + + // Anonymous function handles are printed without a newline. + bool print_as_scalar (void) const { return false; } + + bool parse (const std::string& fcn_text); + +protected: + + // The function we are handling. + octave_value m_fcn; + + // List of captured variable values for anonymous fucntions. + stack_frame::local_vars_map m_local_vars; +}; + +class anonymous_fcn_handle : public base_anonymous_fcn_handle +{ +public: + + using base_anonymous_fcn_handle::anonymous; + + // Setting NAME here is a bit of a kluge to cope with a bad choice + // made to append the number of local variables to the @ + // tag in the binary file format. See also the save_binary and + // load_binary functions. + + anonymous_fcn_handle (const std::string& name = "") + : base_anonymous_fcn_handle (name), m_stack_context () + { } + + anonymous_fcn_handle (const octave_value& fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& stack_context = std::shared_ptr ()); + + anonymous_fcn_handle (const anonymous_fcn_handle&) = default; + + ~anonymous_fcn_handle (void) = default; + + anonymous_fcn_handle * clone (void) const { - octave_scalar_map m; - - m.setfield ("function", fcn_name ()); - m.setfield ("type", type ()); - // When is FILE defined for simple function handles? - m.setfield ("file", file ()); - - return m; + return new anonymous_fcn_handle (*this); + } + + octave_value make_weak_anonymous_handle (void) const; + + octave_value_list call (int nargout, const octave_value_list& args); + + octave_value workspace (void) const; + + friend bool is_equal_to (const anonymous_fcn_handle& fh1, + const anonymous_fcn_handle& fh2); + + std::shared_ptr stack_context (void) const + { + return m_stack_context; } - bool simple_fcn_handle::save_ascii (std::ostream& os) +protected: + + // Pointer to closure stack frames. + std::shared_ptr m_stack_context; +}; + +class weak_anonymous_fcn_handle : public base_anonymous_fcn_handle +{ +public: + + using base_anonymous_fcn_handle::anonymous; + + weak_anonymous_fcn_handle (const anonymous_fcn_handle& afh) + : base_anonymous_fcn_handle (afh), m_stack_context (afh.stack_context ()) + { } + + weak_anonymous_fcn_handle (const weak_anonymous_fcn_handle&) = default; + + ~weak_anonymous_fcn_handle (void) = default; + + weak_anonymous_fcn_handle * clone (void) const { - os << "# octaveroot: " << config::octave_exec_home () << "\n"; - - std::string fnm = file (); - if (! fnm.empty ()) - os << "# path: " << fnm << "\n"; - - os << "# subtype: " << type () << "\n"; - - os << m_name << "\n"; - - return true; - } - - bool simple_fcn_handle::load_ascii (std::istream& is) - { - // FIXME: If m_file is not empty, try to load the file and define - // the function? Is it an error if that fails? Or should this job - // always be deferred until the handle is used? - - return is.good (); + return new weak_anonymous_fcn_handle (*this); } - bool simple_fcn_handle::save_binary (std::ostream& os, bool) - { - std::ostringstream nmbuf; - - // When is FILE defined for simple function handles? - std::string fnm; - - nmbuf << m_name << "@\n" << config::octave_exec_home () - << "\n" << fnm; - - std::string buf_str = nmbuf.str (); - int32_t tmp = buf_str.length (); - os.write (reinterpret_cast (&tmp), 4); - os.write (buf_str.c_str (), buf_str.length ()); - - return true; - } - - bool simple_fcn_handle::load_binary (std::istream& is, bool, - mach_info::float_format) - { - return is.good (); - } - - bool simple_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool) - { + bool is_weak_anonymous (void) const { return true; } + + octave_value_list call (int nargout, const octave_value_list& args); + + octave_value workspace (void) const; + + friend bool is_equal_to (const weak_anonymous_fcn_handle& fh1, + const weak_anonymous_fcn_handle& fh2); + +protected: + + // Pointer to closure stack frames. + std::weak_ptr m_stack_context; +}; + +extern bool is_equal_to (const anonymous_fcn_handle& fh1, + const anonymous_fcn_handle& fh2); + +static void err_invalid_fcn_handle (const std::string& name) +{ + error ("invalid function handle, unable to find function for @%s", + name.c_str ()); +} + +octave_value base_fcn_handle::make_weak_nested_handle (void) const +{ + std::string type_str = type (); + error ("invalid conversion from %s handle to weak nestead handle", + type_str.c_str ()); +} + +octave_value base_fcn_handle::make_weak_anonymous_handle (void) const +{ + std::string type_str = type (); + error ("invalid conversion from %s handle to weak anonymous handle", + type_str.c_str ()); +} + +octave_value_list +base_fcn_handle::subsref (const std::string& type, + const std::list& idx, + int nargout) +{ + octave_value_list retval; + + switch (type[0]) + { + case '(': + { + int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout; + + retval = call (tmp_nargout, idx.front ()); + } + break; + + case '{': + case '.': + error ("function handle cannot be indexed with %c", type[0]); + + default: + panic_impossible (); + } + + // FIXME: perhaps there should be an + // octave_value_list::next_subsref member function? See also + // octave_builtin::subsref. + + if (idx.size () > 1) + retval = retval(0).next_subsref (nargout, type, idx); + + return retval; +} + +octave_value +base_fcn_handle::convert_to_str_internal (bool, bool, char type) const +{ + std::ostringstream buf; + print_raw (buf, true, 0); + return octave_value (buf.str (), type); +} + +bool +base_fcn_handle::save_ascii (std::ostream&) +{ + unimplemented ("save", "text"); + + return true; +} + +bool +base_fcn_handle::load_ascii (std::istream&) +{ + unimplemented ("load", "text"); + + return true; +} + +bool +base_fcn_handle::save_binary (std::ostream&, bool) +{ + unimplemented ("save", "binary"); + + return true; +} + +bool +base_fcn_handle::load_binary (std::istream&, bool, mach_info::float_format) +{ + unimplemented ("load", "binary"); + + return true; +} + +bool +base_fcn_handle::save_hdf5 (octave_hdf5_id, const char *, bool) +{ + unimplemented ("save", "hdf5"); + + return true; +} + +bool +base_fcn_handle::load_hdf5 (octave_hdf5_id&, octave_hdf5_id&, octave_hdf5_id&) +{ + unimplemented ("load", "hdf5"); + + return true; +} + +void base_fcn_handle::warn_load (const char *file_type) const +{ + std::string obj_type = type (); + + warning_with_id + ("Octave:load-save-unavailable", + "%s: loading %s files not available in this version of Octave", + obj_type.c_str (), file_type); +} + +void base_fcn_handle::warn_save (const char *file_type) const +{ + std::string obj_type = type (); + + warning_with_id + ("Octave:load-save-unavailable", + "%s: saving %s files not available in this version of Octave", + obj_type.c_str (), file_type); +} + +void base_fcn_handle::unimplemented (const char *op, const char *fmt) const +{ + std::string htype = type (); + + warning ("%s for %s handles with %s format is not implemented", + op, htype.c_str (), fmt); +} + +octave_value_list +invalid_fcn_handle::call (int, const octave_value_list&) +{ + error ("invalid call to invalid function handle"); +} + +octave_value_list +internal_fcn_handle::call (int nargout, const octave_value_list& args) +{ + interpreter& interp = __get_interpreter__ (); + + return interp.feval (m_fcn, args, nargout); +} + +octave_scalar_map internal_fcn_handle::info (void) +{ + octave_scalar_map m; + + m.setfield ("function", fcn_name ()); + m.setfield ("type", type ()); + m.setfield ("file", ""); + + return m; +} + +bool is_equal_to (const internal_fcn_handle& fh1, + const internal_fcn_handle& fh2) +{ + if (fh1.m_name == fh2.m_name + && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} + +octave_value_list +simple_fcn_handle::call (int nargout, const octave_value_list& args) +{ + // FIXME: if m_name has a '.' in the name, lookup first component. If + // it is a classdef meta object, then build TYPE and IDX arguments and + // make a subsref call using them. + + interpreter& interp = __get_interpreter__ (); + + octave_value fcn_to_call; + + // The following code is similar to part of + // tree_evaluator::visit_index_expression but simpler because it + // handles a more restricted case. + + symbol_table& symtab = interp.get_symbol_table (); + + std::size_t pos = m_name.find ('.'); + + if (pos != std::string::npos) + { + // FIXME: check to see which of these cases actually work in + // Octave and Matlab. For the last two, assume handle is + // created before object is defined as an object. + // + // We can have one of + // + // pkg-list . fcn (args) + // pkg-list . cls . meth (args) + // class-name . method (args) + // class-name . static-method (args) + // object . method (args) + // object . static-method (args) + + // Evaluate package elements until we find a function, + // classdef object, or classdef_meta object that is not a + // package. An object may only appear as the first element, + // then it must be followed directly by a function name. + + std::size_t beg = 0; + std::size_t end = pos; + + std::vector idx_elts; + + while (true) + { + end = m_name.find ('.', beg); + + idx_elts.push_back (m_name.substr (beg, end-beg)); + + if (end == std::string::npos) + break; + + beg = end+1; + } + + std::size_t n_elts = idx_elts.size (); + + bool have_object = false; + octave_value partial_expr_val; + + // Lazy evaluation. The first element was not known to be defined + // as an object in the scope where the handle was created. See if + // there is a definition in the current scope. + + partial_expr_val = interp.varval (idx_elts[0]); + + if (partial_expr_val.is_defined ()) + { + if (! partial_expr_val.is_classdef_object () || n_elts != 2) + err_invalid_fcn_handle (m_name); + + have_object = true; + } + else + partial_expr_val = symtab.find_function (idx_elts[0], ovl ()); + + std::string type; + std::list arg_list; + + for (std::size_t i = 1; i < n_elts; i++) + { + if (partial_expr_val.is_package ()) + { + if (have_object) + err_invalid_fcn_handle (m_name); + + type = "."; + arg_list.push_back (ovl (idx_elts[i])); + + try + { + // Silently ignore extra output values. + + octave_value_list tmp_list + = partial_expr_val.subsref (type, arg_list, 0); + + partial_expr_val + = tmp_list.length () ? tmp_list(0) : octave_value (); + + if (partial_expr_val.is_cs_list ()) + err_invalid_fcn_handle (m_name); + + arg_list.clear (); + } + catch (const index_exception&) + { + err_invalid_fcn_handle (m_name); + } + } + else if (have_object || partial_expr_val.is_classdef_meta ()) + { + // Object or class name must be the next to the last + // element (it was the previous one, so if this is the + // final element, it should be a classdef method, + // but we'll let the classdef or classdef_meta subsref + // function sort that out. + + if (i != n_elts-1) + err_invalid_fcn_handle (m_name); + + type = ".("; + arg_list.push_back (ovl (idx_elts[i])); + arg_list.push_back (args); + + return partial_expr_val.subsref (type, arg_list, nargout); + } + else + err_invalid_fcn_handle (m_name); + } + + // If we get here, we must have a function to call. + + if (! partial_expr_val.is_function ()) + err_invalid_fcn_handle (m_name); + + fcn_to_call = partial_expr_val; + } + else + { + // No "." in the name. + + // Perform function lookup given current arguments. We'll need + // to do this regardless of whether a function was found when + // the handle was created. + + octave_value ov_fcn = symtab.find_function (m_name, args); + + if (m_fcn.is_defined ()) + { + // A simple function was found when the handle was created. + // Use that unless we find a class method to override it. + + fcn_to_call = m_fcn; + + if (ov_fcn.is_defined ()) + { + octave_function *fcn = ov_fcn.function_value (); + + std::string dispatch_class = fcn->dispatch_class (); + + if (fcn->is_class_method ()) + { + // Function found through lookup is a class method + // so use it instead of the simple one found when + // the handle was created. + + fcn_to_call = ov_fcn; + } + } + } + else + { + // There was no simple function found when the handle was + // created so use the one found here (if any). + + fcn_to_call = ov_fcn; + } + } + + if (! fcn_to_call.is_defined ()) + err_invalid_fcn_handle (m_name); + + return interp.feval (fcn_to_call, args, nargout); +} + +octave_function *simple_fcn_handle::function_value (bool) +{ + // FIXME: Shouldn't the lookup rules here match those used in the + // call method? + + if (m_fcn.is_defined ()) + return m_fcn.function_value (); + + symbol_table& symtab = __get_symbol_table__ (); + + // FIXME: is caching the correct thing to do? + // Cache this value so that the pointer will be valid as long as the + // function handle object is valid. + + m_fcn = symtab.find_function (m_name, octave_value_list ()); + + return m_fcn.is_defined () ? m_fcn.function_value () : nullptr; +} + +octave_user_function *simple_fcn_handle::user_function_value (bool) +{ + // FIXME: Shouldn't the lookup rules here match those used in the + // call method? + + if (m_fcn.is_defined ()) + return m_fcn.user_function_value (); + + symbol_table& symtab = __get_symbol_table__ (); + + // FIXME: is caching the correct thing to do? + // Cache this value so that the pointer will be valid as long as the + // function handle object is valid. + + m_fcn = symtab.find_user_function (m_name); + + return m_fcn.is_defined () ? m_fcn.user_function_value () : nullptr; +} + +octave_value simple_fcn_handle::fcn_val (void) +{ + if (m_fcn.is_defined ()) + return m_fcn; + + symbol_table& symtab = __get_symbol_table__ (); + + // FIXME: is caching the correct thing to do? + // Cache this value so that the pointer will be valid as long as the + // function handle object is valid. + + m_fcn = symtab.find_user_function (m_name); + + return m_fcn; +} + +octave_scalar_map simple_fcn_handle::info (void) +{ + octave_scalar_map m; + + m.setfield ("function", fcn_name ()); + m.setfield ("type", type ()); + // When is FILE defined for simple function handles? + m.setfield ("file", file ()); + + return m; +} + +bool simple_fcn_handle::save_ascii (std::ostream& os) +{ + os << "# octaveroot: " << config::octave_exec_home () << "\n"; + + std::string fnm = file (); + if (! fnm.empty ()) + os << "# path: " << fnm << "\n"; + + os << "# subtype: " << type () << "\n"; + + os << m_name << "\n"; + + return true; +} + +bool simple_fcn_handle::load_ascii (std::istream& is) +{ + // FIXME: If m_file is not empty, try to load the file and define + // the function? Is it an error if that fails? Or should this job + // always be deferred until the handle is used? + + return is.good (); +} + +bool simple_fcn_handle::save_binary (std::ostream& os, bool) +{ + std::ostringstream nmbuf; + + // When is FILE defined for simple function handles? + std::string fnm; + + nmbuf << m_name << "@\n" << config::octave_exec_home () + << "\n" << fnm; + + std::string buf_str = nmbuf.str (); + int32_t tmp = buf_str.length (); + os.write (reinterpret_cast (&tmp), 4); + os.write (buf_str.c_str (), buf_str.length ()); + + return true; +} + +bool simple_fcn_handle::load_binary (std::istream& is, bool, + mach_info::float_format) +{ + return is.good (); +} + +bool simple_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool) +{ #if defined (HAVE_HDF5) - bool retval = true; - - octave_hdf5_id group_hid = -1; + bool retval = true; + + octave_hdf5_id group_hid = -1; #if defined (HAVE_HDF5_18) - group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT, - octave_H5P_DEFAULT); + group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT, + octave_H5P_DEFAULT); #else - group_hid = H5Gcreate (loc_id, name, 0); + group_hid = H5Gcreate (loc_id, name, 0); #endif - if (group_hid < 0) + if (group_hid < 0) + return false; + + octave_hdf5_id space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; + + // attach the type of the variable + type_hid = H5Tcopy (H5T_C_S1); + H5Tset_size (type_hid, m_name.length () + 1); + if (type_hid < 0) + { + H5Gclose (group_hid); return false; - - octave_hdf5_id space_hid, data_hid, type_hid; - space_hid = data_hid = type_hid = -1; - - // attach the type of the variable - type_hid = H5Tcopy (H5T_C_S1); - H5Tset_size (type_hid, m_name.length () + 1); - if (type_hid < 0) - { - H5Gclose (group_hid); - return false; - } - - OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2); - hdims[0] = 0; - hdims[1] = 0; - space_hid = H5Screate_simple (0, hdims, nullptr); - if (space_hid < 0) - { - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } + } + + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2); + hdims[0] = 0; + hdims[1] = 0; + space_hid = H5Screate_simple (0, hdims, nullptr); + if (space_hid < 0) + { + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } #if defined (HAVE_HDF5_18) - data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, - octave_H5P_DEFAULT, octave_H5P_DEFAULT, - octave_H5P_DEFAULT); + data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, + octave_H5P_DEFAULT, octave_H5P_DEFAULT, + octave_H5P_DEFAULT); #else - data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, - octave_H5P_DEFAULT); + data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, + octave_H5P_DEFAULT); #endif - if (data_hid < 0 - || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL, - octave_H5P_DEFAULT, m_name.c_str ()) < 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - H5Dclose (data_hid); - - std::string octaveroot = config::octave_exec_home (); - - // When is FILE defined for simple fucntion handles? - std::string fpath; - - H5Sclose (space_hid); - hdims[0] = 1; - hdims[1] = octaveroot.length (); - space_hid = H5Screate_simple (0, hdims, nullptr); - if (space_hid < 0) - { - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - - H5Tclose (type_hid); - type_hid = H5Tcopy (H5T_C_S1); - H5Tset_size (type_hid, octaveroot.length () + 1); - octave_hdf5_id a_id; + if (data_hid < 0 + || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL, + octave_H5P_DEFAULT, m_name.c_str ()) < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + H5Dclose (data_hid); + + std::string octaveroot = config::octave_exec_home (); + + // When is FILE defined for simple fucntion handles? + std::string fpath; + + H5Sclose (space_hid); + hdims[0] = 1; + hdims[1] = octaveroot.length (); + space_hid = H5Screate_simple (0, hdims, nullptr); + if (space_hid < 0) + { + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + H5Tclose (type_hid); + type_hid = H5Tcopy (H5T_C_S1); + H5Tset_size (type_hid, octaveroot.length () + 1); + octave_hdf5_id a_id; #if defined (HAVE_HDF5_18) - a_id = H5Acreate (group_hid, "OCTAVEROOT", type_hid, space_hid, - octave_H5P_DEFAULT, octave_H5P_DEFAULT); + a_id = H5Acreate (group_hid, "OCTAVEROOT", type_hid, space_hid, + octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else - a_id = H5Acreate (group_hid, "OCTAVEROOT", type_hid, space_hid, - octave_H5P_DEFAULT); + a_id = H5Acreate (group_hid, "OCTAVEROOT", type_hid, space_hid, + octave_H5P_DEFAULT); #endif - if (a_id >= 0) - { - retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0); - - H5Aclose (a_id); - } - else - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - - H5Sclose (space_hid); - hdims[0] = 1; - hdims[1] = fpath.length (); - space_hid = H5Screate_simple (0, hdims, nullptr); - if (space_hid < 0) - { - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - - H5Tclose (type_hid); - type_hid = H5Tcopy (H5T_C_S1); - H5Tset_size (type_hid, fpath.length () + 1); + if (a_id >= 0) + { + retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0); + + H5Aclose (a_id); + } + else + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + hdims[0] = 1; + hdims[1] = fpath.length (); + space_hid = H5Screate_simple (0, hdims, nullptr); + if (space_hid < 0) + { + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + H5Tclose (type_hid); + type_hid = H5Tcopy (H5T_C_S1); + H5Tset_size (type_hid, fpath.length () + 1); #if defined (HAVE_HDF5_18) - a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, - octave_H5P_DEFAULT, octave_H5P_DEFAULT); + a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, + octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else - a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, - octave_H5P_DEFAULT); + a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, + octave_H5P_DEFAULT); #endif - if (a_id >= 0) - { - retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0); - - H5Aclose (a_id); - } - else - retval = false; - - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - - return retval; + if (a_id >= 0) + { + retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0); + + H5Aclose (a_id); + } + else + retval = false; + + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + + return retval; #else - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - warn_save ("hdf5"); - - return false; - -#endif - } - - bool simple_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, - octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid) - { -#if defined (HAVE_HDF5) - - unimplemented ("load", "hdf5"); - - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return true; - -#else - - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return false; + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + warn_save ("hdf5"); + + return false; #endif - } - - void simple_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax, - int current_print_indent_level) const - { - octave_print_internal (os, '@' + m_name, pr_as_read_syntax, - current_print_indent_level); - } - - bool is_equal_to (const simple_fcn_handle& fh1, const simple_fcn_handle& fh2) - { - if (fh1.m_name == fh2.m_name) - { - if (fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - - if (fh1.m_fcn.is_undefined () && fh2.m_fcn.is_undefined ()) - return true; - } - - return false; - } - - scoped_fcn_handle::scoped_fcn_handle (const octave_value& fcn, - const std::string& name, - const std::list& parentage) - : base_fcn_handle (name), m_fcn (fcn), m_parentage (parentage) - { - // FIXME: should it be an error if FCN is undefined? - - if (m_fcn.is_defined ()) - { - octave_function *oct_fcn = m_fcn.function_value (); - - if (oct_fcn) - m_file = oct_fcn->fcn_file_name (); - } - - m_parentage.push_front (name); - } - - octave_value_list - scoped_fcn_handle::call (int nargout, const octave_value_list& args) - { - // FIXME: we aren't really using the scope yet. Hmm. - - interpreter& interp = __get_interpreter__ (); - - if (! m_fcn.is_defined ()) - { - // Try to find it? - - find_function (); - } - - if (! m_fcn.is_defined ()) - err_invalid_fcn_handle (m_name); - - return interp.feval (m_fcn, args, nargout); - } - - octave_scalar_map scoped_fcn_handle::info (void) - { - octave_scalar_map m; - - m.setfield ("function", fcn_name ()); - m.setfield ("type", type ()); - m.setfield ("file", file ()); - - m.setfield ("parentage", Cell (m_parentage)); - - return m; - } - - bool scoped_fcn_handle::save_ascii (std::ostream& os) - { - os << "# octaveroot: " << config::octave_exec_home () << "\n"; - - std::string fnm = file (); - if (! fnm.empty ()) - os << "# path: " << fnm << "\n"; - - os << "# subtype: " << type () << "\n"; - - os << m_name << "\n"; - - octave_value tmp = Cell (m_parentage); - tmp.save_ascii (os); - - return os.good (); - } - - bool scoped_fcn_handle::load_ascii (std::istream& is) - { - octave_cell ov_cell; - ov_cell.load_ascii (is); - - if (ov_cell.iscellstr ()) - { - Array cellstr_val = ov_cell.cellstr_value (); - - for (octave_idx_type i = 0; i < cellstr_val.numel (); i++) - m_parentage.push_back (cellstr_val(i)); - } - - return is.good (); - } - - bool scoped_fcn_handle::save_binary (std::ostream& os, bool save_as_floats) - { - std::ostringstream nmbuf; - - std::string fnm = file (); - - nmbuf << m_name << "@\n" << config::octave_exec_home () - << "\n" << fnm; - - std::string buf_str = nmbuf.str (); - int32_t len = buf_str.length (); - os.write (reinterpret_cast (&len), 4); - os.write (buf_str.c_str (), buf_str.length ()); - - octave_value tmp = Cell (m_parentage); - tmp.save_binary (os, save_as_floats); - - return os.good (); - } - - bool scoped_fcn_handle::load_binary (std::istream& is, bool swap, - mach_info::float_format fmt) - { - octave_cell ov_cell; - ov_cell.load_binary (is, swap, fmt); - - if (ov_cell.iscellstr ()) - { - Array cellstr_val = ov_cell.cellstr_value (); - - for (octave_idx_type i = 0; i < cellstr_val.numel (); i++) - m_parentage.push_back (cellstr_val(i)); - } - - return is.good (); - } - - bool scoped_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool) - { +} + +bool simple_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, + octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid) +{ #if defined (HAVE_HDF5) - unimplemented ("save", "hdf5"); - - // FIXME: save parentage. - - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - return true; - -#else - - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - warn_save ("hdf5"); - - return false; - -#endif - } - - bool scoped_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, - octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid) - { -#if defined (HAVE_HDF5) - - unimplemented ("load", "hdf5"); - - // FIXME: load parentage. - - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return true; + unimplemented ("load", "hdf5"); + + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return true; #else - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return false; + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return false; #endif - } - - void scoped_fcn_handle::print_raw (std::ostream& os, - bool pr_as_read_syntax, - int current_print_indent_level) const - { - octave_print_internal (os, '@' + m_name, pr_as_read_syntax, - current_print_indent_level); - } - - bool is_equal_to (const scoped_fcn_handle& fh1, const scoped_fcn_handle& fh2) - { - if (fh1.m_name == fh2.m_name - && fh2.m_parentage == fh2.m_parentage - && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } - - void scoped_fcn_handle::find_function (void) - { - // Since a scoped function is not visible by itself, try to load the - // file named in m_file then find and define the scoped function. - // It is not an error if this fails. We can report later that the - // handle is invalid. - - symbol_table& symtab = __get_symbol_table__ (); - - if (m_parentage.size () == 1) - { - std::string dir_name = sys::file_ops::dirname (m_file); - - std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); - - if (pos != std::string::npos) - dir_name = dir_name.substr (0, pos); - else if (dir_name == "private") - dir_name = "."; - - std::string fcn_name = m_parentage.front (); - - // FIXME: Does dir_name need to be in the load path for this to work? - - m_fcn = symtab.find_private_function (dir_name, m_name); - - // FIXME: Verify that it is a private function? - } - else - { - std::string primary_parent_name = m_parentage.back (); - - octave_value ov_parent_fcn - = symtab.find_user_function (primary_parent_name); - - if (ov_parent_fcn.is_defined ()) - { - octave_user_function *fcn = ov_parent_fcn.user_function_value (); - - if (fcn) - { - std::string file_name = fcn->fcn_file_name (); - - std::string oct_home = config::octave_exec_home (); - - if (file_name.substr (0, oct_home.size ()) == oct_home) - file_name = file_name.substr (oct_home.size ()); - - octave_value subfcn = fcn->find_subfunction (m_name); - - if (subfcn.is_defined ()) - m_fcn = subfcn; - } - } - } - } - - octave_scalar_map base_nested_fcn_handle::info (void) - { - octave_scalar_map m; - - m.setfield ("function", fcn_name ()); - m.setfield ("type", type ()); - m.setfield ("file", ""); - m.setfield ("workspace", workspace ()); - - return m; - } - - // FIXME: For save, we need a way to save the (possibly shared) - // workspace. For load, we need a way to load and link to the - // (possibly shared) workspace that was saved. - // - // Since a nested function is not visible by itself, do we need to try - // to load the file named in m_file then find and define the function? - // Is it an error if that fails? Or should this job always be - // deferred until the handle is used? - - bool base_nested_fcn_handle::save_ascii (std::ostream& os) - { - unimplemented ("save", "text"); - - octave_unused_parameter (os); - - return true; - } - - bool base_nested_fcn_handle::load_ascii (std::istream& is) - { - unimplemented ("load", "text"); - - octave_unused_parameter (is); - - return true; - } - - bool base_nested_fcn_handle::save_binary (std::ostream& os, - bool save_as_floats) - { - unimplemented ("save", "binary"); - - octave_unused_parameter (os); - octave_unused_parameter (save_as_floats); - - return true; - } - - bool base_nested_fcn_handle::load_binary (std::istream& is, bool swap, - mach_info::float_format fmt) - { - unimplemented ("load", "binary"); - - octave_unused_parameter (is); - octave_unused_parameter (swap); - octave_unused_parameter (fmt); - - return true; - } - - bool base_nested_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, - const char *name, bool) - { +} + +void simple_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax, + int current_print_indent_level) const +{ + octave_print_internal (os, '@' + m_name, pr_as_read_syntax, + current_print_indent_level); +} + +bool is_equal_to (const simple_fcn_handle& fh1, const simple_fcn_handle& fh2) +{ + if (fh1.m_name == fh2.m_name) + { + if (fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + + if (fh1.m_fcn.is_undefined () && fh2.m_fcn.is_undefined ()) + return true; + } + + return false; +} + +scoped_fcn_handle::scoped_fcn_handle (const octave_value& fcn, + const std::string& name, + const std::list& parentage) + : base_fcn_handle (name), m_fcn (fcn), m_parentage (parentage) +{ + // FIXME: should it be an error if FCN is undefined? + + if (m_fcn.is_defined ()) + { + octave_function *oct_fcn = m_fcn.function_value (); + + if (oct_fcn) + m_file = oct_fcn->fcn_file_name (); + } + + m_parentage.push_front (name); +} + +octave_value_list +scoped_fcn_handle::call (int nargout, const octave_value_list& args) +{ + // FIXME: we aren't really using the scope yet. Hmm. + + interpreter& interp = __get_interpreter__ (); + + if (! m_fcn.is_defined ()) + { + // Try to find it? + + find_function (); + } + + if (! m_fcn.is_defined ()) + err_invalid_fcn_handle (m_name); + + return interp.feval (m_fcn, args, nargout); +} + +octave_scalar_map scoped_fcn_handle::info (void) +{ + octave_scalar_map m; + + m.setfield ("function", fcn_name ()); + m.setfield ("type", type ()); + m.setfield ("file", file ()); + + m.setfield ("parentage", Cell (m_parentage)); + + return m; +} + +bool scoped_fcn_handle::save_ascii (std::ostream& os) +{ + os << "# octaveroot: " << config::octave_exec_home () << "\n"; + + std::string fnm = file (); + if (! fnm.empty ()) + os << "# path: " << fnm << "\n"; + + os << "# subtype: " << type () << "\n"; + + os << m_name << "\n"; + + octave_value tmp = Cell (m_parentage); + tmp.save_ascii (os); + + return os.good (); +} + +bool scoped_fcn_handle::load_ascii (std::istream& is) +{ + octave_cell ov_cell; + ov_cell.load_ascii (is); + + if (ov_cell.iscellstr ()) + { + Array cellstr_val = ov_cell.cellstr_value (); + + for (octave_idx_type i = 0; i < cellstr_val.numel (); i++) + m_parentage.push_back (cellstr_val(i)); + } + + return is.good (); +} + +bool scoped_fcn_handle::save_binary (std::ostream& os, bool save_as_floats) +{ + std::ostringstream nmbuf; + + std::string fnm = file (); + + nmbuf << m_name << "@\n" << config::octave_exec_home () + << "\n" << fnm; + + std::string buf_str = nmbuf.str (); + int32_t len = buf_str.length (); + os.write (reinterpret_cast (&len), 4); + os.write (buf_str.c_str (), buf_str.length ()); + + octave_value tmp = Cell (m_parentage); + tmp.save_binary (os, save_as_floats); + + return os.good (); +} + +bool scoped_fcn_handle::load_binary (std::istream& is, bool swap, + mach_info::float_format fmt) +{ + octave_cell ov_cell; + ov_cell.load_binary (is, swap, fmt); + + if (ov_cell.iscellstr ()) + { + Array cellstr_val = ov_cell.cellstr_value (); + + for (octave_idx_type i = 0; i < cellstr_val.numel (); i++) + m_parentage.push_back (cellstr_val(i)); + } + + return is.good (); +} + +bool scoped_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool) +{ #if defined (HAVE_HDF5) - unimplemented ("save", "hdf5"); - - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - return true; + unimplemented ("save", "hdf5"); + + // FIXME: save parentage. + + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + return true; #else - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - warn_save ("hdf5"); - - return false; + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + warn_save ("hdf5"); + + return false; #endif - } - - bool base_nested_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, - octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid) - { +} + +bool scoped_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, + octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid) +{ #if defined (HAVE_HDF5) - unimplemented ("load", "hdf5"); - - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return true; + unimplemented ("load", "hdf5"); + + // FIXME: load parentage. + + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return true; #else - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return false; + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return false; #endif - } - - void base_nested_fcn_handle::print_raw (std::ostream& os, - bool pr_as_read_syntax, - int current_print_indent_level) const - { - octave_print_internal (os, '@' + m_name, pr_as_read_syntax, - current_print_indent_level); - } - - octave_value nested_fcn_handle::make_weak_nested_handle (void) const - { - return octave_value (new octave_fcn_handle - (new weak_nested_fcn_handle (*this))); - } - - octave_value_list - nested_fcn_handle::call (int nargout, const octave_value_list& args) - { - tree_evaluator& tw = __get_evaluator__ (); - - octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); - - tw.push_stack_frame (oct_usr_fcn, m_stack_context); - - unwind_action act ([&tw] () { tw.pop_stack_frame (); }); - - return oct_usr_fcn->execute (tw, nargout, args); - } - - octave_value nested_fcn_handle::workspace (void) const - { - return m_stack_context->workspace (); - } - - bool is_equal_to (const nested_fcn_handle& fh1, const nested_fcn_handle& fh2) - { - if (fh1.m_name == fh2.m_name - && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } - - octave_value_list - weak_nested_fcn_handle::call (int nargout, const octave_value_list& args) - { - tree_evaluator& tw = __get_evaluator__ (); - - octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); - - std::shared_ptr frames = m_stack_context.lock (); - - tw.push_stack_frame (oct_usr_fcn, frames); - - unwind_action act ([&tw] () { tw.pop_stack_frame (); }); - - return oct_usr_fcn->execute (tw, nargout, args); - } - - octave_value weak_nested_fcn_handle::workspace (void) const - { - std::shared_ptr frames = m_stack_context.lock (); - - return frames ? frames->workspace () : octave_value (); - } - - bool is_equal_to (const weak_nested_fcn_handle& fh1, - const weak_nested_fcn_handle& fh2) - { - if (fh1.m_name == fh2.m_name - && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } - - class_simple_fcn_handle::class_simple_fcn_handle (const std::string& class_nm, - const std::string& meth_nm) - : base_fcn_handle (meth_nm), m_obj (), m_fcn (), - m_dispatch_class (class_nm) - { } - - class_simple_fcn_handle::class_simple_fcn_handle (const octave_value& fcn, - const std::string& class_nm, - const std::string& meth_nm) - : base_fcn_handle (meth_nm), m_obj (), m_fcn (fcn), - m_dispatch_class (class_nm) - { } - - class_simple_fcn_handle::class_simple_fcn_handle (const octave_value& obj, - const octave_value& fcn, - const std::string& class_nm, - const std::string& meth_nm) - : base_fcn_handle (meth_nm), m_obj (obj), m_fcn (fcn), - m_dispatch_class (class_nm) - { } - - octave_value_list - class_simple_fcn_handle::call (int nargout, const octave_value_list& args) - { - interpreter& interp = __get_interpreter__ (); - - if (m_obj.is_defined ()) - { - octave_value_list tmp_args = args; - tmp_args.prepend (m_obj); - - return interp.feval (m_fcn, tmp_args, nargout); - } - - // FIXME: is this the best approach? Should we be saving current - // dispatch class and restoring that value instead of - // unconditionally setting it to "" when we return from this - // function? - - tree_evaluator& tw = interp.get_evaluator (); - - unwind_action act ([&tw] () { tw.set_dispatch_class (""); }); - - tw.set_dispatch_class (m_dispatch_class); - - if (m_fcn.is_defined ()) - return interp.feval (m_fcn, args, nargout); - - return interp.feval (fcn_name (), args, nargout); - } - - octave_scalar_map class_simple_fcn_handle::info (void) - { - octave_scalar_map m; - - m.setfield ("function", fcn_name ()); - m.setfield ("type", type ()); - m.setfield ("file", ""); - m.setfield ("class", dispatch_class ()); - - return m; - } - - // FIXME: Since a class method is not visible by itself, do we need to - // try to load the file named in m_file then find and define the - // function? Is it an error if that fails? Or should this job always - // be deferred until the handle is used? - - bool class_simple_fcn_handle::save_ascii (std::ostream& os) - { - unimplemented ("save", "text"); - - octave_unused_parameter (os); - - return true; - } - - bool class_simple_fcn_handle::load_ascii (std::istream& is) - { - unimplemented ("load", "text"); - - octave_unused_parameter (is); - - return true; - } - - bool class_simple_fcn_handle::save_binary (std::ostream& os, - bool save_as_floats) - { - unimplemented ("save", "binary"); - - octave_unused_parameter (os); - octave_unused_parameter (save_as_floats); - - return true; - } - - bool class_simple_fcn_handle::load_binary (std::istream& is, bool swap, - mach_info::float_format fmt) - { - unimplemented ("load", "binary"); - - octave_unused_parameter (is); - octave_unused_parameter (swap); - octave_unused_parameter (fmt); - - return true; - } - - bool class_simple_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, - const char *name, bool) - { +} + +void scoped_fcn_handle::print_raw (std::ostream& os, + bool pr_as_read_syntax, + int current_print_indent_level) const +{ + octave_print_internal (os, '@' + m_name, pr_as_read_syntax, + current_print_indent_level); +} + +bool is_equal_to (const scoped_fcn_handle& fh1, const scoped_fcn_handle& fh2) +{ + if (fh1.m_name == fh2.m_name + && fh2.m_parentage == fh2.m_parentage + && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} + +void scoped_fcn_handle::find_function (void) +{ + // Since a scoped function is not visible by itself, try to load the + // file named in m_file then find and define the scoped function. + // It is not an error if this fails. We can report later that the + // handle is invalid. + + symbol_table& symtab = __get_symbol_table__ (); + + if (m_parentage.size () == 1) + { + std::string dir_name = sys::file_ops::dirname (m_file); + + std::size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ()); + + if (pos != std::string::npos) + dir_name = dir_name.substr (0, pos); + else if (dir_name == "private") + dir_name = "."; + + std::string fcn_name = m_parentage.front (); + + // FIXME: Does dir_name need to be in the load path for this to work? + + m_fcn = symtab.find_private_function (dir_name, m_name); + + // FIXME: Verify that it is a private function? + } + else + { + std::string primary_parent_name = m_parentage.back (); + + octave_value ov_parent_fcn + = symtab.find_user_function (primary_parent_name); + + if (ov_parent_fcn.is_defined ()) + { + octave_user_function *fcn = ov_parent_fcn.user_function_value (); + + if (fcn) + { + std::string file_name = fcn->fcn_file_name (); + + std::string oct_home = config::octave_exec_home (); + + if (file_name.substr (0, oct_home.size ()) == oct_home) + file_name = file_name.substr (oct_home.size ()); + + octave_value subfcn = fcn->find_subfunction (m_name); + + if (subfcn.is_defined ()) + m_fcn = subfcn; + } + } + } +} + +octave_scalar_map base_nested_fcn_handle::info (void) +{ + octave_scalar_map m; + + m.setfield ("function", fcn_name ()); + m.setfield ("type", type ()); + m.setfield ("file", ""); + m.setfield ("workspace", workspace ()); + + return m; +} + +// FIXME: For save, we need a way to save the (possibly shared) +// workspace. For load, we need a way to load and link to the +// (possibly shared) workspace that was saved. +// +// Since a nested function is not visible by itself, do we need to try +// to load the file named in m_file then find and define the function? +// Is it an error if that fails? Or should this job always be +// deferred until the handle is used? + +bool base_nested_fcn_handle::save_ascii (std::ostream& os) +{ + unimplemented ("save", "text"); + + octave_unused_parameter (os); + + return true; +} + +bool base_nested_fcn_handle::load_ascii (std::istream& is) +{ + unimplemented ("load", "text"); + + octave_unused_parameter (is); + + return true; +} + +bool base_nested_fcn_handle::save_binary (std::ostream& os, + bool save_as_floats) +{ + unimplemented ("save", "binary"); + + octave_unused_parameter (os); + octave_unused_parameter (save_as_floats); + + return true; +} + +bool base_nested_fcn_handle::load_binary (std::istream& is, bool swap, + mach_info::float_format fmt) +{ + unimplemented ("load", "binary"); + + octave_unused_parameter (is); + octave_unused_parameter (swap); + octave_unused_parameter (fmt); + + return true; +} + +bool base_nested_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, + const char *name, bool) +{ #if defined (HAVE_HDF5) - unimplemented ("save", "hdf5"); - - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - return true; + unimplemented ("save", "hdf5"); + + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + return true; + +#else + + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + warn_save ("hdf5"); + + return false; + +#endif +} + +bool base_nested_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, + octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid) +{ +#if defined (HAVE_HDF5) + + unimplemented ("load", "hdf5"); + + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return true; #else - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - - warn_save ("hdf5"); - - return false; + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return false; #endif - } - - bool class_simple_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, - octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid) - { +} + +void base_nested_fcn_handle::print_raw (std::ostream& os, + bool pr_as_read_syntax, + int current_print_indent_level) const +{ + octave_print_internal (os, '@' + m_name, pr_as_read_syntax, + current_print_indent_level); +} + +octave_value nested_fcn_handle::make_weak_nested_handle (void) const +{ + return octave_value (new octave_fcn_handle + (new weak_nested_fcn_handle (*this))); +} + +octave_value_list +nested_fcn_handle::call (int nargout, const octave_value_list& args) +{ + tree_evaluator& tw = __get_evaluator__ (); + + octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); + + tw.push_stack_frame (oct_usr_fcn, m_stack_context); + + unwind_action act ([&tw] () { tw.pop_stack_frame (); }); + + return oct_usr_fcn->execute (tw, nargout, args); +} + +octave_value nested_fcn_handle::workspace (void) const +{ + return m_stack_context->workspace (); +} + +bool is_equal_to (const nested_fcn_handle& fh1, const nested_fcn_handle& fh2) +{ + if (fh1.m_name == fh2.m_name + && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} + +octave_value_list +weak_nested_fcn_handle::call (int nargout, const octave_value_list& args) +{ + tree_evaluator& tw = __get_evaluator__ (); + + octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); + + std::shared_ptr frames = m_stack_context.lock (); + + tw.push_stack_frame (oct_usr_fcn, frames); + + unwind_action act ([&tw] () { tw.pop_stack_frame (); }); + + return oct_usr_fcn->execute (tw, nargout, args); +} + +octave_value weak_nested_fcn_handle::workspace (void) const +{ + std::shared_ptr frames = m_stack_context.lock (); + + return frames ? frames->workspace () : octave_value (); +} + +bool is_equal_to (const weak_nested_fcn_handle& fh1, + const weak_nested_fcn_handle& fh2) +{ + if (fh1.m_name == fh2.m_name + && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} + +class_simple_fcn_handle::class_simple_fcn_handle (const std::string& class_nm, + const std::string& meth_nm) + : base_fcn_handle (meth_nm), m_obj (), m_fcn (), + m_dispatch_class (class_nm) +{ } + +class_simple_fcn_handle::class_simple_fcn_handle (const octave_value& fcn, + const std::string& class_nm, + const std::string& meth_nm) + : base_fcn_handle (meth_nm), m_obj (), m_fcn (fcn), + m_dispatch_class (class_nm) +{ } + +class_simple_fcn_handle::class_simple_fcn_handle (const octave_value& obj, + const octave_value& fcn, + const std::string& class_nm, + const std::string& meth_nm) + : base_fcn_handle (meth_nm), m_obj (obj), m_fcn (fcn), + m_dispatch_class (class_nm) +{ } + +octave_value_list +class_simple_fcn_handle::call (int nargout, const octave_value_list& args) +{ + interpreter& interp = __get_interpreter__ (); + + if (m_obj.is_defined ()) + { + octave_value_list tmp_args = args; + tmp_args.prepend (m_obj); + + return interp.feval (m_fcn, tmp_args, nargout); + } + + // FIXME: is this the best approach? Should we be saving current + // dispatch class and restoring that value instead of + // unconditionally setting it to "" when we return from this + // function? + + tree_evaluator& tw = interp.get_evaluator (); + + unwind_action act ([&tw] () { tw.set_dispatch_class (""); }); + + tw.set_dispatch_class (m_dispatch_class); + + if (m_fcn.is_defined ()) + return interp.feval (m_fcn, args, nargout); + + return interp.feval (fcn_name (), args, nargout); +} + +octave_scalar_map class_simple_fcn_handle::info (void) +{ + octave_scalar_map m; + + m.setfield ("function", fcn_name ()); + m.setfield ("type", type ()); + m.setfield ("file", ""); + m.setfield ("class", dispatch_class ()); + + return m; +} + +// FIXME: Since a class method is not visible by itself, do we need to +// try to load the file named in m_file then find and define the +// function? Is it an error if that fails? Or should this job always +// be deferred until the handle is used? + +bool class_simple_fcn_handle::save_ascii (std::ostream& os) +{ + unimplemented ("save", "text"); + + octave_unused_parameter (os); + + return true; +} + +bool class_simple_fcn_handle::load_ascii (std::istream& is) +{ + unimplemented ("load", "text"); + + octave_unused_parameter (is); + + return true; +} + +bool class_simple_fcn_handle::save_binary (std::ostream& os, + bool save_as_floats) +{ + unimplemented ("save", "binary"); + + octave_unused_parameter (os); + octave_unused_parameter (save_as_floats); + + return true; +} + +bool class_simple_fcn_handle::load_binary (std::istream& is, bool swap, + mach_info::float_format fmt) +{ + unimplemented ("load", "binary"); + + octave_unused_parameter (is); + octave_unused_parameter (swap); + octave_unused_parameter (fmt); + + return true; +} + +bool class_simple_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, + const char *name, bool) +{ #if defined (HAVE_HDF5) - unimplemented ("load", "hdf5"); - - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return true; + unimplemented ("save", "hdf5"); + + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + return true; #else - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return false; + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + + warn_save ("hdf5"); + + return false; + +#endif +} + +bool class_simple_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, + octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid) +{ +#if defined (HAVE_HDF5) + + unimplemented ("load", "hdf5"); + + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return true; + +#else + + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return false; #endif - } - - void class_simple_fcn_handle::print_raw (std::ostream& os, - bool pr_as_read_syntax, - int current_print_indent_level) const - { - octave_print_internal (os, '@' + m_name, pr_as_read_syntax, - current_print_indent_level); - } - - bool is_equal_to (const class_simple_fcn_handle& fh1, - const class_simple_fcn_handle& fh2) - { - // FIXME: Also need to check object values are equivalent? - - if (fh1.m_name == fh2.m_name - && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } - - const std::string base_anonymous_fcn_handle::anonymous ("@"); - - octave_scalar_map base_anonymous_fcn_handle::info (void) - { - octave_scalar_map m; - - std::ostringstream buf; - print_raw (buf, true, 0); - m.setfield ("function", buf.str ()); - - m.setfield ("type", type ()); - m.setfield ("file", ""); - m.setfield ("workspace", workspace ()); - m.setfield ("within_file_path", ""); - - return m; - } - - bool base_anonymous_fcn_handle::save_ascii (std::ostream& os) - { - // FIXME: can we ensure that m_fcn is always defined? - - if (m_fcn.is_undefined ()) - return false; - - os << m_name << "\n"; - - print_raw (os, true, 0); - os << "\n"; - - std::size_t varlen = m_local_vars.size (); - - if (varlen > 0) - { - os << "# length: " << varlen << "\n"; - - for (const auto& nm_val : m_local_vars) - { - if (! save_text_data (os, nm_val.second, nm_val.first, false, 0)) - return ! os.fail (); - } - } - - return true; - } - - bool base_anonymous_fcn_handle::load_ascii (std::istream& is) - { - octave::skip_preceeding_newline (is); - - std::string buf; - - if (is) - { - // Get a line of text whitespace characters included, leaving - // newline in the stream. - - buf = octave::read_until_newline (is, true); - } - - std::streampos pos = is.tellg (); - - // Set up temporary scope to use for evaluating the text that - // defines the anonymous function. - - interpreter& interp = __get_interpreter__ (); - - tree_evaluator& tw = interp.get_evaluator (); - - tw.push_dummy_scope (buf); - unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw); - - octave_idx_type len = 0; - - if (extract_keyword (is, "length", len, true) && len >= 0) - { - if (len > 0) - { - for (octave_idx_type i = 0; i < len; i++) - { - octave_value t2; - bool dummy; - - std::string name = read_text_data (is, "", dummy, t2, i); - - if (! is) - error ("load: failed to load anonymous function handle"); - - m_local_vars[name] = t2; - } - } - } - else - { - is.seekg (pos); - is.clear (); - } - - if (is) - return parse (buf); - +} + +void class_simple_fcn_handle::print_raw (std::ostream& os, + bool pr_as_read_syntax, + int current_print_indent_level) const +{ + octave_print_internal (os, '@' + m_name, pr_as_read_syntax, + current_print_indent_level); +} + +bool is_equal_to (const class_simple_fcn_handle& fh1, + const class_simple_fcn_handle& fh2) +{ + // FIXME: Also need to check object values are equivalent? + + if (fh1.m_name == fh2.m_name + && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} + +const std::string base_anonymous_fcn_handle::anonymous ("@"); + +octave_scalar_map base_anonymous_fcn_handle::info (void) +{ + octave_scalar_map m; + + std::ostringstream buf; + print_raw (buf, true, 0); + m.setfield ("function", buf.str ()); + + m.setfield ("type", type ()); + m.setfield ("file", ""); + m.setfield ("workspace", workspace ()); + m.setfield ("within_file_path", ""); + + return m; +} + +bool base_anonymous_fcn_handle::save_ascii (std::ostream& os) +{ + // FIXME: can we ensure that m_fcn is always defined? + + if (m_fcn.is_undefined ()) return false; - } - - bool base_anonymous_fcn_handle::save_binary (std::ostream& os, - bool save_as_floats) - { - // FIXME: can we ensure that m_fcn is always defined? - - if (m_fcn.is_undefined ()) + + os << m_name << "\n"; + + print_raw (os, true, 0); + os << "\n"; + + std::size_t varlen = m_local_vars.size (); + + if (varlen > 0) + { + os << "# length: " << varlen << "\n"; + + for (const auto& nm_val : m_local_vars) + { + if (! save_text_data (os, nm_val.second, nm_val.first, false, 0)) + return ! os.fail (); + } + } + + return true; +} + +bool base_anonymous_fcn_handle::load_ascii (std::istream& is) +{ + octave::skip_preceeding_newline (is); + + std::string buf; + + if (is) + { + // Get a line of text whitespace characters included, leaving + // newline in the stream. + + buf = octave::read_until_newline (is, true); + } + + std::streampos pos = is.tellg (); + + // Set up temporary scope to use for evaluating the text that + // defines the anonymous function. + + interpreter& interp = __get_interpreter__ (); + + tree_evaluator& tw = interp.get_evaluator (); + + tw.push_dummy_scope (buf); + unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw); + + octave_idx_type len = 0; + + if (extract_keyword (is, "length", len, true) && len >= 0) + { + if (len > 0) + { + for (octave_idx_type i = 0; i < len; i++) + { + octave_value t2; + bool dummy; + + std::string name = read_text_data (is, "", dummy, t2, i); + + if (! is) + error ("load: failed to load anonymous function handle"); + + m_local_vars[name] = t2; + } + } + } + else + { + is.seekg (pos); + is.clear (); + } + + if (is) + return parse (buf); + + return false; +} + +bool base_anonymous_fcn_handle::save_binary (std::ostream& os, + bool save_as_floats) +{ + // FIXME: can we ensure that m_fcn is always defined? + + if (m_fcn.is_undefined ()) + return false; + + std::ostringstream nmbuf; + + std::size_t varlen = m_local_vars.size (); + + nmbuf << anonymous; + if (varlen > 0) + nmbuf << ' ' << varlen; + + std::string buf_str = nmbuf.str (); + int32_t tmp = buf_str.length (); + os.write (reinterpret_cast (&tmp), 4); + os.write (buf_str.c_str (), buf_str.length ()); + + std::ostringstream buf; + print_raw (buf, true, 0); + std::string stmp = buf.str (); + tmp = stmp.length (); + os.write (reinterpret_cast (&tmp), 4); + os.write (stmp.c_str (), stmp.length ()); + + if (varlen > 0) + { + for (const auto& nm_val : m_local_vars) + { + if (! save_binary_data (os, nm_val.second, nm_val.first, + "", 0, save_as_floats)) + return ! os.fail (); + } + } + + return true; +} + +bool base_anonymous_fcn_handle::load_binary (std::istream& is, bool swap, + mach_info::float_format fmt) +{ + // Read extra characters in m_name as the number of local variable + // values in this anonymous function. + + octave_idx_type len = 0; + std::size_t anl = anonymous.length (); + if (m_name.length () > anl) + { + std::istringstream nm_is (m_name.substr (anl)); + nm_is >> len; + + // Anonymous functions don't have names. We just used this + // string as temporary storage to pass the number of local + // variable values. + + m_name = ""; + } + + int32_t tmp; + + if (! is.read (reinterpret_cast (&tmp), 4)) + return false; + if (swap) + swap_bytes<4> (&tmp); + + OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1); + // is.get (ctmp2, tmp+1, 0); caused is.eof () to be true though + // effectively not reading over file end + is.read (ctmp2, tmp); + ctmp2[tmp] = 0; + + // Set up temporary scope to use for evaluating the text that + // defines the anonymous function. + + interpreter& interp = __get_interpreter__ (); + + tree_evaluator& tw = interp.get_evaluator (); + + tw.push_dummy_scope (ctmp2); + unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw); + + if (len > 0) + { + for (octave_idx_type i = 0; i < len; i++) + { + octave_value t2; + bool dummy; + std::string doc; + + std::string name + = read_binary_data (is, swap, fmt, "", dummy, t2, doc); + + if (! is) + error ("load: failed to load anonymous function handle"); + + m_local_vars[name] = t2; + } + } + + if (is) + return parse (ctmp2); + + return false; +} + +bool base_anonymous_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, + const char *name, + bool save_as_floats) +{ +#if defined (HAVE_HDF5) + + bool retval = true; + + octave_hdf5_id group_hid = -1; +#if defined (HAVE_HDF5_18) + group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT, + octave_H5P_DEFAULT); +#else + group_hid = H5Gcreate (loc_id, name, 0); +#endif + if (group_hid < 0) + return false; + + octave_hdf5_id space_hid, data_hid, type_hid; + space_hid = data_hid = type_hid = -1; + + // attach the type of the variable + type_hid = H5Tcopy (H5T_C_S1); + H5Tset_size (type_hid, m_name.length () + 1); + if (type_hid < 0) + { + H5Gclose (group_hid); return false; - - std::ostringstream nmbuf; - - std::size_t varlen = m_local_vars.size (); - - nmbuf << anonymous; - if (varlen > 0) - nmbuf << ' ' << varlen; - - std::string buf_str = nmbuf.str (); - int32_t tmp = buf_str.length (); - os.write (reinterpret_cast (&tmp), 4); - os.write (buf_str.c_str (), buf_str.length ()); - - std::ostringstream buf; - print_raw (buf, true, 0); - std::string stmp = buf.str (); - tmp = stmp.length (); - os.write (reinterpret_cast (&tmp), 4); - os.write (stmp.c_str (), stmp.length ()); - - if (varlen > 0) - { - for (const auto& nm_val : m_local_vars) - { - if (! save_binary_data (os, nm_val.second, nm_val.first, - "", 0, save_as_floats)) - return ! os.fail (); - } - } - - return true; - } - - bool base_anonymous_fcn_handle::load_binary (std::istream& is, bool swap, - mach_info::float_format fmt) - { - // Read extra characters in m_name as the number of local variable - // values in this anonymous function. - - octave_idx_type len = 0; - std::size_t anl = anonymous.length (); - if (m_name.length () > anl) - { - std::istringstream nm_is (m_name.substr (anl)); - nm_is >> len; - - // Anonymous functions don't have names. We just used this - // string as temporary storage to pass the number of local - // variable values. - - m_name = ""; - } - - int32_t tmp; - - if (! is.read (reinterpret_cast (&tmp), 4)) + } + + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2); + hdims[0] = 0; + hdims[1] = 0; + space_hid = H5Screate_simple (0, hdims, nullptr); + if (space_hid < 0) + { + H5Tclose (type_hid); + H5Gclose (group_hid); return false; - if (swap) - swap_bytes<4> (&tmp); - - OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1); - // is.get (ctmp2, tmp+1, 0); caused is.eof () to be true though - // effectively not reading over file end - is.read (ctmp2, tmp); - ctmp2[tmp] = 0; - - // Set up temporary scope to use for evaluating the text that - // defines the anonymous function. - - interpreter& interp = __get_interpreter__ (); - - tree_evaluator& tw = interp.get_evaluator (); - - tw.push_dummy_scope (ctmp2); - unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw); - - if (len > 0) - { - for (octave_idx_type i = 0; i < len; i++) - { - octave_value t2; - bool dummy; - std::string doc; - - std::string name - = read_binary_data (is, swap, fmt, "", dummy, t2, doc); - - if (! is) - error ("load: failed to load anonymous function handle"); - - m_local_vars[name] = t2; - } - } - - if (is) - return parse (ctmp2); - - return false; - } - - bool base_anonymous_fcn_handle::save_hdf5 (octave_hdf5_id loc_id, - const char *name, - bool save_as_floats) - { -#if defined (HAVE_HDF5) - - bool retval = true; - - octave_hdf5_id group_hid = -1; + } #if defined (HAVE_HDF5_18) - group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT, - octave_H5P_DEFAULT); + data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, + octave_H5P_DEFAULT, octave_H5P_DEFAULT, + octave_H5P_DEFAULT); #else - group_hid = H5Gcreate (loc_id, name, 0); + data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, + octave_H5P_DEFAULT); #endif - if (group_hid < 0) + if (data_hid < 0 + || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL, + octave_H5P_DEFAULT, m_name.c_str ()) < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); return false; - - octave_hdf5_id space_hid, data_hid, type_hid; - space_hid = data_hid = type_hid = -1; - - // attach the type of the variable - type_hid = H5Tcopy (H5T_C_S1); - H5Tset_size (type_hid, m_name.length () + 1); - if (type_hid < 0) - { - H5Gclose (group_hid); - return false; - } - - OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2); - hdims[0] = 0; - hdims[1] = 0; - space_hid = H5Screate_simple (0, hdims, nullptr); - if (space_hid < 0) - { - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } -#if defined (HAVE_HDF5_18) - data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, - octave_H5P_DEFAULT, octave_H5P_DEFAULT, - octave_H5P_DEFAULT); -#else - data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, - octave_H5P_DEFAULT); -#endif - if (data_hid < 0 - || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL, - octave_H5P_DEFAULT, m_name.c_str ()) < 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - H5Dclose (data_hid); - - std::ostringstream buf; - print_raw (buf, true, 0); - std::string stmp = buf.str (); - - // attach the type of the variable - H5Tset_size (type_hid, stmp.length () + 1); - if (type_hid < 0) - { - H5Sclose (space_hid); - H5Gclose (group_hid); - return false; - } + } + H5Dclose (data_hid); + + std::ostringstream buf; + print_raw (buf, true, 0); + std::string stmp = buf.str (); + + // attach the type of the variable + H5Tset_size (type_hid, stmp.length () + 1); + if (type_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } #if defined (HAVE_HDF5_18) - data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid, - octave_H5P_DEFAULT, octave_H5P_DEFAULT, - octave_H5P_DEFAULT); + data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid, + octave_H5P_DEFAULT, octave_H5P_DEFAULT, + octave_H5P_DEFAULT); #else - data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid, - octave_H5P_DEFAULT); + data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid, + octave_H5P_DEFAULT); #endif - if (data_hid < 0 - || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL, - octave_H5P_DEFAULT, stmp.c_str ()) < 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - - H5Dclose (data_hid); - - std::size_t varlen = m_local_vars.size (); - - if (varlen > 0) - { - octave_hdf5_id as_id = H5Screate (H5S_SCALAR); - - if (as_id >= 0) - { - octave_hdf5_id a_id; + if (data_hid < 0 + || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL, + octave_H5P_DEFAULT, stmp.c_str ()) < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); + + std::size_t varlen = m_local_vars.size (); + + if (varlen > 0) + { + octave_hdf5_id as_id = H5Screate (H5S_SCALAR); + + if (as_id >= 0) + { + octave_hdf5_id a_id; #if defined (HAVE_HDF5_18) - a_id = H5Acreate (group_hid, "SYMBOL_TABLE", H5T_NATIVE_IDX, as_id, - octave_H5P_DEFAULT, octave_H5P_DEFAULT); + a_id = H5Acreate (group_hid, "SYMBOL_TABLE", H5T_NATIVE_IDX, as_id, + octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else - a_id = H5Acreate (group_hid, "SYMBOL_TABLE", H5T_NATIVE_IDX, as_id, - octave_H5P_DEFAULT); + a_id = H5Acreate (group_hid, "SYMBOL_TABLE", H5T_NATIVE_IDX, as_id, + octave_H5P_DEFAULT); #endif - if (a_id >= 0) - { - retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0); - - H5Aclose (a_id); - } - else - retval = false; - - H5Sclose (as_id); - } - else - retval = false; + if (a_id >= 0) + { + retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0); + + H5Aclose (a_id); + } + else + retval = false; + + H5Sclose (as_id); + } + else + retval = false; #if defined (HAVE_HDF5_18) - data_hid = H5Gcreate (group_hid, "symbol table", - octave_H5P_DEFAULT, octave_H5P_DEFAULT, - octave_H5P_DEFAULT); + data_hid = H5Gcreate (group_hid, "symbol table", + octave_H5P_DEFAULT, octave_H5P_DEFAULT, + octave_H5P_DEFAULT); #else - data_hid = H5Gcreate (group_hid, "symbol table", 0); + data_hid = H5Gcreate (group_hid, "symbol table", 0); #endif - if (data_hid < 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - - for (const auto& nm_val : m_local_vars) - { - if (! add_hdf5_data (data_hid, nm_val.second, nm_val.first, - "", false, save_as_floats)) - break; - } - - H5Gclose (data_hid); - } - - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - - return retval; + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + for (const auto& nm_val : m_local_vars) + { + if (! add_hdf5_data (data_hid, nm_val.second, nm_val.first, + "", false, save_as_floats)) + break; + } + + H5Gclose (data_hid); + } + + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + + return retval; #else - octave_unused_parameter (loc_id); - octave_unused_parameter (name); - octave_unused_parameter (save_as_floats); - - warn_save ("hdf5"); - - return false; + octave_unused_parameter (loc_id); + octave_unused_parameter (name); + octave_unused_parameter (save_as_floats); + + warn_save ("hdf5"); + + return false; #endif - } - - bool base_anonymous_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, - octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid) - { +} + +bool base_anonymous_fcn_handle::load_hdf5 (octave_hdf5_id& group_hid, + octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid) +{ #if defined (HAVE_HDF5) - bool success = true; + bool success = true; #if defined (HAVE_HDF5_18) - octave_hdf5_id data_hid = H5Dopen (group_hid, "fcn", octave_H5P_DEFAULT); + octave_hdf5_id data_hid = H5Dopen (group_hid, "fcn", octave_H5P_DEFAULT); #else - octave_hdf5_id data_hid = H5Dopen (group_hid, "fcn"); + octave_hdf5_id data_hid = H5Dopen (group_hid, "fcn"); #endif - if (data_hid < 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Gclose (group_hid); - return false; - } - - H5Tclose (type_hid); - type_hid = H5Dget_type (data_hid); - octave_hdf5_id type_class_hid = H5Tget_class (type_hid); - - if (type_class_hid != H5T_STRING) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Dclose (data_hid); - H5Gclose (group_hid); - return false; - } - - H5Sclose (space_hid); - space_hid = H5Dget_space (data_hid); - hsize_t rank = H5Sget_simple_extent_ndims (space_hid); - - if (rank != 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Dclose (data_hid); - H5Gclose (group_hid); - return false; - } - - int slen = H5Tget_size (type_hid); - if (slen < 0) - { - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Dclose (data_hid); - H5Gclose (group_hid); - return false; - } - - OCTAVE_LOCAL_BUFFER (char, fcn_tmp, slen); - - // create datatype for (null-terminated) string to read into: - octave_hdf5_id st_id = H5Tcopy (H5T_C_S1); - H5Tset_size (st_id, slen); - - if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL, - octave_H5P_DEFAULT, fcn_tmp) - < 0) - { - H5Tclose (st_id); - H5Sclose (space_hid); - H5Tclose (type_hid); - H5Dclose (data_hid); - H5Gclose (group_hid); - return false; - } - H5Tclose (st_id); - H5Dclose (data_hid); - - octave_idx_type len = 0; - - // we have to pull some shenanigans here to make sure - // HDF5 doesn't print out all sorts of error messages if we - // call H5Aopen for a non-existing attribute - - H5E_auto_t err_fcn; - void *err_fcn_data; - - // turn off error reporting temporarily, but save the error - // reporting function: + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Gclose (group_hid); + return false; + } + + H5Tclose (type_hid); + type_hid = H5Dget_type (data_hid); + octave_hdf5_id type_class_hid = H5Tget_class (type_hid); + + if (type_class_hid != H5T_STRING) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Sclose (space_hid); + space_hid = H5Dget_space (data_hid); + hsize_t rank = H5Sget_simple_extent_ndims (space_hid); + + if (rank != 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + int slen = H5Tget_size (type_hid); + if (slen < 0) + { + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + OCTAVE_LOCAL_BUFFER (char, fcn_tmp, slen); + + // create datatype for (null-terminated) string to read into: + octave_hdf5_id st_id = H5Tcopy (H5T_C_S1); + H5Tset_size (st_id, slen); + + if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL, + octave_H5P_DEFAULT, fcn_tmp) + < 0) + { + H5Tclose (st_id); + H5Sclose (space_hid); + H5Tclose (type_hid); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + H5Tclose (st_id); + H5Dclose (data_hid); + + octave_idx_type len = 0; + + // we have to pull some shenanigans here to make sure + // HDF5 doesn't print out all sorts of error messages if we + // call H5Aopen for a non-existing attribute + + H5E_auto_t err_fcn; + void *err_fcn_data; + + // turn off error reporting temporarily, but save the error + // reporting function: #if defined (HAVE_HDF5_18) - H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data); - H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr); + H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data); + H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr); #else - H5Eget_auto (&err_fcn, &err_fcn_data); - H5Eset_auto (nullptr, nullptr); + H5Eget_auto (&err_fcn, &err_fcn_data); + H5Eset_auto (nullptr, nullptr); #endif - octave_hdf5_id attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE"); - - if (attr_id >= 0) - { - if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0) - success = false; - - H5Aclose (attr_id); - } - - // restore error reporting: + octave_hdf5_id attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE"); + + if (attr_id >= 0) + { + if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0) + success = false; + + H5Aclose (attr_id); + } + + // restore error reporting: #if defined (HAVE_HDF5_18) - H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data); + H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data); #else - H5Eset_auto (err_fcn, err_fcn_data); + H5Eset_auto (err_fcn, err_fcn_data); #endif - // Set up temporary scope to use for evaluating the text that - // defines the anonymous function. - - interpreter& interp = __get_interpreter__ (); - - tree_evaluator& tw = interp.get_evaluator (); - - tw.push_dummy_scope (fcn_tmp); - unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw); - - if (len > 0 && success) - { - hsize_t num_obj = 0; + // Set up temporary scope to use for evaluating the text that + // defines the anonymous function. + + interpreter& interp = __get_interpreter__ (); + + tree_evaluator& tw = interp.get_evaluator (); + + tw.push_dummy_scope (fcn_tmp); + unwind_action_safe restore_scope (&tree_evaluator::pop_scope, &tw); + + if (len > 0 && success) + { + hsize_t num_obj = 0; #if defined (HAVE_HDF5_18) - data_hid = H5Gopen (group_hid, "symbol table", octave_H5P_DEFAULT); + data_hid = H5Gopen (group_hid, "symbol table", octave_H5P_DEFAULT); #else - data_hid = H5Gopen (group_hid, "symbol table"); + data_hid = H5Gopen (group_hid, "symbol table"); #endif - H5Gget_num_objs (data_hid, &num_obj); - H5Gclose (data_hid); - - if (num_obj != static_cast (len)) - error ("load: failed to load anonymous function handle"); - - hdf5_callback_data dsub; - int current_item = 0; - for (octave_idx_type i = 0; i < len; i++) - { - if (hdf5_h5g_iterate (group_hid, "symbol table", ¤t_item, - &dsub) <= 0) - error ("load: failed to load anonymous function handle"); - - m_local_vars[dsub.name] = dsub.tc; - } - } - - if (success) - return parse (fcn_tmp); - - return false; + H5Gget_num_objs (data_hid, &num_obj); + H5Gclose (data_hid); + + if (num_obj != static_cast (len)) + error ("load: failed to load anonymous function handle"); + + hdf5_callback_data dsub; + int current_item = 0; + for (octave_idx_type i = 0; i < len; i++) + { + if (hdf5_h5g_iterate (group_hid, "symbol table", ¤t_item, + &dsub) <= 0) + error ("load: failed to load anonymous function handle"); + + m_local_vars[dsub.name] = dsub.tc; + } + } + + if (success) + return parse (fcn_tmp); + + return false; #else - octave_unused_parameter (group_hid); - octave_unused_parameter (space_hid); - octave_unused_parameter (type_hid); - - return false; + octave_unused_parameter (group_hid); + octave_unused_parameter (space_hid); + octave_unused_parameter (type_hid); + + return false; #endif - } - - void base_anonymous_fcn_handle::print_raw (std::ostream& os, bool, int) const - { - tree_print_code tpc (os); - - octave_user_function *f = m_fcn.user_function_value (); - - if (! f) - error ("invalid anonymous function handle"); - - os << "@"; - - // The parameter list should always be valid for anonymous - // functions, so we should always call accept for it, and it will - // print the parens for us. - - tree_parameter_list *p = f->parameter_list (); - - if (p) - p->accept (tpc); - - os << " "; - - tree_statement_list *b = f->body (); - - panic_if (b->length () != 1); - - tree_statement *s = b->front (); - - if (! s) - error ("invalid anonymous function handle"); - - panic_unless (s->is_expression ()); - - tree_expression *e = s->expression (); - - if (! e) - error ("invalid anonymous function handle"); - - tpc.print_fcn_handle_body (e); - } - - bool base_anonymous_fcn_handle::parse (const std::string& fcn_text) - { - // FIXME: If evaluation of the string gives us an anonymous function - // handle object, then why extract the function and create a new - // anonymous function object? Why not just attach the workspace - // values to the object returned by eval_string? This code is also is - // duplicated in read_mat5_binary_element in ls-mat5.cc. - - interpreter& interp = __get_interpreter__ (); - - // Set up temporary scope to use for evaluating the text that defines - // the anonymous function so that we don't pick up values of random - // variables that might be in the current scope. - - tree_evaluator& tw = interp.get_evaluator (); - tw.push_dummy_scope ("read_mat5_binary_element"); - - unwind_action act ([&tw] () { tw.pop_scope (); }); - - int parse_status; - octave_value anonymous_fcn_hdl - = interp.eval_string (fcn_text, true, parse_status); - - if (parse_status != 0) - return false; - - octave_fcn_handle *fh = anonymous_fcn_hdl.fcn_handle_value (); - - if (! fh) - return false; - - m_fcn = fh->fcn_val (); - - octave_user_function *uf = m_fcn.user_function_value (true); - - if (uf) - { - symbol_scope uf_scope = uf->scope (); - - if (uf_scope) - uf_scope.cache_name (m_name); - } - - return true; - } - - anonymous_fcn_handle::anonymous_fcn_handle (const octave_value& fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& stack_context) - : base_anonymous_fcn_handle (fcn, local_vars), - m_stack_context (stack_context) - { - if (m_stack_context) - m_stack_context->mark_closure_context (); - } - - octave_value anonymous_fcn_handle::make_weak_anonymous_handle (void) const - { - return octave_value (new octave_fcn_handle - (new weak_anonymous_fcn_handle (*this))); - } - - octave_value_list - anonymous_fcn_handle::call (int nargout, const octave_value_list& args) - { - tree_evaluator& tw = __get_evaluator__ (); - - octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); - - tw.push_stack_frame (oct_usr_fcn, m_local_vars, m_stack_context); - - unwind_action act ([&tw] () { tw.pop_stack_frame (); }); - - return oct_usr_fcn->execute (tw, nargout, args); - } - - octave_value anonymous_fcn_handle::workspace (void) const - { - octave_scalar_map local_vars_map; - - for (const auto& nm_val : m_local_vars) - local_vars_map.assign (nm_val.first, nm_val.second); - - // FIXME: it would be more convenient if stack_frame::workspace - // returned a Cell object directly instead of a Cell in an - // octave_value object. - - Cell cell_frames; - - if (m_stack_context) - { - octave_value ov_frames = m_stack_context->workspace (); - cell_frames = ov_frames.cell_value (); - } - - octave_idx_type num_frames = cell_frames.numel (); - // FIXME: It seems there should be a simple way to concatenate cells... - Cell retval = Cell (num_frames+1, 1); - retval(0) = m_local_vars; - for (octave_idx_type i = 0; i < num_frames; i++) - retval(i+1) = cell_frames(i); - - return retval; - } - - bool is_equal_to (const anonymous_fcn_handle& fh1, - const anonymous_fcn_handle& fh2) - { - if (fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } - - octave_value_list - weak_anonymous_fcn_handle::call (int nargout, const octave_value_list& args) - { - tree_evaluator& tw = __get_evaluator__ (); - - octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); - - std::shared_ptr frames = m_stack_context.lock (); - - tw.push_stack_frame (oct_usr_fcn, m_local_vars, frames); - - unwind_action act ([&tw] () { tw.pop_stack_frame (); }); - - return oct_usr_fcn->execute (tw, nargout, args); - } - - octave_value weak_anonymous_fcn_handle::workspace (void) const - { - octave_scalar_map local_vars_map; - - for (const auto& nm_val : m_local_vars) - local_vars_map.assign (nm_val.first, nm_val.second); - - // FIXME: it would be more convenient if stack_frame::workspace - // returned a Cell object directly instead of a Cell in an - // octave_value object. - - std::shared_ptr frames = m_stack_context.lock (); - - Cell cell_frames; - - if (frames) - { - octave_value ov_frames = frames->workspace (); - cell_frames = ov_frames.cell_value (); - } - - octave_idx_type num_frames = cell_frames.numel (); - - // FIXME: It seems there should be a simple way to concatenate - // cells... - Cell retval = Cell (num_frames+1, 1); - retval(0) = m_local_vars; - for (octave_idx_type i = 0; i < num_frames; i++) - retval(i+1) = cell_frames(i); - - return retval; - } - - bool is_equal_to (const weak_anonymous_fcn_handle& fh1, - const weak_anonymous_fcn_handle& fh2) - { - if (fh1.m_name == fh2.m_name - && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) - return fh1.m_fcn.is_copy_of (fh2.m_fcn); - else - return false; - } +} + +void base_anonymous_fcn_handle::print_raw (std::ostream& os, bool, int) const +{ + tree_print_code tpc (os); + + octave_user_function *f = m_fcn.user_function_value (); + + if (! f) + error ("invalid anonymous function handle"); + + os << "@"; + + // The parameter list should always be valid for anonymous + // functions, so we should always call accept for it, and it will + // print the parens for us. + + tree_parameter_list *p = f->parameter_list (); + + if (p) + p->accept (tpc); + + os << " "; + + tree_statement_list *b = f->body (); + + panic_if (b->length () != 1); + + tree_statement *s = b->front (); + + if (! s) + error ("invalid anonymous function handle"); + + panic_unless (s->is_expression ()); + + tree_expression *e = s->expression (); + + if (! e) + error ("invalid anonymous function handle"); + + tpc.print_fcn_handle_body (e); +} + +bool base_anonymous_fcn_handle::parse (const std::string& fcn_text) +{ + // FIXME: If evaluation of the string gives us an anonymous function + // handle object, then why extract the function and create a new + // anonymous function object? Why not just attach the workspace + // values to the object returned by eval_string? This code is also is + // duplicated in read_mat5_binary_element in ls-mat5.cc. + + interpreter& interp = __get_interpreter__ (); + + // Set up temporary scope to use for evaluating the text that defines + // the anonymous function so that we don't pick up values of random + // variables that might be in the current scope. + + tree_evaluator& tw = interp.get_evaluator (); + tw.push_dummy_scope ("read_mat5_binary_element"); + + unwind_action act ([&tw] () { tw.pop_scope (); }); + + int parse_status; + octave_value anonymous_fcn_hdl + = interp.eval_string (fcn_text, true, parse_status); + + if (parse_status != 0) + return false; + + octave_fcn_handle *fh = anonymous_fcn_hdl.fcn_handle_value (); + + if (! fh) + return false; + + m_fcn = fh->fcn_val (); + + octave_user_function *uf = m_fcn.user_function_value (true); + + if (uf) + { + symbol_scope uf_scope = uf->scope (); + + if (uf_scope) + uf_scope.cache_name (m_name); + } + + return true; +} + +anonymous_fcn_handle::anonymous_fcn_handle (const octave_value& fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& stack_context) + : base_anonymous_fcn_handle (fcn, local_vars), + m_stack_context (stack_context) +{ + if (m_stack_context) + m_stack_context->mark_closure_context (); +} + +octave_value anonymous_fcn_handle::make_weak_anonymous_handle (void) const +{ + return octave_value (new octave_fcn_handle + (new weak_anonymous_fcn_handle (*this))); +} + +octave_value_list +anonymous_fcn_handle::call (int nargout, const octave_value_list& args) +{ + tree_evaluator& tw = __get_evaluator__ (); + + octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); + + tw.push_stack_frame (oct_usr_fcn, m_local_vars, m_stack_context); + + unwind_action act ([&tw] () { tw.pop_stack_frame (); }); + + return oct_usr_fcn->execute (tw, nargout, args); +} + +octave_value anonymous_fcn_handle::workspace (void) const +{ + octave_scalar_map local_vars_map; + + for (const auto& nm_val : m_local_vars) + local_vars_map.assign (nm_val.first, nm_val.second); + + // FIXME: it would be more convenient if stack_frame::workspace + // returned a Cell object directly instead of a Cell in an + // octave_value object. + + Cell cell_frames; + + if (m_stack_context) + { + octave_value ov_frames = m_stack_context->workspace (); + cell_frames = ov_frames.cell_value (); + } + + octave_idx_type num_frames = cell_frames.numel (); + // FIXME: It seems there should be a simple way to concatenate cells... + Cell retval = Cell (num_frames+1, 1); + retval(0) = m_local_vars; + for (octave_idx_type i = 0; i < num_frames; i++) + retval(i+1) = cell_frames(i); + + return retval; +} + +bool is_equal_to (const anonymous_fcn_handle& fh1, + const anonymous_fcn_handle& fh2) +{ + if (fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} + +octave_value_list +weak_anonymous_fcn_handle::call (int nargout, const octave_value_list& args) +{ + tree_evaluator& tw = __get_evaluator__ (); + + octave_user_function *oct_usr_fcn = m_fcn.user_function_value (); + + std::shared_ptr frames = m_stack_context.lock (); + + tw.push_stack_frame (oct_usr_fcn, m_local_vars, frames); + + unwind_action act ([&tw] () { tw.pop_stack_frame (); }); + + return oct_usr_fcn->execute (tw, nargout, args); +} + +octave_value weak_anonymous_fcn_handle::workspace (void) const +{ + octave_scalar_map local_vars_map; + + for (const auto& nm_val : m_local_vars) + local_vars_map.assign (nm_val.first, nm_val.second); + + // FIXME: it would be more convenient if stack_frame::workspace + // returned a Cell object directly instead of a Cell in an + // octave_value object. + + std::shared_ptr frames = m_stack_context.lock (); + + Cell cell_frames; + + if (frames) + { + octave_value ov_frames = frames->workspace (); + cell_frames = ov_frames.cell_value (); + } + + octave_idx_type num_frames = cell_frames.numel (); + + // FIXME: It seems there should be a simple way to concatenate + // cells... + Cell retval = Cell (num_frames+1, 1); + retval(0) = m_local_vars; + for (octave_idx_type i = 0; i < num_frames; i++) + retval(i+1) = cell_frames(i); + + return retval; +} + +bool is_equal_to (const weak_anonymous_fcn_handle& fh1, + const weak_anonymous_fcn_handle& fh2) +{ + if (fh1.m_name == fh2.m_name + && fh1.m_fcn.is_defined () && fh2.m_fcn.is_defined ()) + return fh1.m_fcn.is_copy_of (fh2.m_fcn); + else + return false; +} OCTAVE_END_NAMESPACE(octave) @@ -2957,7 +2957,7 @@ is >> name; new_rep.reset (new octave::simple_fcn_handle (name, fpath, - octaveroot)); + octaveroot)); } else if (subtype == "scopedfunction") { @@ -2965,7 +2965,7 @@ is >> name; new_rep.reset (new octave::scoped_fcn_handle (name, fpath, - octaveroot)); + octaveroot)); } else if (subtype == "anonymous") new_rep.reset (new octave::anonymous_fcn_handle ()); @@ -2975,7 +2975,7 @@ is >> name; new_rep.reset (new octave::nested_fcn_handle (name, fpath, - octaveroot)); + octaveroot)); } else if (subtype == "classsimple") { @@ -2983,7 +2983,7 @@ is >> name; new_rep.reset (new octave::class_simple_fcn_handle (name, fpath, - octaveroot)); + octaveroot)); } } @@ -3084,7 +3084,7 @@ new_rep.reset (new octave::nested_fcn_handle (name, fpath, octaveroot)); else if (subtype == "classsimple") new_rep.reset (new octave::class_simple_fcn_handle (name, fpath, - octaveroot)); + octaveroot)); } if (! new_rep) @@ -3238,7 +3238,7 @@ new_rep.reset (new octave::nested_fcn_handle (name, fpath, octaveroot)); else if (subtype == "classsimple") new_rep.reset (new octave::class_simple_fcn_handle (name, fpath, - octaveroot)); + octaveroot)); } bool status = false; @@ -3459,7 +3459,8 @@ if (args.length () != 1) print_usage (); - octave_fcn_handle *fh = args(0).xfcn_handle_value ("functions: FCN_HANDLE argument must be a function handle object"); + octave_fcn_handle *fh = args( + 0).xfcn_handle_value ("functions: FCN_HANDLE argument must be a function handle object"); return ovl (fh->info ()); } @@ -3475,7 +3476,8 @@ if (args.length () != 1) print_usage (); - octave_fcn_handle *fh = args(0).xfcn_handle_value ("func2str: FCN_HANDLE argument must be a function handle object"); + octave_fcn_handle *fh = args( + 0).xfcn_handle_value ("func2str: FCN_HANDLE argument must be a function handle object"); if (! fh) error ("func2str: FCN_HANDLE must be a valid function handle"); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-fcn-handle.h --- a/libinterp/octave-value/ov-fcn-handle.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-fcn-handle.h Thu Dec 01 20:05:44 2022 -0800 @@ -42,132 +42,132 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; - class tree_evaluator; +class interpreter; +class tree_evaluator; - // Function handles. +// Function handles. - class base_fcn_handle - { - public: +class base_fcn_handle +{ +public: - base_fcn_handle (const std::string& name = "", - const std::string& file = "") - : m_name (name), m_file (file) - { } + base_fcn_handle (const std::string& name = "", + const std::string& file = "") + : m_name (name), m_file (file) + { } - base_fcn_handle (const base_fcn_handle&) = default; + base_fcn_handle (const base_fcn_handle&) = default; - virtual ~base_fcn_handle (void) = default; + virtual ~base_fcn_handle (void) = default; - virtual base_fcn_handle * clone (void) const = 0; + virtual base_fcn_handle * clone (void) const = 0; - virtual std::string type (void) const = 0; + virtual std::string type (void) const = 0; - virtual bool is_internal (void) const { return false; } + virtual bool is_internal (void) const { return false; } - virtual bool is_simple (void) const { return false; } + virtual bool is_simple (void) const { return false; } - virtual bool is_scoped (void) const { return false; } + virtual bool is_scoped (void) const { return false; } - virtual bool is_nested (void) const { return false; } + virtual bool is_nested (void) const { return false; } - virtual bool is_nested (const std::shared_ptr&) const - { - return false; - } + virtual bool is_nested (const std::shared_ptr&) const + { + return false; + } - virtual bool is_weak_nested (void) const { return false; } + virtual bool is_weak_nested (void) const { return false; } - virtual bool is_class_simple (void) const { return false; } + virtual bool is_class_simple (void) const { return false; } - virtual bool is_anonymous (void) const { return false; } + virtual bool is_anonymous (void) const { return false; } - virtual bool is_weak_anonymous (void) const { return false; } + virtual bool is_weak_anonymous (void) const { return false; } - virtual octave_value make_weak_nested_handle (void) const; + virtual octave_value make_weak_nested_handle (void) const; - virtual octave_value make_weak_anonymous_handle (void) const; + virtual octave_value make_weak_anonymous_handle (void) const; - std::string fcn_name (void) const { return m_name; } + std::string fcn_name (void) const { return m_name; } - std::string file (void) const { return m_file; } + std::string file (void) const { return m_file; } - octave_value_list - subsref (const std::string& type, const std::list& idx, - int nargout); + octave_value_list + subsref (const std::string& type, const std::list& idx, + int nargout); - virtual octave_value_list - call (int nargout, const octave_value_list& args) = 0; + virtual octave_value_list + call (int nargout, const octave_value_list& args) = 0; - // FIXME: These must go away. They don't do the right thing for - // scoping or overloads. - virtual octave_function * function_value (bool = false) - { - return nullptr; - } + // FIXME: These must go away. They don't do the right thing for + // scoping or overloads. + virtual octave_function * function_value (bool = false) + { + return nullptr; + } - virtual octave_user_function * user_function_value (bool = false) - { - return nullptr; - } + virtual octave_user_function * user_function_value (bool = false) + { + return nullptr; + } - virtual octave_value fcn_val (void) { return octave_value (); } + virtual octave_value fcn_val (void) { return octave_value (); } - virtual octave_value workspace (void) const { return octave_value (); } + virtual octave_value workspace (void) const { return octave_value (); } - // Should be const. - virtual octave_scalar_map info (void) { return octave_scalar_map (); } + // Should be const. + virtual octave_scalar_map info (void) { return octave_scalar_map (); } - virtual void set_dispatch_class (const std::string& /*class_name*/) { } + virtual void set_dispatch_class (const std::string& /*class_name*/) { } - virtual std::string get_dispatch_class (void) const { return ""; } + virtual std::string get_dispatch_class (void) const { return ""; } - octave_value convert_to_str_internal (bool pad, bool force, char type) const; + octave_value convert_to_str_internal (bool pad, bool force, char type) const; - virtual bool save_ascii (std::ostream& os); + virtual bool save_ascii (std::ostream& os); - virtual bool load_ascii (std::istream& is); + virtual bool load_ascii (std::istream& is); - virtual bool save_binary (std::ostream& os, bool save_as_floats); + virtual bool save_binary (std::ostream& os, bool save_as_floats); - virtual bool load_binary (std::istream& is, bool swap, - mach_info::float_format fmt); + virtual bool load_binary (std::istream& is, bool swap, + mach_info::float_format fmt); - virtual bool save_hdf5 (octave_hdf5_id loc_id, const char *name, - bool save_as_floats); + virtual bool save_hdf5 (octave_hdf5_id loc_id, const char *name, + bool save_as_floats); - virtual bool load_hdf5 (octave_hdf5_id& group_hid, - octave_hdf5_id& space_hid, - octave_hdf5_id& type_hid); + virtual bool load_hdf5 (octave_hdf5_id& group_hid, + octave_hdf5_id& space_hid, + octave_hdf5_id& type_hid); - virtual void print_raw (std::ostream&, bool /*pr_as_read_syntax*/, - int /*current_print_indent_level*/) const - { } + virtual void print_raw (std::ostream&, bool /*pr_as_read_syntax*/, + int /*current_print_indent_level*/) const + { } - // Function handles are printed without a newline by default. - virtual bool print_as_scalar (void) const { return true; } + // Function handles are printed without a newline by default. + virtual bool print_as_scalar (void) const { return true; } - virtual bool - set_fcn (const std::string& /*octaveroot*/, const std::string& /*fpath*/) - { - return false; - } + virtual bool + set_fcn (const std::string& /*octaveroot*/, const std::string& /*fpath*/) + { + return false; + } - protected: +protected: - void warn_load (const char *file_type) const; - void warn_save (const char *file_type) const; + void warn_load (const char *file_type) const; + void warn_save (const char *file_type) const; - void unimplemented (const char *op, const char *fmt) const; + void unimplemented (const char *op, const char *fmt) const; - // The name of the handle, not including the "@", or the text of the - // anonymous function. - std::string m_name; + // The name of the handle, not including the "@", or the text of the + // anonymous function. + std::string m_name; - // The name of the file where the named function was defined. - std::string m_file; - }; + // The name of the file where the named function was defined. + std::string m_file; +}; OCTAVE_END_NAMESPACE(octave) @@ -219,7 +219,7 @@ octave_fcn_handle (const octave_value& fcn, const octave::stack_frame::local_vars_map& local_vars, const std::shared_ptr& closure_frames - = std::shared_ptr ()); + = std::shared_ptr ()); octave_fcn_handle (octave::base_fcn_handle *rep); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-fcn.h --- a/libinterp/octave-value/ov-fcn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-fcn.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,9 +40,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class stack_frame; - class tree_evaluator; - class tree_walker; +class stack_frame; +class tree_evaluator; +class tree_walker; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-float.cc --- a/libinterp/octave-value/ov-float.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-float.cc Thu Dec 01 20:05:44 2022 -0800 @@ -363,49 +363,49 @@ case umap_ ## UMAP: \ return octave_value (FCN (scalar)) - SCALAR_MAPPER (abs, ::fabsf); - SCALAR_MAPPER (acos, octave::math::rc_acos); - SCALAR_MAPPER (acosh, octave::math::rc_acosh); - SCALAR_MAPPER (angle, std::arg); - SCALAR_MAPPER (arg, std::arg); - SCALAR_MAPPER (asin, octave::math::rc_asin); - SCALAR_MAPPER (asinh, octave::math::asinh); - SCALAR_MAPPER (atan, ::atanf); - SCALAR_MAPPER (atanh, octave::math::rc_atanh); - SCALAR_MAPPER (erf, octave::math::erf); - SCALAR_MAPPER (erfinv, octave::math::erfinv); - SCALAR_MAPPER (erfcinv, octave::math::erfcinv); - SCALAR_MAPPER (erfc, octave::math::erfc); - SCALAR_MAPPER (erfcx, octave::math::erfcx); - SCALAR_MAPPER (erfi, octave::math::erfi); - SCALAR_MAPPER (dawson, octave::math::dawson); - SCALAR_MAPPER (gamma, octave::math::gamma); - SCALAR_MAPPER (lgamma, octave::math::rc_lgamma); - SCALAR_MAPPER (cbrt, octave::math::cbrt); - SCALAR_MAPPER (ceil, ::ceilf); - SCALAR_MAPPER (cos, ::cosf); - SCALAR_MAPPER (cosh, ::coshf); - SCALAR_MAPPER (exp, ::expf); - SCALAR_MAPPER (expm1, octave::math::expm1); - SCALAR_MAPPER (fix, octave::math::fix); - SCALAR_MAPPER (floor, std::floor); - SCALAR_MAPPER (log, octave::math::rc_log); - SCALAR_MAPPER (log2, octave::math::rc_log2); - SCALAR_MAPPER (log10, octave::math::rc_log10); - SCALAR_MAPPER (log1p, octave::math::rc_log1p); - SCALAR_MAPPER (round, octave::math::round); - SCALAR_MAPPER (roundb, octave::math::roundb); - SCALAR_MAPPER (signum, octave::math::signum); - SCALAR_MAPPER (sin, ::sinf); - SCALAR_MAPPER (sinh, ::sinhf); - SCALAR_MAPPER (sqrt, octave::math::rc_sqrt); - SCALAR_MAPPER (tan, ::tanf); - SCALAR_MAPPER (tanh, ::tanhf); - SCALAR_MAPPER (isfinite, octave::math::isfinite); - SCALAR_MAPPER (isinf, octave::math::isinf); - SCALAR_MAPPER (isna, octave::math::isna); - SCALAR_MAPPER (isnan, octave::math::isnan); - SCALAR_MAPPER (xsignbit, octave::math::signbit); + SCALAR_MAPPER (abs, ::fabsf); + SCALAR_MAPPER (acos, octave::math::rc_acos); + SCALAR_MAPPER (acosh, octave::math::rc_acosh); + SCALAR_MAPPER (angle, std::arg); + SCALAR_MAPPER (arg, std::arg); + SCALAR_MAPPER (asin, octave::math::rc_asin); + SCALAR_MAPPER (asinh, octave::math::asinh); + SCALAR_MAPPER (atan, ::atanf); + SCALAR_MAPPER (atanh, octave::math::rc_atanh); + SCALAR_MAPPER (erf, octave::math::erf); + SCALAR_MAPPER (erfinv, octave::math::erfinv); + SCALAR_MAPPER (erfcinv, octave::math::erfcinv); + SCALAR_MAPPER (erfc, octave::math::erfc); + SCALAR_MAPPER (erfcx, octave::math::erfcx); + SCALAR_MAPPER (erfi, octave::math::erfi); + SCALAR_MAPPER (dawson, octave::math::dawson); + SCALAR_MAPPER (gamma, octave::math::gamma); + SCALAR_MAPPER (lgamma, octave::math::rc_lgamma); + SCALAR_MAPPER (cbrt, octave::math::cbrt); + SCALAR_MAPPER (ceil, ::ceilf); + SCALAR_MAPPER (cos, ::cosf); + SCALAR_MAPPER (cosh, ::coshf); + SCALAR_MAPPER (exp, ::expf); + SCALAR_MAPPER (expm1, octave::math::expm1); + SCALAR_MAPPER (fix, octave::math::fix); + SCALAR_MAPPER (floor, std::floor); + SCALAR_MAPPER (log, octave::math::rc_log); + SCALAR_MAPPER (log2, octave::math::rc_log2); + SCALAR_MAPPER (log10, octave::math::rc_log10); + SCALAR_MAPPER (log1p, octave::math::rc_log1p); + SCALAR_MAPPER (round, octave::math::round); + SCALAR_MAPPER (roundb, octave::math::roundb); + SCALAR_MAPPER (signum, octave::math::signum); + SCALAR_MAPPER (sin, ::sinf); + SCALAR_MAPPER (sinh, ::sinhf); + SCALAR_MAPPER (sqrt, octave::math::rc_sqrt); + SCALAR_MAPPER (tan, ::tanf); + SCALAR_MAPPER (tanh, ::tanhf); + SCALAR_MAPPER (isfinite, octave::math::isfinite); + SCALAR_MAPPER (isinf, octave::math::isinf); + SCALAR_MAPPER (isna, octave::math::isna); + SCALAR_MAPPER (isnan, octave::math::isnan); + SCALAR_MAPPER (xsignbit, octave::math::signbit); // Special cases for Matlab compatibility. case umap_xtolower: @@ -436,7 +436,7 @@ bool octave_float_scalar::fast_elem_insert_self (void *where, - builtin_type_t btyp) const + builtin_type_t btyp) const { // Support inline real->complex conversion. diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-flt-complex.cc --- a/libinterp/octave-value/ov-flt-complex.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-flt-complex.cc Thu Dec 01 20:05:44 2022 -0800 @@ -448,46 +448,46 @@ case umap_ ## UMAP: \ return octave_value (FCN (scalar)) - SCALAR_MAPPER (abs, std::abs); - SCALAR_MAPPER (acos, octave::math::acos); - SCALAR_MAPPER (acosh, octave::math::acosh); - SCALAR_MAPPER (angle, std::arg); - SCALAR_MAPPER (arg, std::arg); - SCALAR_MAPPER (asin, octave::math::asin); - SCALAR_MAPPER (asinh, octave::math::asinh); - SCALAR_MAPPER (atan, octave::math::atan); - SCALAR_MAPPER (atanh, octave::math::atanh); - SCALAR_MAPPER (erf, octave::math::erf); - SCALAR_MAPPER (erfc, octave::math::erfc); - SCALAR_MAPPER (erfcx, octave::math::erfcx); - SCALAR_MAPPER (erfi, octave::math::erfi); - SCALAR_MAPPER (dawson, octave::math::dawson); - SCALAR_MAPPER (ceil, octave::math::ceil); - SCALAR_MAPPER (conj, std::conj); - SCALAR_MAPPER (cos, std::cos); - SCALAR_MAPPER (cosh, std::cosh); - SCALAR_MAPPER (exp, std::exp); - SCALAR_MAPPER (expm1, octave::math::expm1); - SCALAR_MAPPER (fix, octave::math::fix); - SCALAR_MAPPER (floor, octave::math::floor); - SCALAR_MAPPER (imag, std::imag); - SCALAR_MAPPER (log, std::log); - SCALAR_MAPPER (log2, octave::math::log2); - SCALAR_MAPPER (log10, std::log10); - SCALAR_MAPPER (log1p, octave::math::log1p); - SCALAR_MAPPER (real, std::real); - SCALAR_MAPPER (round, octave::math::round); - SCALAR_MAPPER (roundb, octave::math::roundb); - SCALAR_MAPPER (signum, octave::math::signum); - SCALAR_MAPPER (sin, std::sin); - SCALAR_MAPPER (sinh, std::sinh); - SCALAR_MAPPER (sqrt, std::sqrt); - SCALAR_MAPPER (tan, std::tan); - SCALAR_MAPPER (tanh, std::tanh); - SCALAR_MAPPER (isfinite, octave::math::isfinite); - SCALAR_MAPPER (isinf, octave::math::isinf); - SCALAR_MAPPER (isna, octave::math::isna); - SCALAR_MAPPER (isnan, octave::math::isnan); + SCALAR_MAPPER (abs, std::abs); + SCALAR_MAPPER (acos, octave::math::acos); + SCALAR_MAPPER (acosh, octave::math::acosh); + SCALAR_MAPPER (angle, std::arg); + SCALAR_MAPPER (arg, std::arg); + SCALAR_MAPPER (asin, octave::math::asin); + SCALAR_MAPPER (asinh, octave::math::asinh); + SCALAR_MAPPER (atan, octave::math::atan); + SCALAR_MAPPER (atanh, octave::math::atanh); + SCALAR_MAPPER (erf, octave::math::erf); + SCALAR_MAPPER (erfc, octave::math::erfc); + SCALAR_MAPPER (erfcx, octave::math::erfcx); + SCALAR_MAPPER (erfi, octave::math::erfi); + SCALAR_MAPPER (dawson, octave::math::dawson); + SCALAR_MAPPER (ceil, octave::math::ceil); + SCALAR_MAPPER (conj, std::conj); + SCALAR_MAPPER (cos, std::cos); + SCALAR_MAPPER (cosh, std::cosh); + SCALAR_MAPPER (exp, std::exp); + SCALAR_MAPPER (expm1, octave::math::expm1); + SCALAR_MAPPER (fix, octave::math::fix); + SCALAR_MAPPER (floor, octave::math::floor); + SCALAR_MAPPER (imag, std::imag); + SCALAR_MAPPER (log, std::log); + SCALAR_MAPPER (log2, octave::math::log2); + SCALAR_MAPPER (log10, std::log10); + SCALAR_MAPPER (log1p, octave::math::log1p); + SCALAR_MAPPER (real, std::real); + SCALAR_MAPPER (round, octave::math::round); + SCALAR_MAPPER (roundb, octave::math::roundb); + SCALAR_MAPPER (signum, octave::math::signum); + SCALAR_MAPPER (sin, std::sin); + SCALAR_MAPPER (sinh, std::sinh); + SCALAR_MAPPER (sqrt, std::sqrt); + SCALAR_MAPPER (tan, std::tan); + SCALAR_MAPPER (tanh, std::tanh); + SCALAR_MAPPER (isfinite, octave::math::isfinite); + SCALAR_MAPPER (isinf, octave::math::isinf); + SCALAR_MAPPER (isna, octave::math::isna); + SCALAR_MAPPER (isnan, octave::math::isnan); // Special cases for Matlab compatibility case umap_xtolower: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-flt-cx-diag.cc --- a/libinterp/octave-value/ov-flt-cx-diag.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-flt-cx-diag.cc Thu Dec 01 20:05:44 2022 -0800 @@ -55,7 +55,7 @@ octave_float_complex_diag_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_float_complex_matrix::static_type_id ()); + octave_float_complex_matrix::static_type_id ()); } octave_base_value * @@ -160,7 +160,7 @@ bool octave_float_complex_diag_matrix::save_binary (std::ostream& os, - bool /* save_as_floats */) + bool /* save_as_floats */) { int32_t r = m_matrix.rows (); @@ -185,7 +185,7 @@ bool octave_float_complex_diag_matrix::load_binary (std::istream& is, bool swap, - octave::mach_info::float_format fmt) + octave::mach_info::float_format fmt) { int32_t r, c; char tmp; @@ -215,7 +215,7 @@ bool octave_float_complex_diag_matrix::chk_valid_scalar (const octave_value& val, - FloatComplex& x) const + FloatComplex& x) const { bool retval = val.is_complex_scalar () || val.is_real_scalar (); if (retval) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-flt-cx-mat.cc --- a/libinterp/octave-value/ov-flt-cx-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-flt-cx-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -341,7 +341,7 @@ std::string old_locale (prev_locale ? prev_locale : ""); std::setlocale (LC_ALL, "C"); octave::unwind_action act - ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); + ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); if (kw == "ndims") { @@ -430,7 +430,7 @@ bool octave_float_complex_matrix::load_binary (std::istream& is, bool swap, - octave::mach_info::float_format fmt) + octave::mach_info::float_format fmt) { char tmp; int32_t mdims; @@ -745,48 +745,48 @@ case umap_ ## UMAP: \ return octave_value (m_matrix.FCN ()) - ARRAY_METHOD_MAPPER (abs, abs); - ARRAY_METHOD_MAPPER (isnan, isnan); - ARRAY_METHOD_MAPPER (isinf, isinf); - ARRAY_METHOD_MAPPER (isfinite, isfinite); + ARRAY_METHOD_MAPPER (abs, abs); + ARRAY_METHOD_MAPPER (isnan, isnan); + ARRAY_METHOD_MAPPER (isinf, isinf); + ARRAY_METHOD_MAPPER (isfinite, isfinite); #define ARRAY_MAPPER(UMAP, TYPE, FCN) \ case umap_ ## UMAP: \ return octave_value (m_matrix.map (FCN)) - ARRAY_MAPPER (acos, FloatComplex, octave::math::acos); - ARRAY_MAPPER (acosh, FloatComplex, octave::math::acosh); - ARRAY_MAPPER (angle, float, std::arg); - ARRAY_MAPPER (arg, float, std::arg); - ARRAY_MAPPER (asin, FloatComplex, octave::math::asin); - ARRAY_MAPPER (asinh, FloatComplex, octave::math::asinh); - ARRAY_MAPPER (atan, FloatComplex, octave::math::atan); - ARRAY_MAPPER (atanh, FloatComplex, octave::math::atanh); - ARRAY_MAPPER (erf, FloatComplex, octave::math::erf); - ARRAY_MAPPER (erfc, FloatComplex, octave::math::erfc); - ARRAY_MAPPER (erfcx, FloatComplex, octave::math::erfcx); - ARRAY_MAPPER (erfi, FloatComplex, octave::math::erfi); - ARRAY_MAPPER (dawson, FloatComplex, octave::math::dawson); - ARRAY_MAPPER (ceil, FloatComplex, octave::math::ceil); - ARRAY_MAPPER (cos, FloatComplex, std::cos); - ARRAY_MAPPER (cosh, FloatComplex, std::cosh); - ARRAY_MAPPER (exp, FloatComplex, std::exp); - ARRAY_MAPPER (expm1, FloatComplex, octave::math::expm1); - ARRAY_MAPPER (fix, FloatComplex, octave::math::fix); - ARRAY_MAPPER (floor, FloatComplex, octave::math::floor); - ARRAY_MAPPER (log, FloatComplex, std::log); - ARRAY_MAPPER (log2, FloatComplex, octave::math::log2); - ARRAY_MAPPER (log10, FloatComplex, std::log10); - ARRAY_MAPPER (log1p, FloatComplex, octave::math::log1p); - ARRAY_MAPPER (round, FloatComplex, octave::math::round); - ARRAY_MAPPER (roundb, FloatComplex, octave::math::roundb); - ARRAY_MAPPER (signum, FloatComplex, octave::math::signum); - ARRAY_MAPPER (sin, FloatComplex, std::sin); - ARRAY_MAPPER (sinh, FloatComplex, std::sinh); - ARRAY_MAPPER (sqrt, FloatComplex, std::sqrt); - ARRAY_MAPPER (tan, FloatComplex, std::tan); - ARRAY_MAPPER (tanh, FloatComplex, std::tanh); - ARRAY_MAPPER (isna, bool, octave::math::isna); + ARRAY_MAPPER (acos, FloatComplex, octave::math::acos); + ARRAY_MAPPER (acosh, FloatComplex, octave::math::acosh); + ARRAY_MAPPER (angle, float, std::arg); + ARRAY_MAPPER (arg, float, std::arg); + ARRAY_MAPPER (asin, FloatComplex, octave::math::asin); + ARRAY_MAPPER (asinh, FloatComplex, octave::math::asinh); + ARRAY_MAPPER (atan, FloatComplex, octave::math::atan); + ARRAY_MAPPER (atanh, FloatComplex, octave::math::atanh); + ARRAY_MAPPER (erf, FloatComplex, octave::math::erf); + ARRAY_MAPPER (erfc, FloatComplex, octave::math::erfc); + ARRAY_MAPPER (erfcx, FloatComplex, octave::math::erfcx); + ARRAY_MAPPER (erfi, FloatComplex, octave::math::erfi); + ARRAY_MAPPER (dawson, FloatComplex, octave::math::dawson); + ARRAY_MAPPER (ceil, FloatComplex, octave::math::ceil); + ARRAY_MAPPER (cos, FloatComplex, std::cos); + ARRAY_MAPPER (cosh, FloatComplex, std::cosh); + ARRAY_MAPPER (exp, FloatComplex, std::exp); + ARRAY_MAPPER (expm1, FloatComplex, octave::math::expm1); + ARRAY_MAPPER (fix, FloatComplex, octave::math::fix); + ARRAY_MAPPER (floor, FloatComplex, octave::math::floor); + ARRAY_MAPPER (log, FloatComplex, std::log); + ARRAY_MAPPER (log2, FloatComplex, octave::math::log2); + ARRAY_MAPPER (log10, FloatComplex, std::log10); + ARRAY_MAPPER (log1p, FloatComplex, octave::math::log1p); + ARRAY_MAPPER (round, FloatComplex, octave::math::round); + ARRAY_MAPPER (roundb, FloatComplex, octave::math::roundb); + ARRAY_MAPPER (signum, FloatComplex, octave::math::signum); + ARRAY_MAPPER (sin, FloatComplex, std::sin); + ARRAY_MAPPER (sinh, FloatComplex, std::sinh); + ARRAY_MAPPER (sqrt, FloatComplex, std::sqrt); + ARRAY_MAPPER (tan, FloatComplex, std::tan); + ARRAY_MAPPER (tanh, FloatComplex, std::tanh); + ARRAY_MAPPER (isna, bool, octave::math::isna); default: return octave_base_value::map (umap); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-flt-re-diag.cc --- a/libinterp/octave-value/ov-flt-re-diag.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-flt-re-diag.cc Thu Dec 01 20:05:44 2022 -0800 @@ -54,7 +54,7 @@ octave_float_diag_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_float_matrix::static_type_id ()); + octave_float_matrix::static_type_id ()); } octave_base_value * @@ -232,7 +232,7 @@ bool octave_float_diag_matrix::chk_valid_scalar (const octave_value& val, - float& x) const + float& x) const { bool retval = val.is_real_scalar (); if (retval) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-flt-re-mat.cc --- a/libinterp/octave-value/ov-flt-re-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-flt-re-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -417,7 +417,7 @@ std::string old_locale (prev_locale ? prev_locale : ""); std::setlocale (LC_ALL, "C"); octave::unwind_action act - ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); + ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); if (kw == "ndims") { @@ -795,15 +795,15 @@ case umap_conj: return m_matrix; - // Mappers handled specially. + // Mappers handled specially. #define ARRAY_METHOD_MAPPER(UMAP, FCN) \ case umap_ ## UMAP: \ return octave_value (m_matrix.FCN ()) - ARRAY_METHOD_MAPPER (abs, abs); - ARRAY_METHOD_MAPPER (isnan, isnan); - ARRAY_METHOD_MAPPER (isinf, isinf); - ARRAY_METHOD_MAPPER (isfinite, isfinite); + ARRAY_METHOD_MAPPER (abs, abs); + ARRAY_METHOD_MAPPER (isnan, isnan); + ARRAY_METHOD_MAPPER (isinf, isinf); + ARRAY_METHOD_MAPPER (isfinite, isfinite); #define ARRAY_MAPPER(UMAP, TYPE, FCN) \ case umap_ ## UMAP: \ @@ -813,45 +813,45 @@ case umap_ ## UMAP: \ return do_rc_map (m_matrix, FCN) - RC_ARRAY_MAPPER (acos, FloatComplex, octave::math::rc_acos); - RC_ARRAY_MAPPER (acosh, FloatComplex, octave::math::rc_acosh); - ARRAY_MAPPER (angle, float, std::arg); - ARRAY_MAPPER (arg, float, std::arg); - RC_ARRAY_MAPPER (asin, FloatComplex, octave::math::rc_asin); - ARRAY_MAPPER (asinh, float, octave::math::asinh); - ARRAY_MAPPER (atan, float, ::atanf); - RC_ARRAY_MAPPER (atanh, FloatComplex, octave::math::rc_atanh); - ARRAY_MAPPER (erf, float, octave::math::erf); - ARRAY_MAPPER (erfinv, float, octave::math::erfinv); - ARRAY_MAPPER (erfcinv, float, octave::math::erfcinv); - ARRAY_MAPPER (erfc, float, octave::math::erfc); - ARRAY_MAPPER (erfcx, float, octave::math::erfcx); - ARRAY_MAPPER (erfi, float, octave::math::erfi); - ARRAY_MAPPER (dawson, float, octave::math::dawson); - ARRAY_MAPPER (gamma, float, octave::math::gamma); - RC_ARRAY_MAPPER (lgamma, FloatComplex, octave::math::rc_lgamma); - ARRAY_MAPPER (cbrt, float, octave::math::cbrt); - ARRAY_MAPPER (ceil, float, ::ceilf); - ARRAY_MAPPER (cos, float, ::cosf); - ARRAY_MAPPER (cosh, float, ::coshf); - ARRAY_MAPPER (exp, float, ::expf); - ARRAY_MAPPER (expm1, float, octave::math::expm1); - ARRAY_MAPPER (fix, float, octave::math::fix); - ARRAY_MAPPER (floor, float, ::floorf); - RC_ARRAY_MAPPER (log, FloatComplex, octave::math::rc_log); - RC_ARRAY_MAPPER (log2, FloatComplex, octave::math::rc_log2); - RC_ARRAY_MAPPER (log10, FloatComplex, octave::math::rc_log10); - RC_ARRAY_MAPPER (log1p, FloatComplex, octave::math::rc_log1p); - ARRAY_MAPPER (round, float, octave::math::round); - ARRAY_MAPPER (roundb, float, octave::math::roundb); - ARRAY_MAPPER (signum, float, octave::math::signum); - ARRAY_MAPPER (sin, float, ::sinf); - ARRAY_MAPPER (sinh, float, ::sinhf); - RC_ARRAY_MAPPER (sqrt, FloatComplex, octave::math::rc_sqrt); - ARRAY_MAPPER (tan, float, ::tanf); - ARRAY_MAPPER (tanh, float, ::tanhf); - ARRAY_MAPPER (isna, bool, octave::math::isna); - ARRAY_MAPPER (xsignbit, float, octave::math::signbit); + RC_ARRAY_MAPPER (acos, FloatComplex, octave::math::rc_acos); + RC_ARRAY_MAPPER (acosh, FloatComplex, octave::math::rc_acosh); + ARRAY_MAPPER (angle, float, std::arg); + ARRAY_MAPPER (arg, float, std::arg); + RC_ARRAY_MAPPER (asin, FloatComplex, octave::math::rc_asin); + ARRAY_MAPPER (asinh, float, octave::math::asinh); + ARRAY_MAPPER (atan, float, ::atanf); + RC_ARRAY_MAPPER (atanh, FloatComplex, octave::math::rc_atanh); + ARRAY_MAPPER (erf, float, octave::math::erf); + ARRAY_MAPPER (erfinv, float, octave::math::erfinv); + ARRAY_MAPPER (erfcinv, float, octave::math::erfcinv); + ARRAY_MAPPER (erfc, float, octave::math::erfc); + ARRAY_MAPPER (erfcx, float, octave::math::erfcx); + ARRAY_MAPPER (erfi, float, octave::math::erfi); + ARRAY_MAPPER (dawson, float, octave::math::dawson); + ARRAY_MAPPER (gamma, float, octave::math::gamma); + RC_ARRAY_MAPPER (lgamma, FloatComplex, octave::math::rc_lgamma); + ARRAY_MAPPER (cbrt, float, octave::math::cbrt); + ARRAY_MAPPER (ceil, float, ::ceilf); + ARRAY_MAPPER (cos, float, ::cosf); + ARRAY_MAPPER (cosh, float, ::coshf); + ARRAY_MAPPER (exp, float, ::expf); + ARRAY_MAPPER (expm1, float, octave::math::expm1); + ARRAY_MAPPER (fix, float, octave::math::fix); + ARRAY_MAPPER (floor, float, ::floorf); + RC_ARRAY_MAPPER (log, FloatComplex, octave::math::rc_log); + RC_ARRAY_MAPPER (log2, FloatComplex, octave::math::rc_log2); + RC_ARRAY_MAPPER (log10, FloatComplex, octave::math::rc_log10); + RC_ARRAY_MAPPER (log1p, FloatComplex, octave::math::rc_log1p); + ARRAY_MAPPER (round, float, octave::math::round); + ARRAY_MAPPER (roundb, float, octave::math::roundb); + ARRAY_MAPPER (signum, float, octave::math::signum); + ARRAY_MAPPER (sin, float, ::sinf); + ARRAY_MAPPER (sinh, float, ::sinhf); + RC_ARRAY_MAPPER (sqrt, FloatComplex, octave::math::rc_sqrt); + ARRAY_MAPPER (tan, float, ::tanf); + ARRAY_MAPPER (tanh, float, ::tanhf); + ARRAY_MAPPER (isna, bool, octave::math::isna); + ARRAY_MAPPER (xsignbit, float, octave::math::signbit); // Special cases for Matlab compatibility. case umap_xtolower: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-flt-re-mat.h --- a/libinterp/octave-value/ov-flt-re-mat.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-flt-re-mat.h Thu Dec 01 20:05:44 2022 -0800 @@ -93,7 +93,7 @@ octave::idx_vector index_vector (bool /* require_integers */ = false) const { return m_idx_cache ? *m_idx_cache - : set_idx_cache (octave::idx_vector (m_matrix)); + : set_idx_cache (octave::idx_vector (m_matrix)); } builtin_type_t builtin_type (void) const { return btyp_float; } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-intx.h --- a/libinterp/octave-value/ov-intx.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-intx.h Thu Dec 01 20:05:44 2022 -0800 @@ -64,7 +64,7 @@ OCTAVE_VALUE_INT_MATRIX_T (const Array& nda) : octave_base_int_matrix> - (intNDArray (nda)) { } + (intNDArray (nda)) { } ~OCTAVE_VALUE_INT_MATRIX_T (void) = default; @@ -304,7 +304,7 @@ octave::idx_vector index_vector (bool /* require_integers */ = false) const { return m_idx_cache ? *m_idx_cache - : set_idx_cache (octave::idx_vector (m_matrix)); + : set_idx_cache (octave::idx_vector (m_matrix)); } int write (octave::stream& os, int block_size, diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-java.cc --- a/libinterp/octave-value/ov-java.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-java.cc Thu Dec 01 20:05:44 2022 -0800 @@ -89,10 +89,10 @@ #define TO_JNIENV(env) reinterpret_cast (env) typedef jint (JNICALL *JNI_CreateJavaVM_t) (JavaVM **pvm, JNIEnv **penv, - void *args); + void *args); typedef jint (JNICALL *JNI_GetCreatedJavaVMs_t) (JavaVM **pvm, jsize bufLen, - jsize *nVMs); + jsize *nVMs); template class java_local_ref @@ -210,8 +210,8 @@ static octave::dynamic_library jvm_lib; -static std::map listener_map; -static std::map octave_ref_map; +static std::map listener_map; +static std::map octave_ref_map; static int octave_java_refcount = 0; //! The thread id of the currently executing thread or @c -1 if this is @@ -226,98 +226,98 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class JVMArgs +class JVMArgs +{ +public: + + JVMArgs (void) + { + m_vm_args.version = JNI_VERSION_1_6; + m_vm_args.nOptions = 0; + m_vm_args.options = nullptr; + m_vm_args.ignoreUnrecognized = false; + } + + ~JVMArgs (void) + { + clean (); + } + + JavaVMInitArgs * to_args () + { + update (); + return &m_vm_args; + } + + void add (const std::string& opt) + { + m_java_opts.push_back (opt); + } + + void read_java_opts (const std::string& filename) { - public: - - JVMArgs (void) - { - m_vm_args.version = JNI_VERSION_1_6; - m_vm_args.nOptions = 0; - m_vm_args.options = nullptr; - m_vm_args.ignoreUnrecognized = false; - } - - ~JVMArgs (void) - { - clean (); - } - - JavaVMInitArgs * to_args () - { - update (); - return &m_vm_args; - } - - void add (const std::string& opt) - { - m_java_opts.push_back (opt); - } - - void read_java_opts (const std::string& filename) - { - std::ifstream js = sys::ifstream (filename.c_str ()); - - if (! js.bad () && ! js.fail ()) - { - std::string line; - - while (! js.eof () && ! js.fail ()) - { - std::getline (js, line); - - if (line.find ('-') == 0) - m_java_opts.push_back (line); - else if (line.length () > 0 && Vdebug_java) - warning ("invalid JVM option, skipping: %s", line.c_str ()); - } - } - } - - private: - - void clean (void) - { - if (m_vm_args.options != nullptr) - { - for (int i = 0; i < m_vm_args.nOptions; i++) - delete [] m_vm_args.options[i].optionString; - - delete [] m_vm_args.options; - - m_vm_args.options = nullptr; - m_vm_args.nOptions = 0; - } - } - - void update (void) - { - clean (); - - if (m_java_opts.size () > 0) - { - int index = 0; - - m_vm_args.nOptions = m_java_opts.size (); - m_vm_args.options = new JavaVMOption [m_vm_args.nOptions]; - - for (const auto& opt : m_java_opts) - { - if (Vdebug_java) - octave_stdout << opt << std::endl; - m_vm_args.options[index++].optionString = strsave (opt.c_str ()); - } - - m_java_opts.clear (); - } - } - - private: - - JavaVMInitArgs m_vm_args; - - std::list m_java_opts; - }; + std::ifstream js = sys::ifstream (filename.c_str ()); + + if (! js.bad () && ! js.fail ()) + { + std::string line; + + while (! js.eof () && ! js.fail ()) + { + std::getline (js, line); + + if (line.find ('-') == 0) + m_java_opts.push_back (line); + else if (line.length () > 0 && Vdebug_java) + warning ("invalid JVM option, skipping: %s", line.c_str ()); + } + } + } + +private: + + void clean (void) + { + if (m_vm_args.options != nullptr) + { + for (int i = 0; i < m_vm_args.nOptions; i++) + delete [] m_vm_args.options[i].optionString; + + delete [] m_vm_args.options; + + m_vm_args.options = nullptr; + m_vm_args.nOptions = 0; + } + } + + void update (void) + { + clean (); + + if (m_java_opts.size () > 0) + { + int index = 0; + + m_vm_args.nOptions = m_java_opts.size (); + m_vm_args.options = new JavaVMOption [m_vm_args.nOptions]; + + for (const auto& opt : m_java_opts) + { + if (Vdebug_java) + octave_stdout << opt << std::endl; + m_vm_args.options[index++].optionString = strsave (opt.c_str ()); + } + + m_java_opts.clear (); + } + } + +private: + + JavaVMInitArgs m_vm_args; + + std::list m_java_opts; +}; OCTAVE_END_NAMESPACE(octave) @@ -452,7 +452,8 @@ // The filename is "javaclasspath.txt", but historically has been // "classpath.txt" so both are supported. std::vector cp_list = {"javaclasspath.txt", - "classpath.txt"}; + "classpath.txt" + }; for (std::string filename : cp_list) { @@ -517,10 +518,11 @@ const std::array subdirs = {"bin/client", "bin/server"}; #else const std::array 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" - }; + { + "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 (std::size_t i = 0; i < subdirs.size (); i++) @@ -536,10 +538,10 @@ #if defined (OCTAVE_USE_WINDOWS_API) OCTAVE_BEGIN_NAMESPACE(octave) - // Declare function defined in sysdep.cc - extern LONG - get_regkey_value (HKEY h_rootkey, const std::string subkey, - const std::string name, octave_value& value); +// Declare function defined in sysdep.cc +extern LONG +get_regkey_value (HKEY h_rootkey, const std::string subkey, + const std::string name, octave_value& value); OCTAVE_END_NAMESPACE(octave) static std::string @@ -808,8 +810,8 @@ // Additional options given by file java.opts. m_vm_args.read_java_opts (initial_java_dir () + - octave::sys::file_ops::dir_sep_str () + - "java.opts"); + octave::sys::file_ops::dir_sep_str () + + "java.opts"); if (create_vm (&jvm, ¤t_env, m_vm_args.to_args ()) != JNI_OK) error ("unable to start Java VM in %s", jvm_lib_path.c_str ()); @@ -982,7 +984,7 @@ "()Ljava/lang/String;"); jstring_ref js (jni_env, reinterpret_cast (jni_env->CallObjectMethod (ex, - mID))); + mID))); std::string msg = jstring_to_string (jni_env, js); error ("[java] %s", msg.c_str ()); @@ -1012,9 +1014,9 @@ jclass_ref syscls (jni_env, jni_env->FindClass ("java/lang/System")); jmethodID mID = jni_env->GetStaticMethodID - (syscls, - "getProperty", - "(Ljava/lang/String;)Ljava/lang/String;"); + (syscls, + "getProperty", + "(Ljava/lang/String;)Ljava/lang/String;"); jstring_ref js (jni_env, jni_env->NewStringUTF ("octave.class.loader")); js = reinterpret_cast (jni_env->CallStaticObjectMethod @@ -1037,7 +1039,7 @@ jclass_ref jcls2 (jni_env, jni_env->FindClass ("org/openide/util/Lookup")); jmethodID mID = jni_env->GetStaticMethodID - (jcls2, "getDefault", "()Lorg/openide/util/Lookup;"); + (jcls2, "getDefault", "()Lorg/openide/util/Lookup;"); jobject_ref lObj (jni_env, jni_env->CallStaticObjectMethod (jcls2, mID)); mID = jni_env->GetMethodID (jcls2, "lookup", @@ -1052,21 +1054,21 @@ jstring_ref js (jni_env, jni_env->NewStringUTF (class_loader.c_str ())); uicls = reinterpret_cast - (jni_env->CallObjectMethod (cLoader, mID, jstring (js))); + (jni_env->CallObjectMethod (cLoader, mID, jstring (js))); } if (uicls) uiClass = reinterpret_cast - (jni_env->NewGlobalRef (jclass (uicls))); + (jni_env->NewGlobalRef (jclass (uicls))); } if (uiClass) { jmethodID mID = jni_env->GetStaticMethodID - (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); + (uiClass, "findClass", "(Ljava/lang/String;)Ljava/lang/Class;"); jstring_ref js (jni_env, jni_env->NewStringUTF (name)); jcls = reinterpret_cast - (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js))); + (jni_env->CallStaticObjectMethod (uiClass, mID, jstring (js))); } } @@ -1081,8 +1083,8 @@ jclass_ref ccls (jni_env, jni_env->GetObjectClass (jcls)); jmethodID isArray_ID = jni_env->GetMethodID (ccls, "isArray", "()Z"); jmethodID getComponentType_ID = jni_env->GetMethodID (ccls, - "getComponentType", - "()Ljava/lang/Class;"); + "getComponentType", + "()Ljava/lang/Class;"); dim_vector dv (1, 1); int idx = 0; @@ -1095,11 +1097,11 @@ dv.resize (idx+1); dv(idx) = len; jcls = reinterpret_cast - (jni_env->CallObjectMethod (jcls, getComponentType_ID)); + (jni_env->CallObjectMethod (jcls, getComponentType_ID)); jobj = len > 0 - ? reinterpret_cast (jni_env->GetObjectArrayElement (jobj, - 0)) - : nullptr; + ? reinterpret_cast (jni_env->GetObjectArrayElement (jobj, + 0)) + : nullptr; idx++; } @@ -1155,12 +1157,12 @@ jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env - ->GetStaticMethodID (helperClass, "arraySubsref", - "(Ljava/lang/Object;[[I)Ljava/lang/Object;"); + ->GetStaticMethodID (helperClass, "arraySubsref", + "(Ljava/lang/Object;[[I)Ljava/lang/Object;"); resObj = jni_env->CallStaticObjectMethod - (helperClass, mID, jobj, jobject (java_idx)); + (helperClass, mID, jobj, jobject (java_idx)); if (resObj) retval = box (jni_env, resObj); @@ -1187,11 +1189,11 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, "arraySubsasgn", - "(Ljava/lang/Object;[[ILjava/lang/Object;)" "Ljava/lang/Object;"); + "(Ljava/lang/Object;[[ILjava/lang/Object;)" "Ljava/lang/Object;"); resObj = jni_env->CallStaticObjectMethod - (helperClass, mID, jobj, jobject (java_idx), jobject (rhsObj)); + (helperClass, mID, jobj, jobject (java_idx), jobject (rhsObj)); } if (resObj) @@ -1216,9 +1218,9 @@ jclass_ref cls (jni_env, jni_env->GetObjectClass (jobj)); jclass_ref ccls (jni_env, jni_env->GetObjectClass (cls)); jmethodID getMethods_ID = jni_env->GetMethodID - (ccls, "getMethods", "()[Ljava/lang/reflect/Method;"); + (ccls, "getMethods", "()[Ljava/lang/reflect/Method;"); jmethodID getFields_ID = jni_env->GetMethodID - (ccls, "getFields", "()[Ljava/lang/reflect/Field;"); + (ccls, "getFields", "()[Ljava/lang/reflect/Field;"); jobjectArray_ref mList (jni_env, reinterpret_cast (jni_env->CallObjectMethod (cls, getMethods_ID))); @@ -1232,16 +1234,16 @@ jclass_ref fCls (jni_env, jni_env->FindClass ("java/lang/reflect/Field")); jmethodID m_getName_ID = jni_env->GetMethodID (mCls, "getName", - "()Ljava/lang/String;"); + "()Ljava/lang/String;"); jmethodID f_getName_ID = jni_env->GetMethodID (fCls, "getName", - "()Ljava/lang/String;"); + "()Ljava/lang/String;"); for (int i = 0; i < mLen; i++) { jobject_ref meth (jni_env, jni_env->GetObjectArrayElement (mList, i)); jstring_ref methName (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (meth, - m_getName_ID))); + (jni_env->CallObjectMethod (meth, + m_getName_ID))); name_list.push_back (jstring_to_string (jni_env, methName)); } @@ -1308,8 +1310,8 @@ "()Ljava/lang/String;"); jstring_ref js (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (m_java_object, - mID))); + (jni_env->CallObjectMethod (m_java_object, + mID))); if (js) retval = octave_value (jstring_to_string (jni_env, js), type); @@ -1470,7 +1472,7 @@ reinterpret_cast (jni_env->CallObjectMethod (jobj, mID))); jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), - nullptr); + nullptr); dim_vector dims; dims.resize (jni_env->GetArrayLength (jintArray (iv))); @@ -1492,8 +1494,8 @@ mID = jni_env->GetMethodID (cls, "toDouble", "()[D"); jdoubleArray_ref dv (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (jobj, - mID))); + (jni_env->CallObjectMethod (jobj, + mID))); jni_env->GetDoubleArrayRegion (dv, 0, m.numel (), m.fortran_vec ()); retval = m; @@ -1507,11 +1509,11 @@ mID = jni_env->GetMethodID (cls, "toByte", "()[B"); jbyteArray_ref dv (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (jobj, - mID))); + (jni_env->CallObjectMethod (jobj, + mID))); jni_env->GetByteArrayRegion (dv, 0, m.numel (), reinterpret_cast - (m.fortran_vec ())); + (m.fortran_vec ())); retval = m; break; } @@ -1521,11 +1523,11 @@ mID = jni_env->GetMethodID (cls, "toByte", "()[B"); jbyteArray_ref dv (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (jobj, - mID))); + (jni_env->CallObjectMethod (jobj, + mID))); jni_env->GetByteArrayRegion (dv, 0, m.numel (), reinterpret_cast - (m.fortran_vec ())); + (m.fortran_vec ())); retval = m; break; } @@ -1538,11 +1540,11 @@ mID = jni_env->GetMethodID (cls, "toInt", "()[I"); jintArray_ref dv (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (jobj, - mID))); + (jni_env->CallObjectMethod (jobj, + mID))); jni_env->GetIntArrayRegion (dv, 0, m.numel (), reinterpret_cast - (m.fortran_vec ())); + (m.fortran_vec ())); retval = m; break; } @@ -1552,11 +1554,11 @@ mID = jni_env->GetMethodID (cls, "toInt", "()[I"); jintArray_ref dv (jni_env, reinterpret_cast - (jni_env->CallObjectMethod (jobj, - mID))); + (jni_env->CallObjectMethod (jobj, + mID))); jni_env->GetIntArrayRegion (dv, 0, m.numel (), reinterpret_cast - (m.fortran_vec ())); + (m.fortran_vec ())); retval = m; break; } @@ -1637,8 +1639,8 @@ { jdoubleArray_ref row (jni_env, reinterpret_cast - (jni_env->GetObjectArrayElement - (jarr, r))); + (jni_env->GetObjectArrayElement + (jarr, r))); if (m.isempty ()) { @@ -1646,7 +1648,7 @@ m.resize (cols, rows); } jni_env->GetDoubleArrayRegion - (row, 0, cols, m.fortran_vec () + r * cols); + (row, 0, cols, m.fortran_vec () + r * cols); } retval = m.transpose (); } @@ -1745,7 +1747,7 @@ // into a String[], not into a char array if (val.is_double_type ()) - UNBOX_PRIMITIVE_ARRAY ( , , jdouble, Double); + UNBOX_PRIMITIVE_ARRAY (,, jdouble, Double); else if (val.islogical ()) UNBOX_PRIMITIVE_ARRAY (bool_, bool, jboolean, Boolean); else if (val.isfloat ()) @@ -1833,7 +1835,7 @@ && val.isreal ()) { jclass_ref mcls (jni_env, find_octave_class (jni_env, - "org/octave/Matrix")); + "org/octave/Matrix")); dim_vector dims = val.dims (); jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.ndims ())); jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), nullptr); @@ -1863,7 +1865,7 @@ (m.fortran_vec ())); jmethodID mID = jni_env->GetMethodID (mcls, "", "([B[I)V"); jobj = jni_env->NewObject - (jclass (mcls), mID, jbyteArray (bv), jintArray (iv)); + (jclass (mcls), mID, jbyteArray (bv), jintArray (iv)); jcls = jni_env->GetObjectClass (jobj); } else if (val.is_uint8_type ()) @@ -1875,7 +1877,7 @@ (m.fortran_vec ())); jmethodID mID = jni_env->GetMethodID (mcls, "", "([B[I)V"); jobj = jni_env->NewObject - (jclass (mcls), mID, jbyteArray (bv), jintArray (iv)); + (jclass (mcls), mID, jbyteArray (bv), jintArray (iv)); jcls = jni_env->GetObjectClass (jobj); } else if (val.is_int32_type ()) @@ -1887,7 +1889,7 @@ (m.fortran_vec ())); jmethodID mID = jni_env->GetMethodID (mcls, "", "([I[I)V"); jobj = jni_env->NewObject - (jclass (mcls), mID, jintArray (v), jintArray (iv)); + (jclass (mcls), mID, jintArray (v), jintArray (iv)); jcls = jni_env->GetObjectClass (jobj); } else @@ -1956,7 +1958,7 @@ // Call Java method static Thread java.lang.Thread.currentThread(). jclass_ref cls (jni_env, jni_env->FindClass ("java/lang/Thread")); jmethodID mID = jni_env->GetStaticMethodID (cls, "currentThread", - "()Ljava/lang/Thread;"); + "()Ljava/lang/Thread;"); jobject_ref jthread (jni_env, jni_env->CallStaticObjectMethod (cls, mID)); if (jthread) @@ -1985,9 +1987,9 @@ { // Invoke static void org.octave.Octave.checkPendingAction(). jclass_ref cls (current_env, find_octave_class (current_env, - "org/octave/Octave")); + "org/octave/Octave")); jmethodID mID = current_env->GetStaticMethodID - (cls, "checkPendingAction", "()V"); + (cls, "checkPendingAction", "()V"); current_env->CallStaticVoidMethod (cls, mID); octave_set_default_fpucw (); @@ -2220,7 +2222,7 @@ case '(': if (current_env) retval = get_array_elements - (current_env, TO_JOBJECT (to_java ()), idx.front ()); + (current_env, TO_JOBJECT (to_java ()), idx.front ()); break; default: @@ -2465,10 +2467,11 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, "invokeMethod", - "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); + "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ())); - jobjectArray_ref resObj (jni_env, reinterpret_cast (jni_env->CallStaticObjectMethod (helperClass, mID, - to_java (), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types)))); + jobjectArray_ref resObj (jni_env, + reinterpret_cast (jni_env->CallStaticObjectMethod (helperClass, mID, + to_java (), jstring (methName), jobjectArray (arg_objs), jobjectArray (arg_types)))); if (resObj) retval = box (jni_env, resObj); else @@ -2534,21 +2537,21 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, - "invokeStaticMethod", - "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); + "invokeStaticMethod", + "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); jstring_ref methName (jni_env, jni_env->NewStringUTF (name.c_str ())); jstring_ref clsName (jni_env, jni_env->NewStringUTF (class_name.c_str ())); jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, - mID, - jstring (clsName), - jstring (methName), - jobjectArray (arg_objs), - jobjectArray (arg_types))); + mID, + jstring (clsName), + jstring (methName), + jobjectArray (arg_objs), + jobjectArray (arg_types))); if (resObj) retval = box (jni_env, resObj); else @@ -2616,18 +2619,18 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, - "invokeConstructor", - "(Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); + "invokeConstructor", + "(Ljava/lang/String;[Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/Object;"); jstring_ref clsName (jni_env, jni_env->NewStringUTF (name.c_str ())); jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, - mID, - jstring (clsName), - jobjectArray (arg_objs), - jobjectArray (arg_types))); + mID, + jstring (clsName), + jobjectArray (arg_objs), + jobjectArray (arg_types))); if (resObj) retval = octave_value (new octave_java (resObj, nullptr)); @@ -2688,15 +2691,15 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, "getField", - "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;"); + "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;"); jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, - mID, - to_java (), - jstring (fName))); + mID, + to_java (), + jstring (fName))); if (resObj) retval = box (jni_env, resObj); @@ -2754,16 +2757,16 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, - "getStaticField", - "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); + "getStaticField", + "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ())); jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); jobject_ref resObj (jni_env, jni_env->CallStaticObjectMethod (helperClass, mID, - jstring (cName), - jstring (fName))); + jstring (cName), + jstring (fName))); if (resObj) retval = box (jni_env, resObj); else @@ -2828,9 +2831,9 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, "setField", - "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V"); + "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V"); jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); jni_env->CallStaticObjectMethod (helperClass, mID, to_java (), jstring (fName), jobject (jobj)); @@ -2895,10 +2898,10 @@ { jclass_ref helperClass (jni_env, find_octave_class (jni_env, - "org/octave/ClassHelper")); + "org/octave/ClassHelper")); jmethodID mID = jni_env->GetStaticMethodID (helperClass, - "setStaticField", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"); + "setStaticField", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"); jstring_ref cName (jni_env, jni_env->NewStringUTF (class_name.c_str ())); jstring_ref fName (jni_env, jni_env->NewStringUTF (name.c_str ())); @@ -2979,8 +2982,8 @@ jclass_ref clsCls (current_env, current_env->GetObjectClass (TO_JCLASS (m_java_class))); jmethodID mID = current_env->GetMethodID (clsCls, - "getCanonicalName", - "()Ljava/lang/String;"); + "getCanonicalName", + "()Ljava/lang/String;"); jobject_ref resObj (current_env, current_env->CallObjectMethod (TO_JCLASS (m_java_class), mID)); m_java_classname = jstring_to_string (current_env, resObj); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-lazy-idx.cc --- a/libinterp/octave-value/ov-lazy-idx.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-lazy-idx.cc Thu Dec 01 20:05:44 2022 -0800 @@ -47,7 +47,7 @@ octave_lazy_index::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } octave_base_value * diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-legacy-range.cc diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-magic-int.cc --- a/libinterp/octave-value/ov-magic-int.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-magic-int.cc Thu Dec 01 20:05:44 2022 -0800 @@ -309,7 +309,7 @@ octave_magic_uint::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conv_fcn, - octave_scalar::static_type_id ()); + octave_scalar::static_type_id ()); } DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_magic_int, "magic_int", @@ -319,5 +319,5 @@ octave_magic_int::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conv_fcn, - octave_scalar::static_type_id ()); + octave_scalar::static_type_id ()); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-mex-fcn.cc --- a/libinterp/octave-value/ov-mex-fcn.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-mex-fcn.cc Thu Dec 01 20:05:44 2022 -0800 @@ -47,8 +47,8 @@ "mex function", "mex function"); octave_mex_function::octave_mex_function - (void *fptr, bool interleaved, bool fmex, const octave::dynamic_library& shl, - const std::string& nm) +(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_sh_lib (shl), m_interleaved (interleaved), m_is_fmex (fmex), m_is_system_fcn_file (false) @@ -61,7 +61,7 @@ = octave::sys::canonicalize_file_name (octave::config::oct_file_dir ()); static const std::string oct_file_dir = canonical_oct_file_dir.empty () ? octave::config::oct_file_dir () - : canonical_oct_file_dir; + : canonical_oct_file_dir; m_is_system_fcn_file = (! file_name.empty () diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-mex-fcn.h --- a/libinterp/octave-value/ov-mex-fcn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-mex-fcn.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,7 +41,7 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; +class tree_evaluator; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-null-mat.cc --- a/libinterp/octave-value/ov-null-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-null-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -49,8 +49,8 @@ octave_null_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info - (default_null_matrix_numeric_conversion_function, - octave_matrix::static_type_id ()); + (default_null_matrix_numeric_conversion_function, + octave_matrix::static_type_id ()); } DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_str, "null_string", "char"); @@ -70,8 +70,8 @@ octave_null_str::numeric_conversion_function (void) const { return octave_base_value::type_conv_info - (default_null_str_numeric_conversion_function, - octave_char_matrix_str::static_type_id ()); + (default_null_str_numeric_conversion_function, + octave_char_matrix_str::static_type_id ()); } DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_null_sq_str, "null_sq_string", @@ -92,8 +92,8 @@ octave_null_sq_str::numeric_conversion_function (void) const { return octave_base_value::type_conv_info - (default_null_sq_str_numeric_conversion_function, - octave_char_matrix_sq_str::static_type_id ()); + (default_null_sq_str_numeric_conversion_function, + octave_char_matrix_sq_str::static_type_id ()); } OCTAVE_BEGIN_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-perm.cc --- a/libinterp/octave-value/ov-perm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-perm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -248,7 +248,7 @@ octave_value octave_perm_matrix::convert_to_str_internal (bool pad, bool force, - char type) const + char type) const { return to_dense ().convert_to_str_internal (pad, force, type); } @@ -380,7 +380,7 @@ os.write (reinterpret_cast (&colp), 1); const Array& col_perm = m_matrix.col_perm_vec (); os.write (reinterpret_cast (col_perm.data ()), - col_perm.byte_size ()); + col_perm.byte_size ()); return true; } @@ -493,7 +493,7 @@ octave_perm_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } // FIXME: This is duplicated from octave_base_matrix. Could diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-range.cc --- a/libinterp/octave-value/ov-range.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-range.cc Thu Dec 01 20:05:44 2022 -0800 @@ -143,38 +143,38 @@ #endif DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "double_range", "double"); + "double_range", "double"); // For now, disable all but ov_range. #if 0 DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "float_range", "single"); + "float_range", "single"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "int8_range", "int8"); + "int8_range", "int8"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "int16_range", "int16"); + "int16_range", "int16"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "int32_range", "int32"); + "int32_range", "int32"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "int64_range", "int64"); + "int64_range", "int64"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "uint8_range", "uint8"); + "uint8_range", "uint8"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "uint16_range", "uint16"); + "uint16_range", "uint16"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "uint32_range", "uint32"); + "uint32_range", "uint32"); DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "uint64_range", "uint64"); + "uint64_range", "uint64"); #endif @@ -196,7 +196,7 @@ typedef typename octave_value_range_traits::matrix_type ov_mx_type; return octave_base_value::type_conv_info - (default_numeric_conversion_function, ov_mx_type::static_type_id ()); + (default_numeric_conversion_function, ov_mx_type::static_type_id ()); } template diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-re-diag.cc --- a/libinterp/octave-value/ov-re-diag.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-re-diag.cc Thu Dec 01 20:05:44 2022 -0800 @@ -54,7 +54,7 @@ octave_diag_matrix::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } static octave_base_value * @@ -69,8 +69,8 @@ octave_diag_matrix::numeric_demotion_function (void) const { return octave_base_value::type_conv_info - (default_numeric_demotion_function, - octave_float_diag_matrix::static_type_id ()); + (default_numeric_demotion_function, + octave_float_diag_matrix::static_type_id ()); } octave_base_value * diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-re-mat.cc --- a/libinterp/octave-value/ov-re-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-re-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -101,8 +101,8 @@ octave_matrix::numeric_demotion_function (void) const { return octave_base_value::type_conv_info - (default_numeric_demotion_function, - octave_float_matrix::static_type_id ()); + (default_numeric_demotion_function, + octave_float_matrix::static_type_id ()); } octave_base_value * @@ -343,7 +343,7 @@ { return new octave_matrix (m_matrix.reshape (new_dims), octave::idx_vector (m_idx_cache->as_array ().reshape (new_dims), - m_idx_cache->extent (0))); + m_idx_cache->extent (0))); } else return octave_base_matrix::reshape (new_dims); @@ -356,7 +356,7 @@ { return new octave_matrix (m_matrix.squeeze (), octave::idx_vector (m_idx_cache->as_array ().squeeze (), - m_idx_cache->extent (0))); + m_idx_cache->extent (0))); } else return octave_base_matrix::squeeze (); @@ -520,7 +520,7 @@ std::string old_locale (prev_locale ? prev_locale : ""); std::setlocale (LC_ALL, "C"); octave::unwind_action act - ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); + ([&old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); }); if (kw == "ndims") { @@ -922,15 +922,15 @@ case umap_conj: return m_matrix; - // Mappers handled specially. + // Mappers handled specially. #define ARRAY_METHOD_MAPPER(UMAP, FCN) \ case umap_ ## UMAP: \ return octave_value (m_matrix.FCN ()) - ARRAY_METHOD_MAPPER (abs, abs); - ARRAY_METHOD_MAPPER (isnan, isnan); - ARRAY_METHOD_MAPPER (isinf, isinf); - ARRAY_METHOD_MAPPER (isfinite, isfinite); + ARRAY_METHOD_MAPPER (abs, abs); + ARRAY_METHOD_MAPPER (isnan, isnan); + ARRAY_METHOD_MAPPER (isinf, isinf); + ARRAY_METHOD_MAPPER (isfinite, isfinite); #define ARRAY_MAPPER(UMAP, TYPE, FCN) \ case umap_ ## UMAP: \ @@ -940,45 +940,45 @@ case umap_ ## UMAP: \ return do_rc_map (m_matrix, FCN) - RC_ARRAY_MAPPER (acos, Complex, octave::math::rc_acos); - RC_ARRAY_MAPPER (acosh, Complex, octave::math::rc_acosh); - ARRAY_MAPPER (angle, double, std::arg); - ARRAY_MAPPER (arg, double,std::arg); - RC_ARRAY_MAPPER (asin, Complex, octave::math::rc_asin); - ARRAY_MAPPER (asinh, double, octave::math::asinh); - ARRAY_MAPPER (atan, double, ::atan); - RC_ARRAY_MAPPER (atanh, Complex, octave::math::rc_atanh); - ARRAY_MAPPER (erf, double, octave::math::erf); - ARRAY_MAPPER (erfinv, double, octave::math::erfinv); - ARRAY_MAPPER (erfcinv, double, octave::math::erfcinv); - ARRAY_MAPPER (erfc, double, octave::math::erfc); - ARRAY_MAPPER (erfcx, double, octave::math::erfcx); - ARRAY_MAPPER (erfi, double, octave::math::erfi); - ARRAY_MAPPER (dawson, double, octave::math::dawson); - ARRAY_MAPPER (gamma, double, octave::math::gamma); - RC_ARRAY_MAPPER (lgamma, Complex, octave::math::rc_lgamma); - ARRAY_MAPPER (cbrt, double, octave::math::cbrt); - ARRAY_MAPPER (ceil, double, ::ceil); - ARRAY_MAPPER (cos, double, ::cos); - ARRAY_MAPPER (cosh, double, ::cosh); - ARRAY_MAPPER (exp, double, ::exp); - ARRAY_MAPPER (expm1, double, octave::math::expm1); - ARRAY_MAPPER (fix, double, octave::math::fix); - ARRAY_MAPPER (floor, double, ::floor); - RC_ARRAY_MAPPER (log, Complex, octave::math::rc_log); - RC_ARRAY_MAPPER (log2, Complex, octave::math::rc_log2); - RC_ARRAY_MAPPER (log10, Complex, octave::math::rc_log10); - RC_ARRAY_MAPPER (log1p, Complex, octave::math::rc_log1p); - ARRAY_MAPPER (round, double, octave::math::round); - ARRAY_MAPPER (roundb, double, octave::math::roundb); - ARRAY_MAPPER (signum, double, octave::math::signum); - ARRAY_MAPPER (sin, double, ::sin); - ARRAY_MAPPER (sinh, double, ::sinh); - RC_ARRAY_MAPPER (sqrt, Complex, octave::math::rc_sqrt); - ARRAY_MAPPER (tan, double, ::tan); - ARRAY_MAPPER (tanh, double, ::tanh); - ARRAY_MAPPER (isna, bool, octave::math::isna); - ARRAY_MAPPER (xsignbit, double, octave::math::signbit); + RC_ARRAY_MAPPER (acos, Complex, octave::math::rc_acos); + RC_ARRAY_MAPPER (acosh, Complex, octave::math::rc_acosh); + ARRAY_MAPPER (angle, double, std::arg); + ARRAY_MAPPER (arg, double, std::arg); + RC_ARRAY_MAPPER (asin, Complex, octave::math::rc_asin); + ARRAY_MAPPER (asinh, double, octave::math::asinh); + ARRAY_MAPPER (atan, double, ::atan); + RC_ARRAY_MAPPER (atanh, Complex, octave::math::rc_atanh); + ARRAY_MAPPER (erf, double, octave::math::erf); + ARRAY_MAPPER (erfinv, double, octave::math::erfinv); + ARRAY_MAPPER (erfcinv, double, octave::math::erfcinv); + ARRAY_MAPPER (erfc, double, octave::math::erfc); + ARRAY_MAPPER (erfcx, double, octave::math::erfcx); + ARRAY_MAPPER (erfi, double, octave::math::erfi); + ARRAY_MAPPER (dawson, double, octave::math::dawson); + ARRAY_MAPPER (gamma, double, octave::math::gamma); + RC_ARRAY_MAPPER (lgamma, Complex, octave::math::rc_lgamma); + ARRAY_MAPPER (cbrt, double, octave::math::cbrt); + ARRAY_MAPPER (ceil, double, ::ceil); + ARRAY_MAPPER (cos, double, ::cos); + ARRAY_MAPPER (cosh, double, ::cosh); + ARRAY_MAPPER (exp, double, ::exp); + ARRAY_MAPPER (expm1, double, octave::math::expm1); + ARRAY_MAPPER (fix, double, octave::math::fix); + ARRAY_MAPPER (floor, double, ::floor); + RC_ARRAY_MAPPER (log, Complex, octave::math::rc_log); + RC_ARRAY_MAPPER (log2, Complex, octave::math::rc_log2); + RC_ARRAY_MAPPER (log10, Complex, octave::math::rc_log10); + RC_ARRAY_MAPPER (log1p, Complex, octave::math::rc_log1p); + ARRAY_MAPPER (round, double, octave::math::round); + ARRAY_MAPPER (roundb, double, octave::math::roundb); + ARRAY_MAPPER (signum, double, octave::math::signum); + ARRAY_MAPPER (sin, double, ::sin); + ARRAY_MAPPER (sinh, double, ::sinh); + RC_ARRAY_MAPPER (sqrt, Complex, octave::math::rc_sqrt); + ARRAY_MAPPER (tan, double, ::tan); + ARRAY_MAPPER (tanh, double, ::tanh); + ARRAY_MAPPER (isna, bool, octave::math::isna); + ARRAY_MAPPER (xsignbit, double, octave::math::signbit); // Special cases for Matlab compatibility. case umap_xtolower: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-re-mat.h --- a/libinterp/octave-value/ov-re-mat.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-re-mat.h Thu Dec 01 20:05:44 2022 -0800 @@ -108,7 +108,7 @@ octave::idx_vector index_vector (bool /* require_integers */ = false) const { return m_idx_cache ? *m_idx_cache - : set_idx_cache (octave::idx_vector (m_matrix)); + : set_idx_cache (octave::idx_vector (m_matrix)); } builtin_type_t builtin_type (void) const { return btyp_double; } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-re-sparse.cc --- a/libinterp/octave-value/ov-re-sparse.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-re-sparse.cc Thu Dec 01 20:05:44 2022 -0800 @@ -885,58 +885,58 @@ case umap_conj: return matrix; - // Mappers handled specially. + // Mappers handled specially. #define ARRAY_METHOD_MAPPER(UMAP, FCN) \ case umap_ ## UMAP: \ return octave_value (matrix.FCN ()) - ARRAY_METHOD_MAPPER (abs, abs); + ARRAY_METHOD_MAPPER (abs, abs); #define ARRAY_MAPPER(UMAP, TYPE, FCN) \ case umap_ ## UMAP: \ return octave_value (matrix.map (FCN)) - ARRAY_MAPPER (acos, Complex, octave::math::rc_acos); - ARRAY_MAPPER (acosh, Complex, octave::math::rc_acosh); - ARRAY_MAPPER (angle, double, std::arg); - ARRAY_MAPPER (arg, double,std::arg); - ARRAY_MAPPER (asin, Complex, octave::math::rc_asin); - ARRAY_MAPPER (asinh, double, octave::math::asinh); - ARRAY_MAPPER (atan, double, ::atan); - ARRAY_MAPPER (atanh, Complex, octave::math::rc_atanh); - ARRAY_MAPPER (erf, double, octave::math::erf); - ARRAY_MAPPER (erfinv, double, octave::math::erfinv); - ARRAY_MAPPER (erfcinv, double, octave::math::erfcinv); - ARRAY_MAPPER (erfc, double, octave::math::erfc); - ARRAY_MAPPER (erfcx, double, octave::math::erfcx); - ARRAY_MAPPER (erfi, double, octave::math::erfi); - ARRAY_MAPPER (dawson, double, octave::math::dawson); - ARRAY_MAPPER (gamma, double, octave::math::gamma); - ARRAY_MAPPER (lgamma, Complex, octave::math::rc_lgamma); - ARRAY_MAPPER (cbrt, double, octave::math::cbrt); - ARRAY_MAPPER (ceil, double, ::ceil); - ARRAY_MAPPER (cos, double, ::cos); - ARRAY_MAPPER (cosh, double, ::cosh); - ARRAY_MAPPER (exp, double, ::exp); - ARRAY_MAPPER (expm1, double, octave::math::expm1); - ARRAY_MAPPER (fix, double, octave::math::fix); - ARRAY_MAPPER (floor, double, ::floor); - ARRAY_MAPPER (log, Complex, octave::math::rc_log); - ARRAY_MAPPER (log2, Complex, octave::math::rc_log2); - ARRAY_MAPPER (log10, Complex, octave::math::rc_log10); - ARRAY_MAPPER (log1p, Complex, octave::math::rc_log1p); - ARRAY_MAPPER (round, double, octave::math::round); - ARRAY_MAPPER (roundb, double, octave::math::roundb); - ARRAY_MAPPER (signum, double, octave::math::signum); - ARRAY_MAPPER (sin, double, ::sin); - ARRAY_MAPPER (sinh, double, ::sinh); - ARRAY_MAPPER (sqrt, Complex, octave::math::rc_sqrt); - ARRAY_MAPPER (tan, double, ::tan); - ARRAY_MAPPER (tanh, double, ::tanh); - ARRAY_MAPPER (isnan, bool, octave::math::isnan); - ARRAY_MAPPER (isna, bool, octave::math::isna); - ARRAY_MAPPER (isinf, bool, octave::math::isinf); - ARRAY_MAPPER (isfinite, bool, octave::math::isfinite); + ARRAY_MAPPER (acos, Complex, octave::math::rc_acos); + ARRAY_MAPPER (acosh, Complex, octave::math::rc_acosh); + ARRAY_MAPPER (angle, double, std::arg); + ARRAY_MAPPER (arg, double, std::arg); + ARRAY_MAPPER (asin, Complex, octave::math::rc_asin); + ARRAY_MAPPER (asinh, double, octave::math::asinh); + ARRAY_MAPPER (atan, double, ::atan); + ARRAY_MAPPER (atanh, Complex, octave::math::rc_atanh); + ARRAY_MAPPER (erf, double, octave::math::erf); + ARRAY_MAPPER (erfinv, double, octave::math::erfinv); + ARRAY_MAPPER (erfcinv, double, octave::math::erfcinv); + ARRAY_MAPPER (erfc, double, octave::math::erfc); + ARRAY_MAPPER (erfcx, double, octave::math::erfcx); + ARRAY_MAPPER (erfi, double, octave::math::erfi); + ARRAY_MAPPER (dawson, double, octave::math::dawson); + ARRAY_MAPPER (gamma, double, octave::math::gamma); + ARRAY_MAPPER (lgamma, Complex, octave::math::rc_lgamma); + ARRAY_MAPPER (cbrt, double, octave::math::cbrt); + ARRAY_MAPPER (ceil, double, ::ceil); + ARRAY_MAPPER (cos, double, ::cos); + ARRAY_MAPPER (cosh, double, ::cosh); + ARRAY_MAPPER (exp, double, ::exp); + ARRAY_MAPPER (expm1, double, octave::math::expm1); + ARRAY_MAPPER (fix, double, octave::math::fix); + ARRAY_MAPPER (floor, double, ::floor); + ARRAY_MAPPER (log, Complex, octave::math::rc_log); + ARRAY_MAPPER (log2, Complex, octave::math::rc_log2); + ARRAY_MAPPER (log10, Complex, octave::math::rc_log10); + ARRAY_MAPPER (log1p, Complex, octave::math::rc_log1p); + ARRAY_MAPPER (round, double, octave::math::round); + ARRAY_MAPPER (roundb, double, octave::math::roundb); + ARRAY_MAPPER (signum, double, octave::math::signum); + ARRAY_MAPPER (sin, double, ::sin); + ARRAY_MAPPER (sinh, double, ::sinh); + ARRAY_MAPPER (sqrt, Complex, octave::math::rc_sqrt); + ARRAY_MAPPER (tan, double, ::tan); + ARRAY_MAPPER (tanh, double, ::tanh); + ARRAY_MAPPER (isnan, bool, octave::math::isnan); + ARRAY_MAPPER (isna, bool, octave::math::isna); + ARRAY_MAPPER (isinf, bool, octave::math::isinf); + ARRAY_MAPPER (isfinite, bool, octave::math::isfinite); default: // Attempt to go via dense matrix. return octave_base_sparse::map (umap); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-scalar.cc --- a/libinterp/octave-value/ov-scalar.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-scalar.cc Thu Dec 01 20:05:44 2022 -0800 @@ -79,8 +79,8 @@ octave_scalar::numeric_demotion_function (void) const { return octave_base_value::type_conv_info - (default_numeric_demotion_function, - octave_float_scalar::static_type_id ()); + (default_numeric_demotion_function, + octave_float_scalar::static_type_id ()); } octave_value @@ -384,49 +384,49 @@ case umap_ ## UMAP: \ return octave_value (FCN (scalar)) - SCALAR_MAPPER (abs, ::fabs); - SCALAR_MAPPER (acos, octave::math::rc_acos); - SCALAR_MAPPER (acosh, octave::math::rc_acosh); - SCALAR_MAPPER (angle, std::arg); - SCALAR_MAPPER (arg, std::arg); - SCALAR_MAPPER (asin, octave::math::rc_asin); - SCALAR_MAPPER (asinh, octave::math::asinh); - SCALAR_MAPPER (atan, ::atan); - SCALAR_MAPPER (atanh, octave::math::rc_atanh); - SCALAR_MAPPER (erf, octave::math::erf); - SCALAR_MAPPER (erfinv, octave::math::erfinv); - SCALAR_MAPPER (erfcinv, octave::math::erfcinv); - SCALAR_MAPPER (erfc, octave::math::erfc); - SCALAR_MAPPER (erfcx, octave::math::erfcx); - SCALAR_MAPPER (erfi, octave::math::erfi); - SCALAR_MAPPER (dawson, octave::math::dawson); - SCALAR_MAPPER (gamma, octave::math::gamma); - SCALAR_MAPPER (lgamma, octave::math::rc_lgamma); - SCALAR_MAPPER (cbrt, octave::math::cbrt); - SCALAR_MAPPER (ceil, ::ceil); - SCALAR_MAPPER (cos, ::cos); - SCALAR_MAPPER (cosh, ::cosh); - SCALAR_MAPPER (exp, ::exp); - SCALAR_MAPPER (expm1, octave::math::expm1); - SCALAR_MAPPER (fix, octave::math::fix); - SCALAR_MAPPER (floor, std::floor); - SCALAR_MAPPER (log, octave::math::rc_log); - SCALAR_MAPPER (log2, octave::math::rc_log2); - SCALAR_MAPPER (log10, octave::math::rc_log10); - SCALAR_MAPPER (log1p, octave::math::rc_log1p); - SCALAR_MAPPER (round, octave::math::round); - SCALAR_MAPPER (roundb, octave::math::roundb); - SCALAR_MAPPER (signum, octave::math::signum); - SCALAR_MAPPER (sin, ::sin); - SCALAR_MAPPER (sinh, ::sinh); - SCALAR_MAPPER (sqrt, octave::math::rc_sqrt); - SCALAR_MAPPER (tan, ::tan); - SCALAR_MAPPER (tanh, ::tanh); - SCALAR_MAPPER (isfinite, octave::math::isfinite); - SCALAR_MAPPER (isinf, octave::math::isinf); - SCALAR_MAPPER (isna, octave::math::isna); - SCALAR_MAPPER (isnan, octave::math::isnan); - SCALAR_MAPPER (xsignbit, octave::math::signbit); + SCALAR_MAPPER (abs, ::fabs); + SCALAR_MAPPER (acos, octave::math::rc_acos); + SCALAR_MAPPER (acosh, octave::math::rc_acosh); + SCALAR_MAPPER (angle, std::arg); + SCALAR_MAPPER (arg, std::arg); + SCALAR_MAPPER (asin, octave::math::rc_asin); + SCALAR_MAPPER (asinh, octave::math::asinh); + SCALAR_MAPPER (atan, ::atan); + SCALAR_MAPPER (atanh, octave::math::rc_atanh); + SCALAR_MAPPER (erf, octave::math::erf); + SCALAR_MAPPER (erfinv, octave::math::erfinv); + SCALAR_MAPPER (erfcinv, octave::math::erfcinv); + SCALAR_MAPPER (erfc, octave::math::erfc); + SCALAR_MAPPER (erfcx, octave::math::erfcx); + SCALAR_MAPPER (erfi, octave::math::erfi); + SCALAR_MAPPER (dawson, octave::math::dawson); + SCALAR_MAPPER (gamma, octave::math::gamma); + SCALAR_MAPPER (lgamma, octave::math::rc_lgamma); + SCALAR_MAPPER (cbrt, octave::math::cbrt); + SCALAR_MAPPER (ceil, ::ceil); + SCALAR_MAPPER (cos, ::cos); + SCALAR_MAPPER (cosh, ::cosh); + SCALAR_MAPPER (exp, ::exp); + SCALAR_MAPPER (expm1, octave::math::expm1); + SCALAR_MAPPER (fix, octave::math::fix); + SCALAR_MAPPER (floor, std::floor); + SCALAR_MAPPER (log, octave::math::rc_log); + SCALAR_MAPPER (log2, octave::math::rc_log2); + SCALAR_MAPPER (log10, octave::math::rc_log10); + SCALAR_MAPPER (log1p, octave::math::rc_log1p); + SCALAR_MAPPER (round, octave::math::round); + SCALAR_MAPPER (roundb, octave::math::roundb); + SCALAR_MAPPER (signum, octave::math::signum); + SCALAR_MAPPER (sin, ::sin); + SCALAR_MAPPER (sinh, ::sinh); + SCALAR_MAPPER (sqrt, octave::math::rc_sqrt); + SCALAR_MAPPER (tan, ::tan); + SCALAR_MAPPER (tanh, ::tanh); + SCALAR_MAPPER (isfinite, octave::math::isfinite); + SCALAR_MAPPER (isinf, octave::math::isinf); + SCALAR_MAPPER (isna, octave::math::isna); + SCALAR_MAPPER (isnan, octave::math::isnan); + SCALAR_MAPPER (xsignbit, octave::math::signbit); // Special cases for Matlab compatibility. case umap_xtolower: diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-str-mat.cc --- a/libinterp/octave-value/ov-str-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-str-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -83,12 +83,12 @@ octave_char_matrix_str::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } octave_value octave_char_matrix_str::do_index_op_internal (const octave_value_list& idx, - bool resize_ok, char type) + bool resize_ok, char type) { octave_value retval; diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-struct.cc --- a/libinterp/octave-value/ov-struct.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-struct.cc Thu Dec 01 20:05:44 2022 -0800 @@ -795,7 +795,8 @@ if (! is) break; - Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading struct elements") : Cell (t2)); + Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading struct elements") : + Cell (t2)); m.setfield (nm, tcell); } @@ -908,7 +909,8 @@ if (! is) break; - Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading struct elements") : Cell (t2)); + Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading struct elements") : + Cell (t2)); m.setfield (nm, tcell); } @@ -1009,7 +1011,8 @@ { octave_value t2 = dsub.tc; - Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading struct elements") : Cell (t2)); + Cell tcell = (t2.iscell () ? t2.xcell_value ("load: internal error loading struct elements") : + Cell (t2)); m.setfield (dsub.name, tcell); @@ -1698,7 +1701,7 @@ bool octave_scalar_struct::fast_elem_insert_self (void *where, - builtin_type_t btyp) const + builtin_type_t btyp) const { if (btyp == btyp_struct) @@ -1791,7 +1794,8 @@ { if (nargin == 2) { - Array cstr = args(1).xcellstr_value ("struct: second argument should be a cell array of field names"); + Array cstr = args( + 1).xcellstr_value ("struct: second argument should be a cell array of field names"); return ovl (octave_map (args(0).dims (), cstr)); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-typeinfo.cc --- a/libinterp/octave-value/ov-typeinfo.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-typeinfo.cc Thu Dec 01 20:05:44 2022 -0800 @@ -40,853 +40,854 @@ OCTAVE_BEGIN_NAMESPACE(octave) - extern void install_ops (type_info& ti); +extern void install_ops (type_info& ti); - // FIXME: we should also store all class names and provide a - // way to list them (calling class with nargin == 0?). +// FIXME: we should also store all class names and provide a +// way to list them (calling class with nargin == 0?). - static NDArray as_nd_array (const Array& x) - { - NDArray retval (x.dims ()); +static NDArray as_nd_array (const Array& x) +{ + NDArray retval (x.dims ()); - for (int i = 0; i < x.numel (); i++) - retval.xelem(i) = x(i); + for (int i = 0; i < x.numel (); i++) + retval.xelem(i) = x(i); + + return retval; +} - return retval; - } +static boolNDArray as_bool_nd_array (const Array& x) +{ + boolNDArray retval (x.dims ()); - static boolNDArray as_bool_nd_array (const Array& x) - { - boolNDArray retval (x.dims ()); + for (octave_idx_type i = 0; i < x.numel (); i++) + retval.xelem (i) = x(i); - for (octave_idx_type i = 0; i < x.numel (); i++) - retval.xelem (i) = x(i); - - return retval; - } + return retval; +} - type_info::type_info (int init_tab_sz) - : m_num_types (0), m_types (dim_vector (init_tab_sz, 1), ""), - m_vals (dim_vector (init_tab_sz, 1)), - m_unary_class_ops (dim_vector (octave_value::num_unary_ops, 1), nullptr), - m_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr), - m_non_const_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr), - m_binary_class_ops (dim_vector (octave_value::num_binary_ops, 1), nullptr), - m_binary_ops (dim_vector (octave_value::num_binary_ops, init_tab_sz, init_tab_sz), nullptr), - m_compound_binary_class_ops (dim_vector (octave_value::num_compound_binary_ops, 1), nullptr), - m_compound_binary_ops (dim_vector (octave_value::num_compound_binary_ops, init_tab_sz, init_tab_sz), nullptr), - m_cat_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr), - m_assign_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz, init_tab_sz), nullptr), - m_assignany_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz), nullptr), - m_pref_assign_conv (dim_vector (init_tab_sz, init_tab_sz), -1), - m_widening_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr) - { - install_types (*this); +type_info::type_info (int init_tab_sz) + : m_num_types (0), m_types (dim_vector (init_tab_sz, 1), ""), + m_vals (dim_vector (init_tab_sz, 1)), + m_unary_class_ops (dim_vector (octave_value::num_unary_ops, 1), nullptr), + m_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr), + m_non_const_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr), + m_binary_class_ops (dim_vector (octave_value::num_binary_ops, 1), nullptr), + m_binary_ops (dim_vector (octave_value::num_binary_ops, init_tab_sz, init_tab_sz), nullptr), + m_compound_binary_class_ops (dim_vector (octave_value::num_compound_binary_ops, 1), nullptr), + m_compound_binary_ops (dim_vector (octave_value::num_compound_binary_ops, init_tab_sz, init_tab_sz), + nullptr), + m_cat_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr), + m_assign_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz, init_tab_sz), nullptr), + m_assignany_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz), nullptr), + m_pref_assign_conv (dim_vector (init_tab_sz, init_tab_sz), -1), + m_widening_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr) +{ + install_types (*this); - install_ops (*this); - } + install_ops (*this); +} - int type_info::register_type (const std::string& t_name, - const std::string& /* c_name */, - const octave_value& val, - bool abort_on_duplicate) - { - int i = 0; +int type_info::register_type (const std::string& t_name, + const std::string& /* c_name */, + const octave_value& val, + bool abort_on_duplicate) +{ + int i = 0; - for (i = 0; i < m_num_types; i++) - { - if (t_name == m_types (i)) - { - if (abort_on_duplicate) - { - std::cerr << "duplicate type " << t_name << std::endl; - abort (); - } + for (i = 0; i < m_num_types; i++) + { + if (t_name == m_types (i)) + { + if (abort_on_duplicate) + { + std::cerr << "duplicate type " << t_name << std::endl; + abort (); + } - warning ("duplicate type %s\n", t_name.c_str ()); + warning ("duplicate type %s\n", t_name.c_str ()); - return i; - } - } + return i; + } + } - int len = m_types.numel (); + int len = m_types.numel (); - if (i == len) - { - len *= 2; + if (i == len) + { + len *= 2; - m_types.resize (dim_vector (len, 1), ""); + m_types.resize (dim_vector (len, 1), ""); - m_vals.resize (dim_vector (len, 1), nullptr); + m_vals.resize (dim_vector (len, 1), nullptr); - m_unary_ops.resize - (dim_vector (octave_value::num_unary_ops, len), nullptr); + m_unary_ops.resize + (dim_vector (octave_value::num_unary_ops, len), nullptr); - m_non_const_unary_ops.resize - (dim_vector (octave_value::num_unary_ops, len), nullptr); + m_non_const_unary_ops.resize + (dim_vector (octave_value::num_unary_ops, len), nullptr); - m_binary_ops.resize - (dim_vector (octave_value::num_binary_ops, len, len), nullptr); + m_binary_ops.resize + (dim_vector (octave_value::num_binary_ops, len, len), nullptr); - m_compound_binary_ops.resize - (dim_vector (octave_value::num_compound_binary_ops, len, len), - nullptr); + m_compound_binary_ops.resize + (dim_vector (octave_value::num_compound_binary_ops, len, len), + nullptr); - m_cat_ops.resize (dim_vector (len, len), nullptr); + m_cat_ops.resize (dim_vector (len, len), nullptr); - m_assign_ops.resize - (dim_vector (octave_value::num_assign_ops, len, len), nullptr); + m_assign_ops.resize + (dim_vector (octave_value::num_assign_ops, len, len), nullptr); - m_assignany_ops.resize - (dim_vector (octave_value::num_assign_ops, len), nullptr); + m_assignany_ops.resize + (dim_vector (octave_value::num_assign_ops, len), nullptr); - m_pref_assign_conv.resize (dim_vector (len, len), -1); + m_pref_assign_conv.resize (dim_vector (len, len), -1); - m_widening_ops.resize (dim_vector (len, len), nullptr); - } + m_widening_ops.resize (dim_vector (len, len), nullptr); + } - m_types (i) = t_name; + m_types (i) = t_name; - // Yes, this object is intentionally not deleted in the destructor - // so that we avoid a crash on exit for user-defined data types. - // See bug #53156. If that problem is properly fixed, then this - // could be stored as an object instead of a pointer to an object - // allocated with new. + // Yes, this object is intentionally not deleted in the destructor + // so that we avoid a crash on exit for user-defined data types. + // See bug #53156. If that problem is properly fixed, then this + // could be stored as an object instead of a pointer to an object + // allocated with new. - m_vals(i) = new octave_value (val); + m_vals(i) = new octave_value (val); - m_num_types++; + m_num_types++; - return i; - } + return i; +} - bool type_info::register_unary_class_op (octave_value::unary_op op, - type_info::unary_class_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_unary_class_op (op)) - { - std::string op_name = octave_value::unary_op_as_string (op); +bool type_info::register_unary_class_op (octave_value::unary_op op, + type_info::unary_class_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_unary_class_op (op)) + { + std::string op_name = octave_value::unary_op_as_string (op); - if (abort_on_duplicate) - { - std::cerr << "duplicate unary operator '" << op_name - << "' for class dispatch" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate unary operator '" << op_name + << "' for class dispatch" << std::endl; + abort (); + } - warning ("duplicate unary operator '%s' for class dispatch", - op_name.c_str ()); - } + warning ("duplicate unary operator '%s' for class dispatch", + op_name.c_str ()); + } - m_unary_class_ops.checkelem (static_cast (op)) - = reinterpret_cast (f); + m_unary_class_ops.checkelem (static_cast (op)) + = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_unary_op (octave_value::unary_op op, int t, - unary_op_fcn f, bool abort_on_duplicate) - { - if (lookup_unary_op (op, t)) - { - std::string op_name = octave_value::unary_op_as_string (op); - std::string type_name = m_types(t); +bool type_info::register_unary_op (octave_value::unary_op op, int t, + unary_op_fcn f, bool abort_on_duplicate) +{ + if (lookup_unary_op (op, t)) + { + std::string op_name = octave_value::unary_op_as_string (op); + std::string type_name = m_types(t); - if (abort_on_duplicate) - { - std::cerr << "duplicate unary operator '" << op_name - << "' for type '" << type_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate unary operator '" << op_name + << "' for type '" << type_name << "'" << std::endl; + abort (); + } - warning ("duplicate unary operator '%s' for type '%s'", - op_name.c_str (), type_name.c_str ()); - } + warning ("duplicate unary operator '%s' for type '%s'", + op_name.c_str (), type_name.c_str ()); + } - m_unary_ops.checkelem (static_cast (op), t) = reinterpret_cast (f); + m_unary_ops.checkelem (static_cast (op), t) = reinterpret_cast (f); - return false; - } + return false; +} - bool - type_info::register_non_const_unary_op (octave_value::unary_op op, int t, - type_info::non_const_unary_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_non_const_unary_op (op, t)) - { - std::string op_name = octave_value::unary_op_as_string (op); - std::string type_name = m_types(t); +bool +type_info::register_non_const_unary_op (octave_value::unary_op op, int t, + type_info::non_const_unary_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_non_const_unary_op (op, t)) + { + std::string op_name = octave_value::unary_op_as_string (op); + std::string type_name = m_types(t); - if (abort_on_duplicate) - { - std::cerr << "duplicate unary operator '" << op_name - << "' for type '" << type_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate unary operator '" << op_name + << "' for type '" << type_name << "'" << std::endl; + abort (); + } - warning ("duplicate unary operator '%s' for type '%s'", - op_name.c_str (), type_name.c_str ()); - } + warning ("duplicate unary operator '%s' for type '%s'", + op_name.c_str (), type_name.c_str ()); + } - m_non_const_unary_ops.checkelem (static_cast (op), t) - = reinterpret_cast (f); + m_non_const_unary_ops.checkelem (static_cast (op), t) + = reinterpret_cast (f); - return false; - } + return false; +} - bool - type_info::register_binary_class_op (octave_value::binary_op op, - type_info::binary_class_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_binary_class_op (op)) - { - std::string op_name = octave_value::binary_op_as_string (op); +bool +type_info::register_binary_class_op (octave_value::binary_op op, + type_info::binary_class_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_binary_class_op (op)) + { + std::string op_name = octave_value::binary_op_as_string (op); - if (abort_on_duplicate) - { + if (abort_on_duplicate) + { - std::cerr << "duplicate binary operator '" << op_name - << "' for class dispatch" << std::endl; - abort (); - } + std::cerr << "duplicate binary operator '" << op_name + << "' for class dispatch" << std::endl; + abort (); + } - warning ("duplicate binary operator '%s' for class dispatch", - op_name.c_str ()); - } + warning ("duplicate binary operator '%s' for class dispatch", + op_name.c_str ()); + } - m_binary_class_ops.checkelem (static_cast (op)) - = reinterpret_cast (f); + m_binary_class_ops.checkelem (static_cast (op)) + = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_binary_op (octave_value::binary_op op, - int t1, int t2, - type_info::binary_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_binary_op (op, t1, t2)) - { - std::string op_name = octave_value::binary_op_as_string (op); - std::string t1_name = m_types(t1); - std::string t2_name = m_types(t2); +bool type_info::register_binary_op (octave_value::binary_op op, + int t1, int t2, + type_info::binary_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_binary_op (op, t1, t2)) + { + std::string op_name = octave_value::binary_op_as_string (op); + std::string t1_name = m_types(t1); + std::string t2_name = m_types(t2); - if (abort_on_duplicate) - { - std::cerr << "duplicate binary operator '" << op_name - << "' for types '" << t1_name << "' and '" - << t2_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate binary operator '" << op_name + << "' for types '" << t1_name << "' and '" + << t2_name << "'" << std::endl; + abort (); + } - warning ("duplicate binary operator '%s' for types '%s' and '%s'", - op_name.c_str (), t1_name.c_str (), t1_name.c_str ()); - } + warning ("duplicate binary operator '%s' for types '%s' and '%s'", + op_name.c_str (), t1_name.c_str (), t1_name.c_str ()); + } - m_binary_ops.checkelem (static_cast (op), t1, t2) - = reinterpret_cast (f); + m_binary_ops.checkelem (static_cast (op), t1, t2) + = reinterpret_cast (f); - return false; - } + return false; +} - bool - type_info::register_binary_class_op (octave_value::compound_binary_op op, - type_info::binary_class_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_binary_class_op (op)) - { - std::string op_name = octave_value::binary_op_fcn_name (op); +bool +type_info::register_binary_class_op (octave_value::compound_binary_op op, + type_info::binary_class_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_binary_class_op (op)) + { + std::string op_name = octave_value::binary_op_fcn_name (op); - if (abort_on_duplicate) - { - std::cerr << "duplicate compound binary operator '" - << op_name << "' for class dispatch" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate compound binary operator '" + << op_name << "' for class dispatch" << std::endl; + abort (); + } - warning ("duplicate compound binary operator '%s' for class dispatch", - op_name.c_str ()); - } + warning ("duplicate compound binary operator '%s' for class dispatch", + op_name.c_str ()); + } - m_compound_binary_class_ops.checkelem (static_cast (op)) - = reinterpret_cast (f); + m_compound_binary_class_ops.checkelem (static_cast (op)) + = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_binary_op (octave_value::compound_binary_op op, - int t1, int t2, - type_info::binary_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_binary_op (op, t1, t2)) - { - std::string op_name = octave_value::binary_op_fcn_name (op); - std::string t1_name = m_types(t1); - std::string t2_name = m_types(t2); +bool type_info::register_binary_op (octave_value::compound_binary_op op, + int t1, int t2, + type_info::binary_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_binary_op (op, t1, t2)) + { + std::string op_name = octave_value::binary_op_fcn_name (op); + std::string t1_name = m_types(t1); + std::string t2_name = m_types(t2); - if (abort_on_duplicate) - { - std::cerr << "duplicate compound binary operator '" - << op_name << "' for types '" << t1_name - << "' and '" << t2_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate compound binary operator '" + << op_name << "' for types '" << t1_name + << "' and '" << t2_name << "'" << std::endl; + abort (); + } - warning ("duplicate compound binary operator '%s' for types '%s' and '%s'", - op_name.c_str (), t1_name.c_str (), t1_name.c_str ()); - } + warning ("duplicate compound binary operator '%s' for types '%s' and '%s'", + op_name.c_str (), t1_name.c_str (), t1_name.c_str ()); + } - m_compound_binary_ops.checkelem (static_cast (op), t1, t2) - = reinterpret_cast (f); + m_compound_binary_ops.checkelem (static_cast (op), t1, t2) + = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_cat_op (int t1, int t2, type_info::cat_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_cat_op (t1, t2)) - { - std::string t1_name = m_types(t1); - std::string t2_name = m_types(t2); +bool type_info::register_cat_op (int t1, int t2, type_info::cat_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_cat_op (t1, t2)) + { + std::string t1_name = m_types(t1); + std::string t2_name = m_types(t2); - if (abort_on_duplicate) - { - std::cerr << "duplicate concatenation operator for types '" - << t1_name << "' and '" << t2_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate concatenation operator for types '" + << t1_name << "' and '" << t2_name << "'" << std::endl; + abort (); + } - warning ("duplicate concatenation operator for types '%s' and '%s'", - t1_name.c_str (), t1_name.c_str ()); - } + warning ("duplicate concatenation operator for types '%s' and '%s'", + t1_name.c_str (), t1_name.c_str ()); + } - m_cat_ops.checkelem (t1, t2) = reinterpret_cast (f); + m_cat_ops.checkelem (t1, t2) = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_assign_op (octave_value::assign_op op, - int t_lhs, int t_rhs, - type_info::assign_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_assign_op (op, t_lhs, t_rhs)) - { - std::string op_name = octave_value::assign_op_as_string (op); - std::string t_lhs_name = m_types(t_lhs); - std::string t_rhs_name = m_types(t_rhs); +bool type_info::register_assign_op (octave_value::assign_op op, + int t_lhs, int t_rhs, + type_info::assign_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_assign_op (op, t_lhs, t_rhs)) + { + std::string op_name = octave_value::assign_op_as_string (op); + std::string t_lhs_name = m_types(t_lhs); + std::string t_rhs_name = m_types(t_rhs); - if (abort_on_duplicate) - { - std::cerr << "duplicate assignment operator '" - << op_name << "' for types '" << t_lhs_name - << "' and '" << t_rhs_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate assignment operator '" + << op_name << "' for types '" << t_lhs_name + << "' and '" << t_rhs_name << "'" << std::endl; + abort (); + } - warning ("duplicate assignment operator '%s' for types '%s' and '%s'", - op_name.c_str (), t_lhs_name.c_str (), t_rhs_name.c_str ()); - } + warning ("duplicate assignment operator '%s' for types '%s' and '%s'", + op_name.c_str (), t_lhs_name.c_str (), t_rhs_name.c_str ()); + } - m_assign_ops.checkelem (static_cast (op), t_lhs, t_rhs) - = reinterpret_cast (f); + m_assign_ops.checkelem (static_cast (op), t_lhs, t_rhs) + = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_assignany_op (octave_value::assign_op op, int t_lhs, - type_info::assignany_op_fcn f, - bool abort_on_duplicate) - { - if (lookup_assignany_op (op, t_lhs)) - { - std::string op_name = octave_value::assign_op_as_string (op); - std::string t_lhs_name = m_types(t_lhs); +bool type_info::register_assignany_op (octave_value::assign_op op, int t_lhs, + type_info::assignany_op_fcn f, + bool abort_on_duplicate) +{ + if (lookup_assignany_op (op, t_lhs)) + { + std::string op_name = octave_value::assign_op_as_string (op); + std::string t_lhs_name = m_types(t_lhs); - if (abort_on_duplicate) - { - std::cerr << "duplicate assignment operator '" << op_name - << "' for types '" << t_lhs_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "duplicate assignment operator '" << op_name + << "' for types '" << t_lhs_name << "'" << std::endl; + abort (); + } - warning ("duplicate assignment operator '%s' for types '%s'", - op_name.c_str (), t_lhs_name.c_str ()); - } + warning ("duplicate assignment operator '%s' for types '%s'", + op_name.c_str (), t_lhs_name.c_str ()); + } - m_assignany_ops.checkelem (static_cast (op), t_lhs) - = reinterpret_cast (f); + m_assignany_ops.checkelem (static_cast (op), t_lhs) + = reinterpret_cast (f); - return false; - } + return false; +} - bool type_info::register_pref_assign_conv (int t_lhs, int t_rhs, - int t_result, - bool abort_on_duplicate) - { - if (lookup_pref_assign_conv (t_lhs, t_rhs) >= 0) - { - std::string t_lhs_name = m_types(t_lhs); - std::string t_rhs_name = m_types(t_rhs); +bool type_info::register_pref_assign_conv (int t_lhs, int t_rhs, + int t_result, + bool abort_on_duplicate) +{ + if (lookup_pref_assign_conv (t_lhs, t_rhs) >= 0) + { + std::string t_lhs_name = m_types(t_lhs); + std::string t_rhs_name = m_types(t_rhs); - if (abort_on_duplicate) - { - std::cerr << "overriding assignment conversion for types '" - << t_lhs_name << "' and '" << t_rhs_name << "'" - << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "overriding assignment conversion for types '" + << t_lhs_name << "' and '" << t_rhs_name << "'" + << std::endl; + abort (); + } - warning ("overriding assignment conversion for types '%s' and '%s'", - t_lhs_name.c_str (), t_rhs_name.c_str ()); - } + warning ("overriding assignment conversion for types '%s' and '%s'", + t_lhs_name.c_str (), t_rhs_name.c_str ()); + } - m_pref_assign_conv.checkelem (t_lhs, t_rhs) = t_result; + m_pref_assign_conv.checkelem (t_lhs, t_rhs) = t_result; - return false; - } + return false; +} - bool type_info::register_widening_op (int t, int t_result, - octave_base_value::type_conv_fcn f, - bool abort_on_duplicate) - { - if (lookup_widening_op (t, t_result)) - { - std::string t_name = m_types(t); - std::string t_result_name = m_types(t_result); +bool type_info::register_widening_op (int t, int t_result, + octave_base_value::type_conv_fcn f, + bool abort_on_duplicate) +{ + if (lookup_widening_op (t, t_result)) + { + std::string t_name = m_types(t); + std::string t_result_name = m_types(t_result); - if (abort_on_duplicate) - { - std::cerr << "overriding widening op for '" << t_name - << "' to '" << t_result_name << "'" << std::endl; - abort (); - } + if (abort_on_duplicate) + { + std::cerr << "overriding widening op for '" << t_name + << "' to '" << t_result_name << "'" << std::endl; + abort (); + } - warning ("overriding widening op for '%s' to '%s'", - t_name.c_str (), t_result_name.c_str ()); - } + warning ("overriding widening op for '%s' to '%s'", + t_name.c_str (), t_result_name.c_str ()); + } - m_widening_ops.checkelem (t, t_result) = reinterpret_cast (f); + m_widening_ops.checkelem (t, t_result) = reinterpret_cast (f); - return false; - } + return false; +} - octave_value type_info::lookup_type (const std::string& nm) - { - octave_value retval; +octave_value type_info::lookup_type (const std::string& nm) +{ + octave_value retval; - for (int i = 0; i < m_num_types; i++) - { - if (nm == m_types(i)) - { - retval = *m_vals(i); - retval.make_unique (); - break; - } - } + for (int i = 0; i < m_num_types; i++) + { + if (nm == m_types(i)) + { + retval = *m_vals(i); + retval.make_unique (); + break; + } + } - return retval; - } + return retval; +} - type_info::unary_class_op_fcn - type_info::lookup_unary_class_op (octave_value::unary_op op) - { - void *f = m_unary_class_ops.checkelem (static_cast (op)); - return reinterpret_cast (f); - } +type_info::unary_class_op_fcn +type_info::lookup_unary_class_op (octave_value::unary_op op) +{ + void *f = m_unary_class_ops.checkelem (static_cast (op)); + return reinterpret_cast (f); +} - type_info::unary_op_fcn - type_info::lookup_unary_op (octave_value::unary_op op, int t) - { - void *f = m_unary_ops.checkelem (static_cast (op), t); - return reinterpret_cast (f); - } +type_info::unary_op_fcn +type_info::lookup_unary_op (octave_value::unary_op op, int t) +{ + void *f = m_unary_ops.checkelem (static_cast (op), t); + return reinterpret_cast (f); +} - type_info::non_const_unary_op_fcn - type_info::lookup_non_const_unary_op (octave_value::unary_op op, int t) - { - void *f = m_non_const_unary_ops.checkelem (static_cast (op), t); - return reinterpret_cast (f); - } +type_info::non_const_unary_op_fcn +type_info::lookup_non_const_unary_op (octave_value::unary_op op, int t) +{ + void *f = m_non_const_unary_ops.checkelem (static_cast (op), t); + return reinterpret_cast (f); +} - type_info::binary_class_op_fcn - type_info::lookup_binary_class_op (octave_value::binary_op op) - { - void *f = m_binary_class_ops.checkelem (static_cast (op)); - return reinterpret_cast (f); - } +type_info::binary_class_op_fcn +type_info::lookup_binary_class_op (octave_value::binary_op op) +{ + void *f = m_binary_class_ops.checkelem (static_cast (op)); + return reinterpret_cast (f); +} - type_info::binary_op_fcn - type_info::lookup_binary_op (octave_value::binary_op op, int t1, int t2) - { - void *f = m_binary_ops.checkelem (static_cast (op), t1, t2); - return reinterpret_cast (f); - } +type_info::binary_op_fcn +type_info::lookup_binary_op (octave_value::binary_op op, int t1, int t2) +{ + void *f = m_binary_ops.checkelem (static_cast (op), t1, t2); + return reinterpret_cast (f); +} - type_info::binary_class_op_fcn - type_info::lookup_binary_class_op (octave_value::compound_binary_op op) - { - void *f = m_compound_binary_class_ops.checkelem (static_cast (op)); - return reinterpret_cast (f); - } +type_info::binary_class_op_fcn +type_info::lookup_binary_class_op (octave_value::compound_binary_op op) +{ + void *f = m_compound_binary_class_ops.checkelem (static_cast (op)); + return reinterpret_cast (f); +} - type_info::binary_op_fcn - type_info::lookup_binary_op (octave_value::compound_binary_op op, - int t1, int t2) - { - void *f = m_compound_binary_ops.checkelem (static_cast (op), t1, t2); - return reinterpret_cast (f); - } +type_info::binary_op_fcn +type_info::lookup_binary_op (octave_value::compound_binary_op op, + int t1, int t2) +{ + void *f = m_compound_binary_ops.checkelem (static_cast (op), t1, t2); + return reinterpret_cast (f); +} - type_info::cat_op_fcn - type_info::lookup_cat_op (int t1, int t2) - { - void *f = m_cat_ops.checkelem (t1, t2); - return reinterpret_cast (f); - } +type_info::cat_op_fcn +type_info::lookup_cat_op (int t1, int t2) +{ + void *f = m_cat_ops.checkelem (t1, t2); + return reinterpret_cast (f); +} - type_info::assign_op_fcn - type_info::lookup_assign_op (octave_value::assign_op op, - int t_lhs, int t_rhs) - { - void *f = m_assign_ops.checkelem (static_cast (op), t_lhs, t_rhs); - return reinterpret_cast (f); - } +type_info::assign_op_fcn +type_info::lookup_assign_op (octave_value::assign_op op, + int t_lhs, int t_rhs) +{ + void *f = m_assign_ops.checkelem (static_cast (op), t_lhs, t_rhs); + return reinterpret_cast (f); +} - type_info::assignany_op_fcn - type_info::lookup_assignany_op (octave_value::assign_op op, int t_lhs) - { - void *f = m_assignany_ops.checkelem (static_cast (op), t_lhs); - return reinterpret_cast (f); - } +type_info::assignany_op_fcn +type_info::lookup_assignany_op (octave_value::assign_op op, int t_lhs) +{ + void *f = m_assignany_ops.checkelem (static_cast (op), t_lhs); + return reinterpret_cast (f); +} - int - type_info::lookup_pref_assign_conv (int t_lhs, int t_rhs) - { - return m_pref_assign_conv.checkelem (t_lhs, t_rhs); - } +int +type_info::lookup_pref_assign_conv (int t_lhs, int t_rhs) +{ + return m_pref_assign_conv.checkelem (t_lhs, t_rhs); +} - octave_base_value::type_conv_fcn - type_info::lookup_widening_op (int t, int t_result) - { - void *f = m_widening_ops.checkelem (t, t_result); - return reinterpret_cast (f); - } +octave_base_value::type_conv_fcn +type_info::lookup_widening_op (int t, int t_result) +{ + void *f = m_widening_ops.checkelem (t, t_result); + return reinterpret_cast (f); +} - string_vector - type_info::installed_type_names (void) const - { - string_vector retval (m_num_types); +string_vector +type_info::installed_type_names (void) const +{ + string_vector retval (m_num_types); - for (int i = 0; i < m_num_types; i++) - retval(i) = m_types(i); + for (int i = 0; i < m_num_types; i++) + retval(i) = m_types(i); - return retval; - } + return retval; +} - octave_scalar_map - type_info::unary_ops_map (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::unary_ops_map (void) const +{ + octave_scalar_map retval; - int len = std::min (static_cast (m_non_const_unary_ops.columns ()), - m_num_types); + int len = std::min (static_cast (m_non_const_unary_ops.columns ()), + m_num_types); - dim_vector tab_dims (1, len); + dim_vector tab_dims (1, len); - for (int j = 0; j < octave_value::num_unary_ops; j++) - { - boolNDArray tab (tab_dims); + for (int j = 0; j < octave_value::num_unary_ops; j++) + { + boolNDArray tab (tab_dims); - for (int i = 0; i < len; i++) - tab.xelem (i) = (m_unary_ops(j,i) != nullptr); + for (int i = 0; i < len; i++) + tab.xelem (i) = (m_unary_ops(j, i) != nullptr); - octave_value::unary_op op_id = static_cast (j); + octave_value::unary_op op_id = static_cast (j); - retval.setfield (octave_value::unary_op_as_string (op_id), tab); - } + retval.setfield (octave_value::unary_op_as_string (op_id), tab); + } - return retval; - } + return retval; +} - octave_scalar_map - type_info::non_const_unary_ops_map (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::non_const_unary_ops_map (void) const +{ + octave_scalar_map retval; - int len = std::min (static_cast (m_non_const_unary_ops.columns ()), - m_num_types); + int len = std::min (static_cast (m_non_const_unary_ops.columns ()), + m_num_types); - dim_vector tab_dims (1, len); + dim_vector tab_dims (1, len); - for (int j = 0; j < octave_value::num_unary_ops; j++) - { - boolNDArray tab (tab_dims); + for (int j = 0; j < octave_value::num_unary_ops; j++) + { + boolNDArray tab (tab_dims); - for (int i = 0; i < len; i++) - tab.xelem (i) = (m_non_const_unary_ops(j,i) != nullptr); + for (int i = 0; i < len; i++) + tab.xelem (i) = (m_non_const_unary_ops(j, i) != nullptr); - octave_value::unary_op op_id = static_cast (j); + octave_value::unary_op op_id = static_cast (j); - retval.setfield (octave_value::unary_op_as_string (op_id), tab); - } + retval.setfield (octave_value::unary_op_as_string (op_id), tab); + } - return retval; - } + return retval; +} - octave_scalar_map - type_info::binary_ops_map (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::binary_ops_map (void) const +{ + octave_scalar_map retval; - int len = std::min (static_cast (m_binary_ops.columns ()), - m_num_types); + int len = std::min (static_cast (m_binary_ops.columns ()), + m_num_types); - dim_vector tab_dims (len, len); + dim_vector tab_dims (len, len); - for (int k = 0; k < octave_value::num_binary_ops; k++) - { - boolNDArray tab (tab_dims); + for (int k = 0; k < octave_value::num_binary_ops; k++) + { + boolNDArray tab (tab_dims); - for (int j = 0; j < len; j++) - for (int i = 0; i < len; i++) - tab.xelem (j,i) = (m_binary_ops(k,j,i) != nullptr); + for (int j = 0; j < len; j++) + for (int i = 0; i < len; i++) + tab.xelem (j, i) = (m_binary_ops(k, j, i) != nullptr); - octave_value::binary_op op_id = static_cast (k); + octave_value::binary_op op_id = static_cast (k); - retval.setfield (octave_value::binary_op_as_string (op_id), tab); - } + retval.setfield (octave_value::binary_op_as_string (op_id), tab); + } - return retval; - } + return retval; +} - octave_scalar_map - type_info::compound_binary_ops_map (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::compound_binary_ops_map (void) const +{ + octave_scalar_map retval; - int len = std::min (static_cast (m_compound_binary_ops.columns ()), - m_num_types); + int len = std::min (static_cast (m_compound_binary_ops.columns ()), + m_num_types); - dim_vector tab_dims (len, len); + dim_vector tab_dims (len, len); - for (int k = 0; k < octave_value::num_compound_binary_ops; k++) - { - boolNDArray tab (tab_dims); + for (int k = 0; k < octave_value::num_compound_binary_ops; k++) + { + boolNDArray tab (tab_dims); - for (int j = 0; j < len; j++) - for (int i = 0; i < len; i++) - tab.xelem (j,i) = (m_compound_binary_ops(k,j,i) != nullptr); + for (int j = 0; j < len; j++) + for (int i = 0; i < len; i++) + tab.xelem (j, i) = (m_compound_binary_ops(k, j, i) != nullptr); - octave_value::compound_binary_op op_id - = static_cast (k); + octave_value::compound_binary_op op_id + = static_cast (k); - retval.setfield (octave_value::binary_op_fcn_name (op_id), tab); - } + retval.setfield (octave_value::binary_op_fcn_name (op_id), tab); + } - return retval; - } + return retval; +} - octave_scalar_map - type_info::assign_ops_map (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::assign_ops_map (void) const +{ + octave_scalar_map retval; - int len = std::min (static_cast (m_assign_ops.columns ()), - m_num_types); + int len = std::min (static_cast (m_assign_ops.columns ()), + m_num_types); - dim_vector tab_dims (len, len); + dim_vector tab_dims (len, len); - for (int k = 0; k < octave_value::num_assign_ops; k++) - { - boolNDArray tab (tab_dims); + for (int k = 0; k < octave_value::num_assign_ops; k++) + { + boolNDArray tab (tab_dims); - for (int j = 0; j < len; j++) - for (int i = 0; i < len; i++) - tab.xelem (j,i) = (m_assign_ops(k,j,i) != nullptr); + for (int j = 0; j < len; j++) + for (int i = 0; i < len; i++) + tab.xelem (j, i) = (m_assign_ops(k, j, i) != nullptr); - octave_value::assign_op op_id = static_cast (k); + octave_value::assign_op op_id = static_cast (k); - retval.setfield (octave_value::assign_op_as_string (op_id), tab); - } + retval.setfield (octave_value::assign_op_as_string (op_id), tab); + } - return retval; - } + return retval; +} - octave_scalar_map - type_info::assignany_ops_map (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::assignany_ops_map (void) const +{ + octave_scalar_map retval; - int len = std::min (static_cast (m_assignany_ops.columns ()), - m_num_types); + int len = std::min (static_cast (m_assignany_ops.columns ()), + m_num_types); - dim_vector tab_dims (1, len); + dim_vector tab_dims (1, len); - for (int j = 0; j < octave_value::num_assign_ops; j++) - { - boolNDArray tab (tab_dims); + for (int j = 0; j < octave_value::num_assign_ops; j++) + { + boolNDArray tab (tab_dims); - for (int i = 0; i < len; i++) - tab.xelem (i) = (m_assignany_ops(j,i) != nullptr); + for (int i = 0; i < len; i++) + tab.xelem (i) = (m_assignany_ops(j, i) != nullptr); - octave_value::assign_op op_id = static_cast (j); + octave_value::assign_op op_id = static_cast (j); - retval.setfield (octave_value::assign_op_as_string (op_id), tab); - } + retval.setfield (octave_value::assign_op_as_string (op_id), tab); + } - return retval; - } + return retval; +} - octave_scalar_map - type_info::installed_type_info (void) const - { - octave_scalar_map retval; +octave_scalar_map +type_info::installed_type_info (void) const +{ + octave_scalar_map retval; - retval.setfield ("types", octave_value (Cell (installed_type_names ()))); - retval.setfield ("unary_ops", unary_ops_map ()); - retval.setfield ("non_const_unary_ops", non_const_unary_ops_map ()); - retval.setfield ("binary_ops", binary_ops_map ()); - retval.setfield ("compound_binary_ops", compound_binary_ops_map ()); - retval.setfield ("cat_ops", as_bool_nd_array (m_cat_ops)); - retval.setfield ("assign_ops", assign_ops_map ()); - retval.setfield ("assignany_ops", assignany_ops_map ()); - retval.setfield ("pref_assign_conv", as_nd_array (m_pref_assign_conv)); - retval.setfield ("widening_ops", as_bool_nd_array (m_widening_ops)); + retval.setfield ("types", octave_value (Cell (installed_type_names ()))); + retval.setfield ("unary_ops", unary_ops_map ()); + retval.setfield ("non_const_unary_ops", non_const_unary_ops_map ()); + retval.setfield ("binary_ops", binary_ops_map ()); + retval.setfield ("compound_binary_ops", compound_binary_ops_map ()); + retval.setfield ("cat_ops", as_bool_nd_array (m_cat_ops)); + retval.setfield ("assign_ops", assign_ops_map ()); + retval.setfield ("assignany_ops", assignany_ops_map ()); + retval.setfield ("pref_assign_conv", as_nd_array (m_pref_assign_conv)); + retval.setfield ("widening_ops", as_bool_nd_array (m_widening_ops)); - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) OCTAVE_BEGIN_NAMESPACE(octave_value_typeinfo) - int register_type (const std::string& t_name, const std::string& c_name, - const octave_value& val) - { - octave::type_info& type_info = octave::__get_type_info__ (); +int register_type (const std::string& t_name, const std::string& c_name, + const octave_value& val) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.register_type (t_name, c_name, val); - } + return type_info.register_type (t_name, c_name, val); +} - octave_value lookup_type (const std::string& nm) - { - octave::type_info& type_info = octave::__get_type_info__ (); +octave_value lookup_type (const std::string& nm) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_type (nm); - } + return type_info.lookup_type (nm); +} - unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op op) - { - octave::type_info& type_info = octave::__get_type_info__ (); +unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op op) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_unary_class_op (op); - } + return type_info.lookup_unary_class_op (op); +} - unary_op_fcn lookup_unary_op (octave_value::unary_op op, int t) - { - octave::type_info& type_info = octave::__get_type_info__ (); +unary_op_fcn lookup_unary_op (octave_value::unary_op op, int t) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_unary_op (op, t); - } + return type_info.lookup_unary_op (op, t); +} - non_const_unary_op_fcn - lookup_non_const_unary_op (octave_value::unary_op op, int t) - { - octave::type_info& type_info = octave::__get_type_info__ (); +non_const_unary_op_fcn +lookup_non_const_unary_op (octave_value::unary_op op, int t) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_non_const_unary_op (op, t); - } + return type_info.lookup_non_const_unary_op (op, t); +} - binary_class_op_fcn - lookup_binary_class_op (octave_value::binary_op op) - { - octave::type_info& type_info = octave::__get_type_info__ (); +binary_class_op_fcn +lookup_binary_class_op (octave_value::binary_op op) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_binary_class_op (op); - } + return type_info.lookup_binary_class_op (op); +} - binary_op_fcn - lookup_binary_op (octave_value::binary_op op, int t1, int t2) - { - octave::type_info& type_info = octave::__get_type_info__ (); +binary_op_fcn +lookup_binary_op (octave_value::binary_op op, int t1, int t2) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_binary_op (op, t1, t2); - } + return type_info.lookup_binary_op (op, t1, t2); +} - binary_class_op_fcn - lookup_binary_class_op (octave_value::compound_binary_op op) - { - octave::type_info& type_info = octave::__get_type_info__ (); +binary_class_op_fcn +lookup_binary_class_op (octave_value::compound_binary_op op) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_binary_class_op (op); - } + return type_info.lookup_binary_class_op (op); +} - binary_op_fcn - lookup_binary_op (octave_value::compound_binary_op op, int t1, int t2) - { - octave::type_info& type_info = octave::__get_type_info__ (); +binary_op_fcn +lookup_binary_op (octave_value::compound_binary_op op, int t1, int t2) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_binary_op (op, t1, t2); - } + return type_info.lookup_binary_op (op, t1, t2); +} - cat_op_fcn lookup_cat_op (int t1, int t2) - { - octave::type_info& type_info = octave::__get_type_info__ (); +cat_op_fcn lookup_cat_op (int t1, int t2) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_cat_op (t1, t2); - } + return type_info.lookup_cat_op (t1, t2); +} - assign_op_fcn - lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs) - { - octave::type_info& type_info = octave::__get_type_info__ (); +assign_op_fcn +lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_assign_op (op, t_lhs, t_rhs); - } + return type_info.lookup_assign_op (op, t_lhs, t_rhs); +} - assignany_op_fcn - lookup_assignany_op (octave_value::assign_op op, int t_lhs) - { - octave::type_info& type_info = octave::__get_type_info__ (); +assignany_op_fcn +lookup_assignany_op (octave_value::assign_op op, int t_lhs) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_assignany_op (op, t_lhs); - } + return type_info.lookup_assignany_op (op, t_lhs); +} - int lookup_pref_assign_conv (int t_lhs, int t_rhs) - { - octave::type_info& type_info = octave::__get_type_info__ (); +int lookup_pref_assign_conv (int t_lhs, int t_rhs) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_pref_assign_conv (t_lhs, t_rhs); - } + return type_info.lookup_pref_assign_conv (t_lhs, t_rhs); +} - octave_base_value::type_conv_fcn - lookup_widening_op (int t, int t_result) - { - octave::type_info& type_info = octave::__get_type_info__ (); +octave_base_value::type_conv_fcn +lookup_widening_op (int t, int t_result) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.lookup_widening_op (t, t_result); - } + return type_info.lookup_widening_op (t, t_result); +} - string_vector installed_type_names (void) - { - octave::type_info& type_info = octave::__get_type_info__ (); +string_vector installed_type_names (void) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.installed_type_names (); - } + return type_info.installed_type_names (); +} - octave_scalar_map installed_type_info (void) - { - octave::type_info& type_info = octave::__get_type_info__ (); +octave_scalar_map installed_type_info (void) +{ + octave::type_info& type_info = octave::__get_type_info__ (); - return type_info.installed_type_info (); - } + return type_info.installed_type_info (); +} OCTAVE_END_NAMESPACE(octave_value_typeinfo) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-typeinfo.h --- a/libinterp/octave-value/ov-typeinfo.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-typeinfo.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,298 +39,298 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTINTERP_API - type_info - { - public: +class +OCTINTERP_API +type_info +{ +public: - typedef octave_value (*unary_class_op_fcn) (const octave_value&); + typedef octave_value (*unary_class_op_fcn) (const octave_value&); + + typedef octave_value (*unary_op_fcn) (const octave_base_value&); - typedef octave_value (*unary_op_fcn) (const octave_base_value&); + typedef void (*non_const_unary_op_fcn) (octave_base_value&); - typedef void (*non_const_unary_op_fcn) (octave_base_value&); + typedef octave_value (*binary_class_op_fcn) + (const octave_value&, const octave_value&); - typedef octave_value (*binary_class_op_fcn) - (const octave_value&, const octave_value&); + typedef octave_value (*binary_op_fcn) + (const octave_base_value&, const octave_base_value&); - typedef octave_value (*binary_op_fcn) - (const octave_base_value&, const octave_base_value&); + typedef octave_value (*cat_op_fcn) + (const octave_base_value&, const octave_base_value&, + const Array& ra_idx); - typedef octave_value (*cat_op_fcn) - (const octave_base_value&, const octave_base_value&, - const Array& ra_idx); + typedef octave_value (*assign_op_fcn) + (octave_base_value&, const octave_value_list&, const octave_base_value&); + + typedef octave_value (*assignany_op_fcn) + (octave_base_value&, const octave_value_list&, const octave_value&); - typedef octave_value (*assign_op_fcn) - (octave_base_value&, const octave_value_list&, const octave_base_value&); + explicit type_info (int init_tab_sz = 16); - typedef octave_value (*assignany_op_fcn) - (octave_base_value&, const octave_value_list&, const octave_value&); + // No copying! + + type_info (const type_info&) = delete; - explicit type_info (int init_tab_sz = 16); + type_info& operator = (const type_info&) = delete; - // No copying! + ~type_info (void) = default; - type_info (const type_info&) = delete; + // It is intentional that there is no install_type function. - type_info& operator = (const type_info&) = delete; + bool install_unary_class_op (octave_value::unary_op op, + unary_class_op_fcn f) + { + return register_unary_class_op (op, f, true); + } - ~type_info (void) = default; - - // It is intentional that there is no install_type function. + bool install_unary_op (octave_value::unary_op op, int t, unary_op_fcn f) + { + return register_unary_op (op, t, f, true); + } - bool install_unary_class_op (octave_value::unary_op op, - unary_class_op_fcn f) - { - return register_unary_class_op (op, f, true); - } + bool install_non_const_unary_op (octave_value::unary_op op, int t, + non_const_unary_op_fcn f) + { + return register_non_const_unary_op (op, t, f, true); + } - bool install_unary_op (octave_value::unary_op op, int t, unary_op_fcn f) - { - return register_unary_op (op, t, f, true); - } + bool install_binary_class_op (octave_value::binary_op op, + binary_class_op_fcn f) + { + return register_binary_class_op (op, f, true); + } - bool install_non_const_unary_op (octave_value::unary_op op, int t, - non_const_unary_op_fcn f) - { - return register_non_const_unary_op (op, t, f, true); - } + bool install_binary_op (octave_value::binary_op op, int t1, int t2, + binary_op_fcn f) + { + return register_binary_op (op, t1, t2, f, true); + } - bool install_binary_class_op (octave_value::binary_op op, - binary_class_op_fcn f) - { - return register_binary_class_op (op, f, true); - } + bool install_binary_class_op (octave_value::compound_binary_op op, + binary_class_op_fcn f) + { + return register_binary_class_op (op, f, true); + } - bool install_binary_op (octave_value::binary_op op, int t1, int t2, - binary_op_fcn f) - { - return register_binary_op (op, t1, t2, f, true); - } + bool install_binary_op (octave_value::compound_binary_op op, + int t_lhs, int t_rhs, binary_op_fcn f) + { + return register_binary_op (op, t_lhs, t_rhs, f, true); + } + + bool install_cat_op (int t1, int t2, cat_op_fcn f) + { + return register_cat_op (t1, t2, f, true); + } - bool install_binary_class_op (octave_value::compound_binary_op op, - binary_class_op_fcn f) - { - return register_binary_class_op (op, f, true); - } + bool install_assign_op (octave_value::assign_op op, + int t_lhs, int t_rhs, assign_op_fcn f) + { + return register_assign_op (op, t_lhs, t_rhs, f, true); + } - bool install_binary_op (octave_value::compound_binary_op op, - int t_lhs, int t_rhs, binary_op_fcn f) - { - return register_binary_op (op, t_lhs, t_rhs, f, true); - } + bool install_assignany_op (octave_value::assign_op op, int t_lhs, + assignany_op_fcn f) + { + return register_assignany_op (op, t_lhs, f, true); + } + + bool install_pref_assign_conv (int t_lhs, int t_rhs, int t_result) + { + return register_pref_assign_conv (t_lhs, t_rhs, t_result, true); + } - bool install_cat_op (int t1, int t2, cat_op_fcn f) - { - return register_cat_op (t1, t2, f, true); - } + bool install_widening_op (int t, int t_result, + octave_base_value::type_conv_fcn f) + { + return register_widening_op (t, t_result, f, true); + } + + int register_type (const std::string&, const std::string&, + const octave_value&, bool abort_on_duplicate = false); - bool install_assign_op (octave_value::assign_op op, - int t_lhs, int t_rhs, assign_op_fcn f) - { - return register_assign_op (op, t_lhs, t_rhs, f, true); - } + bool register_unary_class_op (octave_value::unary_op, unary_class_op_fcn, + bool abort_on_duplicate = false); + + bool register_unary_op (octave_value::unary_op, int, unary_op_fcn, + bool abort_on_duplicate = false); + + bool register_non_const_unary_op (octave_value::unary_op, int, + non_const_unary_op_fcn, + bool abort_on_duplicate = false); - bool install_assignany_op (octave_value::assign_op op, int t_lhs, - assignany_op_fcn f) - { - return register_assignany_op (op, t_lhs, f, true); - } + bool register_binary_class_op (octave_value::binary_op, + binary_class_op_fcn, + bool abort_on_duplicate = false); - bool install_pref_assign_conv (int t_lhs, int t_rhs, int t_result) - { - return register_pref_assign_conv (t_lhs, t_rhs, t_result, true); - } + bool register_binary_op (octave_value::binary_op, int, int, + binary_op_fcn, bool abort_on_duplicate = false); + + bool register_binary_class_op (octave_value::compound_binary_op, + binary_class_op_fcn, + bool abort_on_duplicate = false); - bool install_widening_op (int t, int t_result, - octave_base_value::type_conv_fcn f) - { - return register_widening_op (t, t_result, f, true); - } + bool register_binary_op (octave_value::compound_binary_op, int, int, + binary_op_fcn, bool abort_on_duplicate = false); + + bool register_cat_op (int, int, cat_op_fcn, + bool abort_on_duplicate = false); - int register_type (const std::string&, const std::string&, - const octave_value&, bool abort_on_duplicate = false); + bool register_assign_op (octave_value::assign_op, int, int, assign_op_fcn, + bool abort_on_duplicate = false); - bool register_unary_class_op (octave_value::unary_op, unary_class_op_fcn, + bool register_assignany_op (octave_value::assign_op, int, assignany_op_fcn, + bool abort_on_duplicate = false); + + bool register_pref_assign_conv (int, int, int, bool abort_on_duplicate = false); - bool register_unary_op (octave_value::unary_op, int, unary_op_fcn, - bool abort_on_duplicate = false); - - bool register_non_const_unary_op (octave_value::unary_op, int, - non_const_unary_op_fcn, - bool abort_on_duplicate = false); - - bool register_binary_class_op (octave_value::binary_op, - binary_class_op_fcn, - bool abort_on_duplicate = false); - - bool register_binary_op (octave_value::binary_op, int, int, - binary_op_fcn, bool abort_on_duplicate = false); - - bool register_binary_class_op (octave_value::compound_binary_op, - binary_class_op_fcn, - bool abort_on_duplicate = false); - - bool register_binary_op (octave_value::compound_binary_op, int, int, - binary_op_fcn, bool abort_on_duplicate = false); - - bool register_cat_op (int, int, cat_op_fcn, - bool abort_on_duplicate = false); - - bool register_assign_op (octave_value::assign_op, int, int, assign_op_fcn, + bool register_widening_op (int, int, octave_base_value::type_conv_fcn, bool abort_on_duplicate = false); - bool register_assignany_op (octave_value::assign_op, int, assignany_op_fcn, - bool abort_on_duplicate = false); + octave_value lookup_type (const std::string& nm); + + unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op); - bool register_pref_assign_conv (int, int, int, - bool abort_on_duplicate = false); + unary_op_fcn lookup_unary_op (octave_value::unary_op, int); - bool register_widening_op (int, int, octave_base_value::type_conv_fcn, - bool abort_on_duplicate = false); + non_const_unary_op_fcn + lookup_non_const_unary_op (octave_value::unary_op, int); - octave_value lookup_type (const std::string& nm); + binary_class_op_fcn lookup_binary_class_op (octave_value::binary_op); - unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op); + binary_op_fcn lookup_binary_op (octave_value::binary_op, int, int); - unary_op_fcn lookup_unary_op (octave_value::unary_op, int); + binary_class_op_fcn + lookup_binary_class_op (octave_value::compound_binary_op); - non_const_unary_op_fcn - lookup_non_const_unary_op (octave_value::unary_op, int); - - binary_class_op_fcn lookup_binary_class_op (octave_value::binary_op); + binary_op_fcn + lookup_binary_op (octave_value::compound_binary_op, int, int); - binary_op_fcn lookup_binary_op (octave_value::binary_op, int, int); + cat_op_fcn lookup_cat_op (int, int); - binary_class_op_fcn - lookup_binary_class_op (octave_value::compound_binary_op); + assign_op_fcn lookup_assign_op (octave_value::assign_op, int, int); - binary_op_fcn - lookup_binary_op (octave_value::compound_binary_op, int, int); + assignany_op_fcn lookup_assignany_op (octave_value::assign_op, int); - cat_op_fcn lookup_cat_op (int, int); + int lookup_pref_assign_conv (int, int); + + octave_base_value::type_conv_fcn lookup_widening_op (int, int); - assign_op_fcn lookup_assign_op (octave_value::assign_op, int, int); + string_vector installed_type_names (void) const; - assignany_op_fcn lookup_assignany_op (octave_value::assign_op, int); - - int lookup_pref_assign_conv (int, int); + octave_scalar_map installed_type_info (void) const; - octave_base_value::type_conv_fcn lookup_widening_op (int, int); + octave_scalar_map unary_ops_map (void) const; - string_vector installed_type_names (void) const; + octave_scalar_map non_const_unary_ops_map (void) const; - octave_scalar_map installed_type_info (void) const; + octave_scalar_map binary_ops_map (void) const; - octave_scalar_map unary_ops_map (void) const; + octave_scalar_map compound_binary_ops_map (void) const; - octave_scalar_map non_const_unary_ops_map (void) const; + octave_scalar_map assign_ops_map (void) const; - octave_scalar_map binary_ops_map (void) const; + octave_scalar_map assignany_ops_map (void) const; - octave_scalar_map compound_binary_ops_map (void) const; - - octave_scalar_map assign_ops_map (void) const; +private: - octave_scalar_map assignany_ops_map (void) const; + int m_num_types; - private: - - int m_num_types; + Array m_types; - Array m_types; + Array m_vals; - Array m_vals; + Array m_unary_class_ops; - Array m_unary_class_ops; + Array m_unary_ops; - Array m_unary_ops; + Array m_non_const_unary_ops; - Array m_non_const_unary_ops; + Array m_binary_class_ops; - Array m_binary_class_ops; + Array m_binary_ops; - Array m_binary_ops; + Array m_compound_binary_class_ops; - Array m_compound_binary_class_ops; + Array m_compound_binary_ops; - Array m_compound_binary_ops; + Array m_cat_ops; - Array m_cat_ops; - - Array m_assign_ops; + Array m_assign_ops; - Array m_assignany_ops; + Array m_assignany_ops; - Array m_pref_assign_conv; + Array m_pref_assign_conv; - Array m_widening_ops; - }; + Array m_widening_ops; +}; OCTAVE_END_NAMESPACE(octave) OCTAVE_BEGIN_NAMESPACE(octave_value_typeinfo) - typedef octave::type_info::unary_class_op_fcn unary_class_op_fcn; +typedef octave::type_info::unary_class_op_fcn unary_class_op_fcn; - typedef octave::type_info::unary_op_fcn unary_op_fcn; +typedef octave::type_info::unary_op_fcn unary_op_fcn; - typedef octave::type_info::non_const_unary_op_fcn non_const_unary_op_fcn; +typedef octave::type_info::non_const_unary_op_fcn non_const_unary_op_fcn; - typedef octave::type_info::binary_class_op_fcn binary_class_op_fcn; +typedef octave::type_info::binary_class_op_fcn binary_class_op_fcn; - typedef octave::type_info::binary_op_fcn binary_op_fcn; +typedef octave::type_info::binary_op_fcn binary_op_fcn; - typedef octave::type_info::cat_op_fcn cat_op_fcn; +typedef octave::type_info::cat_op_fcn cat_op_fcn; - typedef octave::type_info::assign_op_fcn assign_op_fcn; +typedef octave::type_info::assign_op_fcn assign_op_fcn; - typedef octave::type_info::assignany_op_fcn assignany_op_fcn; +typedef octave::type_info::assignany_op_fcn assignany_op_fcn; - extern OCTINTERP_API int register_type (const std::string& t_name, - const std::string& c_name, - const octave_value& val); +extern OCTINTERP_API int register_type (const std::string& t_name, + const std::string& c_name, + const octave_value& val); - extern OCTINTERP_API octave_value lookup_type (const std::string& nm); +extern OCTINTERP_API octave_value lookup_type (const std::string& nm); - extern OCTINTERP_API unary_class_op_fcn - lookup_unary_class_op (octave_value::unary_op op); +extern OCTINTERP_API unary_class_op_fcn +lookup_unary_class_op (octave_value::unary_op op); - extern OCTINTERP_API unary_op_fcn - lookup_unary_op (octave_value::unary_op op, int t); +extern OCTINTERP_API unary_op_fcn +lookup_unary_op (octave_value::unary_op op, int t); - extern OCTINTERP_API non_const_unary_op_fcn - lookup_non_const_unary_op (octave_value::unary_op op, int t); +extern OCTINTERP_API non_const_unary_op_fcn +lookup_non_const_unary_op (octave_value::unary_op op, int t); - extern OCTINTERP_API binary_class_op_fcn - lookup_binary_class_op (octave_value::binary_op op); +extern OCTINTERP_API binary_class_op_fcn +lookup_binary_class_op (octave_value::binary_op op); - extern OCTINTERP_API binary_op_fcn - lookup_binary_op (octave_value::binary_op op, int t1, int t2); +extern OCTINTERP_API binary_op_fcn +lookup_binary_op (octave_value::binary_op op, int t1, int t2); - extern OCTINTERP_API binary_class_op_fcn - lookup_binary_class_op (octave_value::compound_binary_op op); +extern OCTINTERP_API binary_class_op_fcn +lookup_binary_class_op (octave_value::compound_binary_op op); - extern OCTINTERP_API binary_op_fcn - lookup_binary_op (octave_value::compound_binary_op op, int t1, int t2); +extern OCTINTERP_API binary_op_fcn +lookup_binary_op (octave_value::compound_binary_op op, int t1, int t2); - extern OCTINTERP_API cat_op_fcn lookup_cat_op (int t1, int t2); +extern OCTINTERP_API cat_op_fcn lookup_cat_op (int t1, int t2); - extern OCTINTERP_API assign_op_fcn - lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs); +extern OCTINTERP_API assign_op_fcn +lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs); - extern OCTINTERP_API assignany_op_fcn - lookup_assignany_op (octave_value::assign_op op, int t_lhs); +extern OCTINTERP_API assignany_op_fcn +lookup_assignany_op (octave_value::assign_op op, int t_lhs); - extern OCTINTERP_API int lookup_pref_assign_conv (int t_lhs, int t_rhs); +extern OCTINTERP_API int lookup_pref_assign_conv (int t_lhs, int t_rhs); - extern OCTINTERP_API octave_base_value::type_conv_fcn - lookup_widening_op (int t, int t_result); +extern OCTINTERP_API octave_base_value::type_conv_fcn +lookup_widening_op (int t, int t_result); - extern OCTINTERP_API string_vector installed_type_names (void); +extern OCTINTERP_API string_vector installed_type_names (void); - extern OCTINTERP_API octave_scalar_map installed_type_info (void); +extern OCTINTERP_API octave_scalar_map installed_type_info (void); OCTAVE_END_NAMESPACE(octave_value_typeinfo) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-usr-fcn.cc --- a/libinterp/octave-value/ov-usr-fcn.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-usr-fcn.cc Thu Dec 01 20:05:44 2022 -0800 @@ -137,10 +137,11 @@ octave_user_code::dump (void) const { std::map m - = {{ "scope_info", m_scope ? m_scope.dump () : "0x0" }, - { "m_file_name", m_file_name }, - { "time_parsed", m_t_parsed }, - { "time_checked", m_t_checked }}; + = {{ "scope_info", m_scope ? m_scope.dump () : "0x0" }, + { "m_file_name", m_file_name }, + { "time_parsed", m_t_parsed }, + { "time_checked", m_t_checked } + }; return octave_value (m); } @@ -157,9 +158,9 @@ { } octave_user_script::octave_user_script - (const std::string& fnm, const std::string& nm, - const octave::symbol_scope& scope, octave::tree_statement_list *cmds, - const std::string& ds) +(const std::string& fnm, const std::string& nm, + const octave::symbol_scope& scope, octave::tree_statement_list *cmds, + const std::string& ds) : octave_user_code (fnm, nm, scope, cmds, ds) { if (m_cmd_list) @@ -167,9 +168,9 @@ } octave_user_script::octave_user_script - (const std::string& fnm, const std::string& nm, - const octave::symbol_scope& scope, const std::string& ds) - : octave_user_code (fnm, nm, scope, nullptr, ds) +(const std::string& fnm, const std::string& nm, + const octave::symbol_scope& scope, const std::string& ds) + : octave_user_code (fnm, nm, scope, nullptr, ds) { } // We must overload the call method so that we call the proper @@ -211,8 +212,8 @@ // extrinsic/intrinsic state?). octave_user_function::octave_user_function - (const octave::symbol_scope& scope, octave::tree_parameter_list *pl, - octave::tree_parameter_list *rl, octave::tree_statement_list *cl) +(const octave::symbol_scope& scope, octave::tree_parameter_list *pl, + octave::tree_parameter_list *rl, octave::tree_statement_list *cl) : octave_user_code ("", "", scope, cl, ""), m_param_list (pl), m_ret_list (rl), m_lead_comm (), m_trail_comm (), @@ -262,7 +263,7 @@ && last_stmt->is_end_of_file ()) { octave::tree_statement_list::reverse_iterator - next_to_last_elt = m_cmd_list->rbegin (); + next_to_last_elt = m_cmd_list->rbegin (); next_to_last_elt++; @@ -353,10 +354,10 @@ static const std::string canonical_fcn_file_dir = octave::sys::canonicalize_file_name - (octave::config::fcn_file_dir ()); + (octave::config::fcn_file_dir ()); static const std::string fcn_file_dir = canonical_fcn_file_dir.empty () ? octave::config::fcn_file_dir () - : canonical_fcn_file_dir; + : canonical_fcn_file_dir; if (fcn_file_dir == ff_name.substr (0, fcn_file_dir.length ())) m_system_fcn_file = true; @@ -585,19 +586,20 @@ octave_user_function::dump (void) const { std::map m - = {{ "user_code", octave_user_code::dump () }, - { "line", m_location_line }, - { "col", m_location_column }, - { "end_line", m_end_location_line }, - { "end_col", m_end_location_column }, - { "system_fcn_file", m_system_fcn_file }, - { "num_named_args", m_num_named_args }, - { "subfunction", m_subfunction }, - { "inline_function", m_inline_function }, - { "anonymous_function", m_anonymous_function }, - { "nested_function", m_nested_function }, - { "ctor_type", ctor_type_str () }, - { "class_method", m_class_method }}; + = {{ "user_code", octave_user_code::dump () }, + { "line", m_location_line }, + { "col", m_location_column }, + { "end_line", m_end_location_line }, + { "end_col", m_end_location_column }, + { "system_fcn_file", m_system_fcn_file }, + { "num_named_args", m_num_named_args }, + { "subfunction", m_subfunction }, + { "inline_function", m_inline_function }, + { "anonymous_function", m_anonymous_function }, + { "nested_function", m_nested_function }, + { "ctor_type", ctor_type_str () }, + { "class_method", m_class_method } + }; return octave_value (m); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov-usr-fcn.h --- a/libinterp/octave-value/ov-usr-fcn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov-usr-fcn.h Thu Dec 01 20:05:44 2022 -0800 @@ -43,13 +43,13 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class file_info; - class stack_frame; - class tree_parameter_list; - class tree_statement_list; - class tree_evaluator; - class tree_expression; - class tree_walker; +class file_info; +class stack_frame; +class tree_parameter_list; +class tree_statement_list; +class tree_evaluator; +class tree_expression; +class tree_walker; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov.cc diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ov.h Thu Dec 01 20:05:44 2022 -0800 @@ -46,8 +46,8 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class stack_frame; - class type_info; +class stack_frame; +class type_info; OCTAVE_END_NAMESPACE(octave) @@ -1631,53 +1631,53 @@ OCTAVE_BEGIN_NAMESPACE(octave) - extern OCTINTERP_API octave_value - unary_op (type_info& ti, octave_value::unary_op op, - const octave_value& a); +extern OCTINTERP_API octave_value +unary_op (type_info& ti, octave_value::unary_op op, + const octave_value& a); - extern OCTINTERP_API octave_value - unary_op (octave_value::unary_op op, const octave_value& a); +extern OCTINTERP_API octave_value +unary_op (octave_value::unary_op op, const octave_value& a); - extern OCTINTERP_API octave_value - binary_op (type_info& ti, octave_value::binary_op op, - const octave_value& a, const octave_value& b); +extern OCTINTERP_API octave_value +binary_op (type_info& ti, octave_value::binary_op op, + const octave_value& a, const octave_value& b); - extern OCTINTERP_API octave_value - binary_op (type_info& ti, octave_value::compound_binary_op op, - const octave_value& a, const octave_value& b); +extern OCTINTERP_API octave_value +binary_op (type_info& ti, octave_value::compound_binary_op op, + const octave_value& a, const octave_value& b); - extern OCTINTERP_API octave_value - binary_op (octave_value::binary_op op, const octave_value& a, - const octave_value& b); +extern OCTINTERP_API octave_value +binary_op (octave_value::binary_op op, const octave_value& a, + const octave_value& b); - extern OCTINTERP_API octave_value - binary_op (octave_value::compound_binary_op op, const octave_value& a, - const octave_value& b); +extern OCTINTERP_API octave_value +binary_op (octave_value::compound_binary_op op, const octave_value& a, + const octave_value& b); - extern OCTINTERP_API octave_value - cat_op (type_info& ti, const octave_value& a, - const octave_value& b, const Array& ra_idx); +extern OCTINTERP_API octave_value +cat_op (type_info& ti, const octave_value& a, + const octave_value& b, const Array& ra_idx); - extern OCTINTERP_API octave_value - cat_op (const octave_value& a, const octave_value& b, - const Array& ra_idx); +extern OCTINTERP_API octave_value +cat_op (const octave_value& a, const octave_value& b, + const Array& ra_idx); - extern OCTINTERP_API octave_value - colon_op (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool is_for_cmd_expr = false); +extern OCTINTERP_API octave_value +colon_op (const octave_value& base, const octave_value& increment, + const octave_value& limit, bool is_for_cmd_expr = false); - inline octave_value - colon_op (const octave_value& base, const octave_value& limit, - bool is_for_cmd_expr = false) - { - // Note, we need to pass an undefined octave_value object instead of - // octave_value (1.0) so that we can properly detect the - // two-argument case and correctly pass just two arguments to any - // user-defined function that is provided if either base or limit is - // an object. +inline octave_value +colon_op (const octave_value& base, const octave_value& limit, + bool is_for_cmd_expr = false) +{ + // Note, we need to pass an undefined octave_value object instead of + // octave_value (1.0) so that we can properly detect the + // two-argument case and correctly pass just two arguments to any + // user-defined function that is provided if either base or limit is + // an object. - return colon_op (base, octave_value (), limit, is_for_cmd_expr); - } + return colon_op (base, octave_value (), limit, is_for_cmd_expr); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave-value/ovl.h --- a/libinterp/octave-value/ovl.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave-value/ovl.h Thu Dec 01 20:05:44 2022 -0800 @@ -143,7 +143,7 @@ if (tags && len > 0 && m_names.numel () > 0) retval.m_names = m_names.linear_slice (offset, std::min (offset + len, - m_names.numel ())); + m_names.numel ())); return retval; } @@ -208,7 +208,7 @@ template inline octave_value_list -ovl (const OV_Args&... args) +ovl (const OV_Args& ... args) { return octave_value_list (std::initializer_list ({args...})); } diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave.cc --- a/libinterp/octave.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave.cc Thu Dec 01 20:05:44 2022 -0800 @@ -56,378 +56,378 @@ OCTAVE_BEGIN_NAMESPACE(octave) - cmdline_options::cmdline_options (void) - { - m_all_args.resize (1); - m_all_args[0] = ""; - } +cmdline_options::cmdline_options (void) +{ + m_all_args.resize (1); + m_all_args[0] = ""; +} + +cmdline_options::cmdline_options (int argc, char **argv) +{ + // Save raw program arguments. + m_all_args = string_vector (argv, argc); + + while (true) + { + int long_idx; + + int optc = octave_getopt_long_wrapper (argc, argv, short_opts, + long_opts, &long_idx); + + if (optc < 0) + break; + + switch (optc) + { + case '?': + // Unrecognized option. getopt_long already printed a message about + // it, so we will just print the usage string and exit. + octave_print_terse_usage_and_exit (); + break; + + case 'H': + m_read_history_file = false; + break; + + case 'W': + m_no_window_system = true; + break; + + case 'V': + m_verbose_flag = true; + break; + + case 'd': + // This is the same as yydebug in parse.y. + octave_debug++; + break; + + case 'f': + m_read_init_files = false; + m_read_site_files = false; + break; + + case 'h': + octave_print_verbose_usage_and_exit (); + break; + + case 'i': + m_forced_interactive = true; + break; + + case 'p': + if (octave_optarg_wrapper ()) + m_command_line_path.push_back (octave_optarg_wrapper ()); + break; + + case 'q': + m_inhibit_startup_message = true; + break; + + case 'x': + m_echo_commands = true; + break; + + case 'v': + octave_print_version_and_exit (); + break; + + case BUILT_IN_DOCSTRINGS_FILE_OPTION: + if (octave_optarg_wrapper ()) + m_docstrings_file = octave_optarg_wrapper ();; + break; - cmdline_options::cmdline_options (int argc, char **argv) - { - // Save raw program arguments. - m_all_args = string_vector (argv, argc); + case DOC_CACHE_FILE_OPTION: + if (octave_optarg_wrapper ()) + m_doc_cache_file = octave_optarg_wrapper (); + break; + + case EVAL_OPTION: + if (octave_optarg_wrapper ()) + { + if (m_code_to_eval.empty ()) + m_code_to_eval = octave_optarg_wrapper (); + else + m_code_to_eval += (std::string (" ") + + octave_optarg_wrapper ()); + } + break; + + case EXEC_PATH_OPTION: + if (octave_optarg_wrapper ()) + m_exec_path = octave_optarg_wrapper (); + break; + + case EXPERIMENTAL_TERMINAL_WIDGET_OPTION: +#if defined (HAVE_QSCINTILLA) + m_experimental_terminal_widget = true; +#endif + break; + + case GUI_OPTION: + m_gui = true; + break; + + case IMAGE_PATH_OPTION: + if (octave_optarg_wrapper ()) + m_image_path = octave_optarg_wrapper (); + break; + + case INFO_FILE_OPTION: + if (octave_optarg_wrapper ()) + m_info_file = octave_optarg_wrapper (); + break; - while (true) - { - int long_idx; + case INFO_PROG_OPTION: + if (octave_optarg_wrapper ()) + m_info_program = octave_optarg_wrapper (); + break; + + case LINE_EDITING_OPTION: + m_forced_line_editing = m_line_editing = true; + break; + + case NO_GUI_OPTION: + m_gui = false; + break; + + case NO_INIT_FILE_OPTION: + m_read_init_files = false; + break; + + case NO_INIT_PATH_OPTION: + m_set_initial_path = false; + break; - int optc = octave_getopt_long_wrapper (argc, argv, short_opts, - long_opts, &long_idx); + case NO_LINE_EDITING_OPTION: + m_line_editing = false; + break; + + case NO_SITE_FILE_OPTION: + m_read_site_files = false; + break; + + case PERSIST_OPTION: + m_persist = true; + break; - if (optc < 0) + case SERVER_OPTION: + m_server = true; + break; + + case TEXI_MACROS_FILE_OPTION: + if (octave_optarg_wrapper ()) + m_texi_macros_file = octave_optarg_wrapper (); + break; + + case TRADITIONAL_OPTION: + m_traditional = true; + m_persist = true; break; - switch (optc) - { - case '?': - // Unrecognized option. getopt_long already printed a message about - // it, so we will just print the usage string and exit. - octave_print_terse_usage_and_exit (); - break; - - case 'H': - m_read_history_file = false; - break; - - case 'W': - m_no_window_system = true; - break; + default: + // getopt_long should print a message about unrecognized options and + // return '?', which is handled above. If we end up here, it is + // because there was an option but we forgot to handle it. + // That should be fatal. + panic_impossible (); + break; + } + } - case 'V': - m_verbose_flag = true; - break; - - case 'd': - // This is the same as yydebug in parse.y. - octave_debug++; - break; + m_remaining_args = string_vector (argv+octave_optind_wrapper (), + argc-octave_optind_wrapper ()); +} - case 'f': - m_read_init_files = false; - m_read_site_files = false; - break; - - case 'h': - octave_print_verbose_usage_and_exit (); - break; - - case 'i': - m_forced_interactive = true; - break; +octave_value cmdline_options::as_octave_value (void) const +{ + octave_scalar_map m; - case 'p': - if (octave_optarg_wrapper ()) - m_command_line_path.push_back (octave_optarg_wrapper ()); - break; - - case 'q': - m_inhibit_startup_message = true; - break; - - case 'x': - m_echo_commands = true; - break; - - case 'v': - octave_print_version_and_exit (); - break; - - case BUILT_IN_DOCSTRINGS_FILE_OPTION: - if (octave_optarg_wrapper ()) - m_docstrings_file = octave_optarg_wrapper ();; - break; - - case DOC_CACHE_FILE_OPTION: - if (octave_optarg_wrapper ()) - m_doc_cache_file = octave_optarg_wrapper (); - break; - - case EVAL_OPTION: - if (octave_optarg_wrapper ()) - { - if (m_code_to_eval.empty ()) - m_code_to_eval = octave_optarg_wrapper (); - else - m_code_to_eval += (std::string (" ") - + octave_optarg_wrapper ()); - } - break; - - case EXEC_PATH_OPTION: - if (octave_optarg_wrapper ()) - m_exec_path = octave_optarg_wrapper (); - break; + m.assign ("sys_argc", sys_argc ()); + m.assign ("sys_argv", Cell (string_vector (sys_argv ()))); + m.assign ("echo_commands", echo_commands ()); + m.assign ("forced_interactive", forced_interactive ()); + m.assign ("forced_line_editing", forced_line_editing ()); + m.assign ("gui", gui ()); + m.assign ("inhibit_startup_message", inhibit_startup_message ()); + m.assign ("line_editing", line_editing ()); + m.assign ("no_window_system", no_window_system ()); + m.assign ("persist", persist ()); + m.assign ("read_history_file", read_history_file ()); + m.assign ("read_init_files", read_init_files ()); + m.assign ("read_site_files", read_site_files ()); + m.assign ("server", server ()); + m.assign ("set_initial_path", set_initial_path ()); + m.assign ("traditional", traditional ()); + m.assign ("verbose_flag", verbose_flag ()); + m.assign ("code_to_eval", code_to_eval ()); + m.assign ("command_line_path", string_vector (command_line_path ())); + m.assign ("docstrings_file", docstrings_file ()); + m.assign ("doc_cache_file", doc_cache_file ()); + m.assign ("exec_path", exec_path ()); + m.assign ("image_path", image_path ()); + m.assign ("info_file", info_file ()); + m.assign ("info_program", info_program ()); + m.assign ("texi_macros_file", texi_macros_file ()); + m.assign ("all_args", Cell (all_args ())); + m.assign ("remaining_args", Cell (remaining_args ())); - case EXPERIMENTAL_TERMINAL_WIDGET_OPTION: -#if defined (HAVE_QSCINTILLA) - m_experimental_terminal_widget = true; -#endif - break; + return m; +} - case GUI_OPTION: - m_gui = true; - break; +application *application::s_instance = nullptr; - case IMAGE_PATH_OPTION: - if (octave_optarg_wrapper ()) - m_image_path = octave_optarg_wrapper (); - break; - - case INFO_FILE_OPTION: - if (octave_optarg_wrapper ()) - m_info_file = octave_optarg_wrapper (); - break; +application::application (int argc, char **argv) + : m_options (argc, argv) +{ + init (); +} - case INFO_PROG_OPTION: - if (octave_optarg_wrapper ()) - m_info_program = octave_optarg_wrapper (); - break; - - case LINE_EDITING_OPTION: - m_forced_line_editing = m_line_editing = true; - break; +application::application (const cmdline_options& opts) + : m_options (opts) +{ + init (); +} - case NO_GUI_OPTION: - m_gui = false; - break; - - case NO_INIT_FILE_OPTION: - m_read_init_files = false; - break; - - case NO_INIT_PATH_OPTION: - m_set_initial_path = false; - break; +// Note: Although the application destructor doesn't explicitly +// perform any actions, it can't be declared "default" in the header +// file if the interpreter is an incomplete type. Providing +// an explicit definition of the destructor here is much simpler than +// including the full declaration of interpreter in the +// octave.h header file. +application::~application (void) { } - case NO_LINE_EDITING_OPTION: - m_line_editing = false; - break; - - case NO_SITE_FILE_OPTION: - m_read_site_files = false; - break; +void +application::set_program_names (const std::string& pname) +{ + m_program_invocation_name = pname; - case PERSIST_OPTION: - m_persist = true; - break; + std::size_t pos = pname.find_last_of (sys::file_ops::dir_sep_chars ()); - case SERVER_OPTION: - m_server = true; - break; - - case TEXI_MACROS_FILE_OPTION: - if (octave_optarg_wrapper ()) - m_texi_macros_file = octave_optarg_wrapper (); - break; + m_program_name = (pos != std::string::npos) ? pname.substr (pos+1) : pname; +} - case TRADITIONAL_OPTION: - m_traditional = true; - m_persist = true; - break; +void +application::intern_argv (const string_vector& args) +{ + octave_idx_type nargs = args.numel (); - default: - // getopt_long should print a message about unrecognized options and - // return '?', which is handled above. If we end up here, it is - // because there was an option but we forgot to handle it. - // That should be fatal. - panic_impossible (); - break; - } - } + if (nargs > 0) + { + // Skip first argument (program name). + nargs--; - m_remaining_args = string_vector (argv+octave_optind_wrapper (), - argc-octave_optind_wrapper ()); - } + m_argv.resize (nargs); - octave_value cmdline_options::as_octave_value (void) const - { - octave_scalar_map m; + for (octave_idx_type i = 0; i < nargs; i++) + m_argv[i] = args[i+1]; + } +} - m.assign ("sys_argc", sys_argc ()); - m.assign ("sys_argv", Cell (string_vector (sys_argv ()))); - m.assign ("echo_commands", echo_commands ()); - m.assign ("forced_interactive", forced_interactive ()); - m.assign ("forced_line_editing", forced_line_editing ()); - m.assign ("gui", gui ()); - m.assign ("inhibit_startup_message", inhibit_startup_message ()); - m.assign ("line_editing", line_editing ()); - m.assign ("no_window_system", no_window_system ()); - m.assign ("persist", persist ()); - m.assign ("read_history_file", read_history_file ()); - m.assign ("read_init_files", read_init_files ()); - m.assign ("read_site_files", read_site_files ()); - m.assign ("server", server ()); - m.assign ("set_initial_path", set_initial_path ()); - m.assign ("traditional", traditional ()); - m.assign ("verbose_flag", verbose_flag ()); - m.assign ("code_to_eval", code_to_eval ()); - m.assign ("command_line_path", string_vector (command_line_path ())); - m.assign ("docstrings_file", docstrings_file ()); - m.assign ("doc_cache_file", doc_cache_file ()); - m.assign ("exec_path", exec_path ()); - m.assign ("image_path", image_path ()); - m.assign ("info_file", info_file ()); - m.assign ("info_program", info_program ()); - m.assign ("texi_macros_file", texi_macros_file ()); - m.assign ("all_args", Cell (all_args ())); - m.assign ("remaining_args", Cell (remaining_args ())); +bool application::forced_interactive (void) +{ + return s_instance ? s_instance->m_options.forced_interactive () : false; +} + +// Provided for convenience. Will be removed once we eliminate the +// old terminal widget. +bool application::experimental_terminal_widget (void) const +{ + return (s_instance + ? s_instance->m_options.experimental_terminal_widget () : false); +} - return m; - } - - application *application::s_instance = nullptr; +bool application::interpreter_initialized (void) +{ + return m_interpreter ? m_interpreter->initialized () : false; +} - application::application (int argc, char **argv) - : m_options (argc, argv) - { - init (); - } +interpreter& application::create_interpreter (void) +{ + if (! m_interpreter) + m_interpreter = std::unique_ptr (new interpreter (this)); + + return *m_interpreter; +} - application::application (const cmdline_options& opts) - : m_options (opts) - { - init (); - } +void application::initialize_interpreter (void) +{ + if (m_interpreter) + m_interpreter->initialize (); +} - // Note: Although the application destructor doesn't explicitly - // perform any actions, it can't be declared "default" in the header - // file if the interpreter is an incomplete type. Providing - // an explicit definition of the destructor here is much simpler than - // including the full declaration of interpreter in the - // octave.h header file. - application::~application (void) { } - - void - application::set_program_names (const std::string& pname) - { - m_program_invocation_name = pname; - - std::size_t pos = pname.find_last_of (sys::file_ops::dir_sep_chars ()); +int application::execute_interpreter (void) +{ + return m_interpreter ? m_interpreter->execute () : -1; +} - m_program_name = (pos != std::string::npos) ? pname.substr (pos+1) : pname; - } - - void - application::intern_argv (const string_vector& args) - { - octave_idx_type nargs = args.numel (); +void application::delete_interpreter (void) +{ + m_interpreter.reset (); +} - if (nargs > 0) - { - // Skip first argument (program name). - nargs--; - - m_argv.resize (nargs); +void application::init (void) +{ + if (s_instance) + throw std::runtime_error + ("only one Octave application object may be active"); - for (octave_idx_type i = 0; i < nargs; i++) - m_argv[i] = args[i+1]; - } - } + s_instance = this; - bool application::forced_interactive (void) - { - return s_instance ? s_instance->m_options.forced_interactive () : false; - } + string_vector all_args = m_options.all_args (); - // Provided for convenience. Will be removed once we eliminate the - // old terminal widget. - bool application::experimental_terminal_widget (void) const - { - return (s_instance - ? s_instance->m_options.experimental_terminal_widget () : false); - } + set_program_names (all_args[0]); + + string_vector remaining_args = m_options.remaining_args (); - bool application::interpreter_initialized (void) - { - return m_interpreter ? m_interpreter->initialized () : false; - } + std::string code_to_eval = m_options.code_to_eval (); - interpreter& application::create_interpreter (void) - { - if (! m_interpreter) - m_interpreter = std::unique_ptr (new interpreter (this)); - - return *m_interpreter; - } + m_have_script_file = ! remaining_args.empty (); - void application::initialize_interpreter (void) - { - if (m_interpreter) - m_interpreter->initialize (); - } - - int application::execute_interpreter (void) - { - return m_interpreter ? m_interpreter->execute () : -1; - } + m_have_eval_option_code = ! code_to_eval.empty (); - void application::delete_interpreter (void) - { - m_interpreter.reset (); - } + if (m_have_eval_option_code && m_have_script_file) + { + std::cerr << R"(error: --eval "CODE" and script file are mutually exclusive options)" << std::endl; - void application::init (void) - { - if (s_instance) - throw std::runtime_error - ("only one Octave application object may be active"); - - s_instance = this; - - string_vector all_args = m_options.all_args (); - - set_program_names (all_args[0]); + octave_print_terse_usage_and_exit (); + } - string_vector remaining_args = m_options.remaining_args (); - - std::string code_to_eval = m_options.code_to_eval (); - - m_have_script_file = ! remaining_args.empty (); - - m_have_eval_option_code = ! code_to_eval.empty (); - - if (m_have_eval_option_code && m_have_script_file) - { - std::cerr << R"(error: --eval "CODE" and script file are mutually exclusive options)" << std::endl; - - octave_print_terse_usage_and_exit (); - } + if (m_options.gui ()) + { + if (m_options.no_window_system ()) + { + std::cerr << "error: --gui and --no-window-system are mutually exclusive options" << std::endl; + octave_print_terse_usage_and_exit (); + } + if (! m_options.line_editing ()) + { + std::cerr << "error: --gui and --no-line-editing are mutually exclusive options" << std::endl; + octave_print_terse_usage_and_exit (); + } + if (m_options.server ()) + { + std::cerr << "error: --gui and --server are mutually exclusive options" << std::endl; + octave_print_terse_usage_and_exit (); + } + } - if (m_options.gui ()) - { - if (m_options.no_window_system ()) - { - std::cerr << "error: --gui and --no-window-system are mutually exclusive options" << std::endl; - octave_print_terse_usage_and_exit (); - } - if (! m_options.line_editing ()) - { - std::cerr << "error: --gui and --no-line-editing are mutually exclusive options" << std::endl; - octave_print_terse_usage_and_exit (); - } - if (m_options.server ()) - { - std::cerr << "error: --gui and --server are mutually exclusive options" << std::endl; - octave_print_terse_usage_and_exit (); - } - } + m_is_octave_program = ((m_have_script_file || m_have_eval_option_code) + && ! m_options.persist () + && ! m_options.traditional ()); + + // This should probably happen early. + sysdep_init (); +} - m_is_octave_program = ((m_have_script_file || m_have_eval_option_code) - && ! m_options.persist () - && ! m_options.traditional ()); - - // This should probably happen early. - sysdep_init (); - } +int cli_application::execute (void) +{ + interpreter& interp = create_interpreter (); - int cli_application::execute (void) - { - interpreter& interp = create_interpreter (); + int status = interp.execute (); - int status = interp.execute (); - - return status; - } + return status; +} DEFUN (isguirunning, args, , doc: /* -*- texinfo -*- diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/octave.h --- a/libinterp/octave.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/octave.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,352 +38,352 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Command line arguments. See also options.h. +// Command line arguments. See also options.h. - class OCTINTERP_API cmdline_options - { - public: +class OCTINTERP_API cmdline_options +{ +public: - cmdline_options (void); + cmdline_options (void); - cmdline_options (int argc, char **argv); + cmdline_options (int argc, char **argv); - cmdline_options (const cmdline_options&) = default; + cmdline_options (const cmdline_options&) = default; - cmdline_options& operator = (const cmdline_options&) = default; + cmdline_options& operator = (const cmdline_options&) = default; - int sys_argc (void) const { return m_all_args.numel (); } - char **sys_argv (void) const { return m_all_args.c_str_vec (); } + int sys_argc (void) const { return m_all_args.numel (); } + char ** sys_argv (void) const { return m_all_args.c_str_vec (); } - bool echo_commands (void) const { return m_echo_commands; } + bool echo_commands (void) const { return m_echo_commands; } - bool experimental_terminal_widget (void) const - { return m_experimental_terminal_widget; } - bool forced_interactive (void) const { return m_forced_interactive; } - bool forced_line_editing (void) const { return m_forced_line_editing; } - bool gui (void) const { return m_gui; } - bool inhibit_startup_message (void) const - { return m_inhibit_startup_message; } - bool line_editing (void) const { return m_line_editing; } + bool experimental_terminal_widget (void) const + { return m_experimental_terminal_widget; } + bool forced_interactive (void) const { return m_forced_interactive; } + bool forced_line_editing (void) const { return m_forced_line_editing; } + bool gui (void) const { return m_gui; } + bool inhibit_startup_message (void) const + { return m_inhibit_startup_message; } + bool line_editing (void) const { return m_line_editing; } - bool no_window_system (void) const { return m_no_window_system; } - bool persist (void) const { return m_persist; } - bool read_history_file (void) const { return m_read_history_file; } - bool read_init_files (void) const { return m_read_init_files; } - bool read_site_files (void) const { return m_read_site_files; } - bool server (void) const { return m_server; } - bool set_initial_path (void) const { return m_set_initial_path; } - bool traditional (void) const { return m_traditional; } - bool verbose_flag (void) const { return m_verbose_flag; } - std::string code_to_eval (void) const { return m_code_to_eval; } - std::list command_line_path (void) const - { return m_command_line_path; } - std::string docstrings_file (void) const { return m_docstrings_file; } - std::string doc_cache_file (void) const { return m_doc_cache_file; } - std::string exec_path (void) const { return m_exec_path; } - std::string image_path (void) const { return m_image_path; } - std::string info_file (void) const { return m_info_file; } - std::string info_program (void) const { return m_info_program; } - std::string texi_macros_file (void) const {return m_texi_macros_file; } - string_vector all_args (void) const { return m_all_args; } - string_vector remaining_args (void) const { return m_remaining_args; } + bool no_window_system (void) const { return m_no_window_system; } + bool persist (void) const { return m_persist; } + bool read_history_file (void) const { return m_read_history_file; } + bool read_init_files (void) const { return m_read_init_files; } + bool read_site_files (void) const { return m_read_site_files; } + bool server (void) const { return m_server; } + bool set_initial_path (void) const { return m_set_initial_path; } + bool traditional (void) const { return m_traditional; } + bool verbose_flag (void) const { return m_verbose_flag; } + std::string code_to_eval (void) const { return m_code_to_eval; } + std::list command_line_path (void) const + { return m_command_line_path; } + std::string docstrings_file (void) const { return m_docstrings_file; } + std::string doc_cache_file (void) const { return m_doc_cache_file; } + std::string exec_path (void) const { return m_exec_path; } + std::string image_path (void) const { return m_image_path; } + std::string info_file (void) const { return m_info_file; } + std::string info_program (void) const { return m_info_program; } + std::string texi_macros_file (void) const {return m_texi_macros_file; } + string_vector all_args (void) const { return m_all_args; } + string_vector remaining_args (void) const { return m_remaining_args; } - void echo_commands (bool arg) { m_echo_commands = arg; } + void echo_commands (bool arg) { m_echo_commands = arg; } - void experimental_terminal_widget (bool arg) - { m_experimental_terminal_widget = arg; } - void forced_line_editing (bool arg) { m_forced_line_editing = arg; } - void forced_interactive (bool arg) { m_forced_interactive = arg; } - void gui (bool arg) { m_gui = arg; } - void inhibit_startup_message (bool arg) { m_inhibit_startup_message = arg; } - void line_editing (bool arg) { m_line_editing = arg; } + void experimental_terminal_widget (bool arg) + { m_experimental_terminal_widget = arg; } + void forced_line_editing (bool arg) { m_forced_line_editing = arg; } + void forced_interactive (bool arg) { m_forced_interactive = arg; } + void gui (bool arg) { m_gui = arg; } + void inhibit_startup_message (bool arg) { m_inhibit_startup_message = arg; } + void line_editing (bool arg) { m_line_editing = arg; } - void no_window_system (bool arg) { m_no_window_system = arg; } - void persist (bool arg) { m_persist = arg; } - void read_history_file (bool arg) { m_read_history_file = arg; } - void read_init_files (bool arg) { m_read_init_files = arg; } - void read_site_files (bool arg) { m_read_site_files = arg; } - void server (bool arg) { m_server = arg; } - void set_initial_path (bool arg) { m_set_initial_path = arg; } - void traditional (bool arg) { m_traditional = arg; } - void verbose_flag (bool arg) { m_verbose_flag = arg; } - void code_to_eval (const std::string& arg) { m_code_to_eval = arg; } - void command_line_path (const std::list& arg) - { m_command_line_path = arg; } - void docstrings_file (const std::string& arg) { m_docstrings_file = arg; } - void doc_cache_file (const std::string& arg) { m_doc_cache_file = arg; } - void exec_path (const std::string& arg) { m_exec_path = arg; } - void image_path (const std::string& arg) { m_image_path = arg; } - void info_file (const std::string& arg) { m_info_file = arg; } - void info_program (const std::string& arg) { m_info_program = arg; } - void texi_macros_file (const std::string& arg) { m_texi_macros_file = arg; } - void all_args (const string_vector& arg) { m_all_args = arg; } - void remaining_args (const string_vector& arg) { m_remaining_args = arg; } + void no_window_system (bool arg) { m_no_window_system = arg; } + void persist (bool arg) { m_persist = arg; } + void read_history_file (bool arg) { m_read_history_file = arg; } + void read_init_files (bool arg) { m_read_init_files = arg; } + void read_site_files (bool arg) { m_read_site_files = arg; } + void server (bool arg) { m_server = arg; } + void set_initial_path (bool arg) { m_set_initial_path = arg; } + void traditional (bool arg) { m_traditional = arg; } + void verbose_flag (bool arg) { m_verbose_flag = arg; } + void code_to_eval (const std::string& arg) { m_code_to_eval = arg; } + void command_line_path (const std::list& arg) + { m_command_line_path = arg; } + void docstrings_file (const std::string& arg) { m_docstrings_file = arg; } + void doc_cache_file (const std::string& arg) { m_doc_cache_file = arg; } + void exec_path (const std::string& arg) { m_exec_path = arg; } + void image_path (const std::string& arg) { m_image_path = arg; } + void info_file (const std::string& arg) { m_info_file = arg; } + void info_program (const std::string& arg) { m_info_program = arg; } + void texi_macros_file (const std::string& arg) { m_texi_macros_file = arg; } + void all_args (const string_vector& arg) { m_all_args = arg; } + void remaining_args (const string_vector& arg) { m_remaining_args = arg; } - octave_value as_octave_value (void) const; + octave_value as_octave_value (void) const; - private: +private: - // If TRUE, echo commands as they are read and executed. - // (--echo-commands, -x) - bool m_echo_commands = false; + // If TRUE, echo commands as they are read and executed. + // (--echo-commands, -x) + bool m_echo_commands = false; - // If TRUE, use new experimental terminal widget in the GUI. - // (--experimental-terminal-widget) - bool m_experimental_terminal_widget = false; + // If TRUE, use new experimental terminal widget in the GUI. + // (--experimental-terminal-widget) + bool m_experimental_terminal_widget = false; - // If TRUE, start the GUI. - // (--gui) and (--force-gui) for backwards compatibility - bool m_gui = false; + // If TRUE, start the GUI. + // (--gui) and (--force-gui) for backwards compatibility + bool m_gui = false; - // TRUE means the user forced this shell to be interactive. - // (--interactive, -i) - bool m_forced_interactive = false; + // TRUE means the user forced this shell to be interactive. + // (--interactive, -i) + bool m_forced_interactive = false; - // If TRUE, force readline command line editing. - // (--line-editing) - bool m_forced_line_editing = false; + // If TRUE, force readline command line editing. + // (--line-editing) + bool m_forced_line_editing = false; - // TRUE means we don't print the usual startup message. - // (--quiet; --silent; -q) - bool m_inhibit_startup_message = false; + // TRUE means we don't print the usual startup message. + // (--quiet; --silent; -q) + bool m_inhibit_startup_message = false; - // TRUE means we are using readline. - // (--no-line-editing) - bool m_line_editing = true; + // TRUE means we are using readline. + // (--no-line-editing) + bool m_line_editing = true; - // If TRUE, ignore the window system even if it is available. - // (--no-window-system, -W) - bool m_no_window_system = false; + // If TRUE, ignore the window system even if it is available. + // (--no-window-system, -W) + bool m_no_window_system = false; - // If TRUE, don't exit after evaluating code given by --eval option. - // (--persist) - bool m_persist = false; + // If TRUE, don't exit after evaluating code given by --eval option. + // (--persist) + bool m_persist = false; - // If TRUE, initialize history list from saved history file. - // (--no-history; -H) - bool m_read_history_file = true; + // If TRUE, initialize history list from saved history file. + // (--no-history; -H) + bool m_read_history_file = true; - // TRUE means we read ~/.octaverc and ./.octaverc. - // (--norc; --no-init-file; -f) - bool m_read_init_files = true; + // TRUE means we read ~/.octaverc and ./.octaverc. + // (--norc; --no-init-file; -f) + bool m_read_init_files = true; - // TRUE means we read the site-wide octaverc files. - // (--norc; --no-site-file; -f) - bool m_read_site_files = true; + // TRUE means we read the site-wide octaverc files. + // (--norc; --no-site-file; -f) + bool m_read_site_files = true; - // If TRUE, start the command server. - // (--server) - bool m_server = false; + // If TRUE, start the command server. + // (--server) + bool m_server = false; - // TRUE means we set the initial path to configured defaults. - // (--no-init-path) - bool m_set_initial_path = true; + // TRUE means we set the initial path to configured defaults. + // (--no-init-path) + bool m_set_initial_path = true; - // If TRUE use traditional (maximally MATLAB compatible) settings - // (--traditional) - bool m_traditional = false; + // If TRUE use traditional (maximally MATLAB compatible) settings + // (--traditional) + bool m_traditional = false; - // If TRUE, print verbose info in some cases. - // (--verbose; -V) - bool m_verbose_flag = false; + // If TRUE, print verbose info in some cases. + // (--verbose; -V) + bool m_verbose_flag = false; - // The code to evaluate at startup - // (--eval CODE) - std::string m_code_to_eval; + // The code to evaluate at startup + // (--eval CODE) + std::string m_code_to_eval; - // The value of "path" specified on the command line. - // (--path; -p) - std::list m_command_line_path; + // The value of "path" specified on the command line. + // (--path; -p) + std::list m_command_line_path; - // The value for "built_in_docstrings_file" specified on the - // command line. - // (--built-in-docstrings-file) - std::string m_docstrings_file; + // The value for "built_in_docstrings_file" specified on the + // command line. + // (--built-in-docstrings-file) + std::string m_docstrings_file; - // The value for "doc_cache_file" specified on the command line. - // (--doc-cache-file) - std::string m_doc_cache_file; + // The value for "doc_cache_file" specified on the command line. + // (--doc-cache-file) + std::string m_doc_cache_file; - // The value for "EXEC_PATH" specified on the command line. - // (--exec-path) - std::string m_exec_path; + // The value for "EXEC_PATH" specified on the command line. + // (--exec-path) + std::string m_exec_path; - // The value for "IMAGE_PATH" specified on the command line. - // (--image-path) - std::string m_image_path; + // The value for "IMAGE_PATH" specified on the command line. + // (--image-path) + std::string m_image_path; - // The value for "info_file" specified on the command line. - // (--info-file) - std::string m_info_file; + // The value for "info_file" specified on the command line. + // (--info-file) + std::string m_info_file; - // The value for "info_program" specified on the command line. - // (--info-program) - std::string m_info_program; + // The value for "info_program" specified on the command line. + // (--info-program) + std::string m_info_program; - // The value for "texi_macos_file" specified on the command line. - // (--texi-macros-file) - std::string m_texi_macros_file; + // The value for "texi_macos_file" specified on the command line. + // (--texi-macros-file) + std::string m_texi_macros_file; - // All arguments passed to the argc, argv constructor. - string_vector m_all_args; + // All arguments passed to the argc, argv constructor. + string_vector m_all_args; - // Arguments remaining after parsing. - string_vector m_remaining_args; - }; + // Arguments remaining after parsing. + string_vector m_remaining_args; +}; - // The application object contains a pointer to the current - // interpreter and the interpreter contains a pointer back to the - // application context so we need a forward declaration for one (or - // both) of them... +// The application object contains a pointer to the current +// interpreter and the interpreter contains a pointer back to the +// application context so we need a forward declaration for one (or +// both) of them... - class interpreter; +class interpreter; - // Base class for an Octave application. +// Base class for an Octave application. - class OCTINTERP_API application - { - public: +class OCTINTERP_API application +{ +public: - application (const cmdline_options& opts = cmdline_options ()); + application (const cmdline_options& opts = cmdline_options ()); - application (int argc, char **argv); + application (int argc, char **argv); - // No copying, at least not yet... + // No copying, at least not yet... - application (const application&) = delete; + application (const application&) = delete; - application& operator = (const application&) = delete; + application& operator = (const application&) = delete; - virtual ~application (void); + virtual ~application (void); - int sys_argc (void) const { return m_options.sys_argc (); } - char **sys_argv (void) const { return m_options.sys_argv (); } + int sys_argc (void) const { return m_options.sys_argc (); } + char ** sys_argv (void) const { return m_options.sys_argv (); } - void set_program_names (const std::string& pname); + void set_program_names (const std::string& pname); - void intern_argv (const string_vector& args); + void intern_argv (const string_vector& args); - cmdline_options options (void) const { return m_options; } + cmdline_options options (void) const { return m_options; } - bool have_eval_option_code (void) const { return m_have_eval_option_code; } + bool have_eval_option_code (void) const { return m_have_eval_option_code; } - bool have_script_file (void) const { return m_have_script_file; } + bool have_script_file (void) const { return m_have_script_file; } - bool is_octave_program (void) const { return m_is_octave_program; } + bool is_octave_program (void) const { return m_is_octave_program; } - bool interpreter_initialized (void); + bool interpreter_initialized (void); - virtual interpreter& create_interpreter (void); + virtual interpreter& create_interpreter (void); - virtual void initialize_interpreter (void); + virtual void initialize_interpreter (void); - virtual int execute_interpreter (void); + virtual int execute_interpreter (void); - virtual void delete_interpreter (void); + virtual void delete_interpreter (void); - virtual int execute (void) = 0; + virtual int execute (void) = 0; - virtual bool gui_running (void) const { return false; } - virtual void gui_running (bool) { } + virtual bool gui_running (void) const { return false; } + virtual void gui_running (bool) { } - void program_invocation_name (const std::string& nm) - { m_program_invocation_name = nm; } + void program_invocation_name (const std::string& nm) + { m_program_invocation_name = nm; } - void program_name (const std::string& nm) { m_program_name = nm; } + void program_name (const std::string& nm) { m_program_name = nm; } - void forced_interactive (bool arg) { m_options.forced_interactive (arg); } + void forced_interactive (bool arg) { m_options.forced_interactive (arg); } - // Provided for convenience. Will be removed once we eliminate the - // old terminal widget. - bool experimental_terminal_widget (void) const; + // Provided for convenience. Will be removed once we eliminate the + // old terminal widget. + bool experimental_terminal_widget (void) const; - static application * app (void) { return s_instance; } + static application * app (void) { return s_instance; } - static std::string program_invocation_name (void) - { - return s_instance ? s_instance->m_program_invocation_name : ""; - } + static std::string program_invocation_name (void) + { + return s_instance ? s_instance->m_program_invocation_name : ""; + } - static std::string program_name (void) - { - return s_instance ? s_instance->m_program_name : ""; - } + static std::string program_name (void) + { + return s_instance ? s_instance->m_program_name : ""; + } - static string_vector argv (void) - { - return s_instance ? s_instance->m_argv : string_vector (); - } + static string_vector argv (void) + { + return s_instance ? s_instance->m_argv : string_vector (); + } - static bool is_gui_running (void) - { - return s_instance ? s_instance->gui_running () : false; - } + static bool is_gui_running (void) + { + return s_instance ? s_instance->gui_running () : false; + } - // Convenience functions. + // Convenience functions. - static bool forced_interactive (void); + static bool forced_interactive (void); - private: +private: - // The application instance; There should be only one. - static application *s_instance; + // The application instance; There should be only one. + static application *s_instance; - void init (void); + void init (void); - protected: +protected: - // The name used to invoke Octave. - std::string m_program_invocation_name; + // The name used to invoke Octave. + std::string m_program_invocation_name; - // The last component of octave_program_invocation_name. - std::string m_program_name; + // The last component of octave_program_invocation_name. + std::string m_program_name; - // The current argument vector (may change if we are running a - // script with --persist because after the script is done, the - // arguments revert to the full list given to the octave - // interpreter at startup. - string_vector m_argv; + // The current argument vector (may change if we are running a + // script with --persist because after the script is done, the + // arguments revert to the full list given to the octave + // interpreter at startup. + string_vector m_argv; - cmdline_options m_options; + cmdline_options m_options; - // TRUE means we have --eval CODE - bool m_have_eval_option_code = false; + // TRUE means we have --eval CODE + bool m_have_eval_option_code = false; - // TRUE if there is a command line argument that looks like the - // name of a file to execute. - bool m_have_script_file = false; + // TRUE if there is a command line argument that looks like the + // name of a file to execute. + bool m_have_script_file = false; - // TRUE if this is a program and no interpreter and interaction is - // needed. For example, an octave program with shebang line, or code - // from eval without persist. - bool m_is_octave_program = false; + // TRUE if this is a program and no interpreter and interaction is + // needed. For example, an octave program with shebang line, or code + // from eval without persist. + bool m_is_octave_program = false; - std::unique_ptr m_interpreter; - }; + std::unique_ptr m_interpreter; +}; - class OCTINTERP_API cli_application : public application - { - public: +class OCTINTERP_API cli_application : public application +{ +public: - cli_application (const cmdline_options& opts = cmdline_options ()) - : application (opts) - { } + cli_application (const cmdline_options& opts = cmdline_options ()) + : application (opts) + { } - cli_application (int argc, char **argv) - : application (argc, argv) - { } + cli_application (int argc, char **argv) + : application (argc, argv) + { } - // No copying, at least not yet... + // No copying, at least not yet... - cli_application (const cli_application&) = delete; + cli_application (const cli_application&) = delete; - cli_application& operator = (const cli_application&) = delete; + cli_application& operator = (const cli_application&) = delete; - ~cli_application (void) = default; + ~cli_application (void) = default; - int execute (void); - }; + int execute (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-b-sbm.cc --- a/libinterp/operators/op-b-sbm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-b-sbm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -81,7 +81,7 @@ const octave_bool& v = dynamic_cast (a); return new octave_sparse_bool_matrix - (SparseBoolMatrix (1, 1, v.bool_value ())); + (SparseBoolMatrix (1, 1, v.bool_value ())); } void diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-bm-sbm.cc --- a/libinterp/operators/op-bm-sbm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-bm-sbm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -82,7 +82,7 @@ { const octave_bool_matrix& v = dynamic_cast (a); return new octave_sparse_bool_matrix - (SparseBoolMatrix (v.bool_matrix_value ())); + (SparseBoolMatrix (v.bool_matrix_value ())); } DEFNDASSIGNOP_FN (assign, bool_matrix, sparse_bool_matrix, bool_array, assign) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-cs-scm.cc --- a/libinterp/operators/op-cs-scm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-cs-scm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -55,7 +55,7 @@ if (v2.rows () == 1 && v2.columns () == 1) return octave_value (SparseComplexMatrix (1, 1, v1.complex_value () - / v2.complex_value ())); + / v2.complex_value ())); else { MatrixType typ = v2.matrix_type (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-fm-fcm.cc --- a/libinterp/operators/op-fm-fcm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-fm-fcm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -169,7 +169,7 @@ const octave_float_matrix& v = dynamic_cast (a); return new octave_float_complex_matrix (FloatComplexNDArray - (v.float_array_value ())); + (v.float_array_value ())); } void diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-fs-fcm.cc --- a/libinterp/operators/op-fs-fcm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-fs-fcm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -133,7 +133,7 @@ const octave_float_scalar& v = dynamic_cast (a); return new octave_float_complex_matrix (FloatComplexMatrix - (v.float_matrix_value ())); + (v.float_matrix_value ())); } void diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-s-scm.cc --- a/libinterp/operators/op-s-scm.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-s-scm.cc Thu Dec 01 20:05:44 2022 -0800 @@ -58,7 +58,7 @@ if (v2.rows () == 1 && v2.columns () == 1) return octave_value (SparseComplexMatrix (1, 1, v1.scalar_value () - / v2.complex_value ())); + / v2.complex_value ())); else { MatrixType typ = v2.matrix_type (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-scm-cs.cc --- a/libinterp/operators/op-scm-cs.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-scm-cs.cc Thu Dec 01 20:05:44 2022 -0800 @@ -73,7 +73,7 @@ if (v1.rows () == 1 && v1.columns () == 1) return octave_value (SparseComplexMatrix (1, 1, v2.complex_value () - / v1.complex_value ())); + / v1.complex_value ())); else { MatrixType typ = v1.matrix_type (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-scm-s.cc --- a/libinterp/operators/op-scm-s.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-scm-s.cc Thu Dec 01 20:05:44 2022 -0800 @@ -81,7 +81,7 @@ if (v1.rows () == 1 && v1.columns () == 1) return octave_value (SparseComplexMatrix (1, 1, v2.scalar_value () - / v1.complex_value ())); + / v1.complex_value ())); else { MatrixType typ = v1.matrix_type (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/op-sm-cs.cc --- a/libinterp/operators/op-sm-cs.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/op-sm-cs.cc Thu Dec 01 20:05:44 2022 -0800 @@ -72,7 +72,7 @@ if (v1.rows () == 1 && v1.columns () == 1) return octave_value (SparseComplexMatrix (1, 1, v2.complex_value () - / v1.scalar_value ())); + / v1.scalar_value ())); else { MatrixType typ = v1.matrix_type (); diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/operators/ops.h --- a/libinterp/operators/ops.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/operators/ops.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,7 +33,7 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class type_info; +class type_info; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/anon-fcn-validator.cc --- a/libinterp/parse-tree/anon-fcn-validator.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/anon-fcn-validator.cc Thu Dec 01 20:05:44 2022 -0800 @@ -35,50 +35,50 @@ OCTAVE_BEGIN_NAMESPACE(octave) - anon_fcn_validator::anon_fcn_validator (tree_parameter_list *, - tree_expression *expr) - : m_ok (true), m_line (-1), m_column (-1), m_message () - { - expr->accept (*this); - } +anon_fcn_validator::anon_fcn_validator (tree_parameter_list *, + tree_expression *expr) + : m_ok (true), m_line (-1), m_column (-1), m_message () +{ + expr->accept (*this); +} - void anon_fcn_validator::visit_postfix_expression (tree_postfix_expression& expr) - { - octave_value::unary_op op = expr.op_type (); +void anon_fcn_validator::visit_postfix_expression (tree_postfix_expression& expr) +{ + octave_value::unary_op op = expr.op_type (); - if (op == octave_value::op_incr || op == octave_value::op_decr) - error (expr); - else - tree_walker::visit_postfix_expression (expr); - } + if (op == octave_value::op_incr || op == octave_value::op_decr) + error (expr); + else + tree_walker::visit_postfix_expression (expr); +} - void anon_fcn_validator::visit_prefix_expression (tree_prefix_expression& expr) - { - octave_value::unary_op op = expr.op_type (); +void anon_fcn_validator::visit_prefix_expression (tree_prefix_expression& expr) +{ + octave_value::unary_op op = expr.op_type (); - if (op == octave_value::op_incr || op == octave_value::op_decr) - error (expr); - else - tree_walker::visit_prefix_expression (expr); - } + if (op == octave_value::op_incr || op == octave_value::op_decr) + error (expr); + else + tree_walker::visit_prefix_expression (expr); +} - void anon_fcn_validator::visit_multi_assignment (tree_multi_assignment& expr) - { - error (expr); - } +void anon_fcn_validator::visit_multi_assignment (tree_multi_assignment& expr) +{ + error (expr); +} - void anon_fcn_validator::visit_simple_assignment (tree_simple_assignment& expr) - { - error (expr); - } +void anon_fcn_validator::visit_simple_assignment (tree_simple_assignment& expr) +{ + error (expr); +} - void anon_fcn_validator::error (tree_expression& expr) - { - m_ok = false; - m_line = expr.line (); - m_column = expr.column (); - m_message - = "invalid use of operator " + expr.oper () + " in anonymous function"; - } +void anon_fcn_validator::error (tree_expression& expr) +{ + m_ok = false; + m_line = expr.line (); + m_column = expr.column (); + m_message + = "invalid use of operator " + expr.oper () + " in anonymous function"; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/anon-fcn-validator.h --- a/libinterp/parse-tree/anon-fcn-validator.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/anon-fcn-validator.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,49 +34,49 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_expression; - class tree_parameter_list; +class tree_expression; +class tree_parameter_list; - // How to check the semantics of the code that the parse trees represent. +// How to check the semantics of the code that the parse trees represent. - class anon_fcn_validator : public tree_walker - { - public: +class anon_fcn_validator : public tree_walker +{ +public: - anon_fcn_validator (tree_parameter_list *, tree_expression *expr); + anon_fcn_validator (tree_parameter_list *, tree_expression *expr); - // No copying! + // No copying! - anon_fcn_validator (const anon_fcn_validator&) = delete; + anon_fcn_validator (const anon_fcn_validator&) = delete; - anon_fcn_validator& operator = (const anon_fcn_validator&) = delete; + anon_fcn_validator& operator = (const anon_fcn_validator&) = delete; - ~anon_fcn_validator (void) = default; + ~anon_fcn_validator (void) = default; - void visit_postfix_expression (tree_postfix_expression&); + void visit_postfix_expression (tree_postfix_expression&); - void visit_prefix_expression (tree_prefix_expression&); + void visit_prefix_expression (tree_prefix_expression&); - void visit_multi_assignment (tree_multi_assignment&); + void visit_multi_assignment (tree_multi_assignment&); - void visit_simple_assignment (tree_simple_assignment&); + void visit_simple_assignment (tree_simple_assignment&); - bool ok (void) const { return m_ok; } + bool ok (void) const { return m_ok; } - int line (void) const { return m_line; } - int column (void) const { return m_column; } + int line (void) const { return m_line; } + int column (void) const { return m_column; } - std::string message (void) const { return m_message; } + std::string message (void) const { return m_message; } - private: +private: - bool m_ok; - int m_line; - int m_column; - std::string m_message; + bool m_ok; + int m_line; + int m_column; + std::string m_message; - void error (tree_expression& expr); - }; + void error (tree_expression& expr); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/bp-table.cc --- a/libinterp/parse-tree/bp-table.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/bp-table.cc Thu Dec 01 20:05:44 2022 -0800 @@ -56,482 +56,482 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class bp_file_info - { - public: - - bp_file_info (tree_evaluator& tw, const std::string& file) - : m_ok (false), m_file (file), m_dir (), m_fcn (), m_class_name () - { - std::string abs_file = sys::env::make_absolute (file); - - std::string dir = sys::file_ops::dirname (abs_file); - std::string fcn = sys::file_ops::tail (abs_file); - std::size_t len = fcn.length (); - if (len >= 2 && fcn[len-2] == '.' && fcn[len-1] == 'm') - fcn = fcn.substr (0, len-2); - - std::size_t pos = dir.rfind (sys::file_ops::dir_sep_chars ()); - - if (pos != std::string::npos && pos < dir.length () - 1) - { - if (dir[pos+1] == '@') - { - m_class_name = dir.substr (pos+1); +class bp_file_info +{ +public: - fcn = sys::file_ops::concat (m_class_name, fcn); - - dir = dir.substr (0, pos); - } - } - - m_dir = dir; - m_fcn = fcn; - - interpreter& interp = tw.get_interpreter (); - - load_path& lp = interp.get_load_path (); - - if (lp.contains_file_in_dir (m_file, m_dir)) - m_ok = true; - } - - std::string file (void) const { return m_file; } - std::string dir (void) const { return m_fcn; } - std::string fcn (void) const { return m_fcn; } - std::string class_name (void) const { return m_class_name; } - - bool ok (void) const { return m_ok; } - - private: + bp_file_info (tree_evaluator& tw, const std::string& file) + : m_ok (false), m_file (file), m_dir (), m_fcn (), m_class_name () + { + std::string abs_file = sys::env::make_absolute (file); - bool m_ok; - std::string m_file; - std::string m_dir; - std::string m_fcn; - std::string m_class_name; - }; - - // Clear all reasons to stop, other than breakpoints. - - void bp_table::dbclear_all_signals (void) - { - interpreter& interp = m_evaluator.get_interpreter (); - error_system& es = interp.get_error_system (); - - es.debug_on_error (false); - bp_table::m_errors_that_stop.clear (); - - es.debug_on_caught (false); - bp_table::m_caught_that_stop.clear (); - - es.debug_on_warning (false); - bp_table::m_warnings_that_stop.clear (); + std::string dir = sys::file_ops::dirname (abs_file); + std::string fcn = sys::file_ops::tail (abs_file); + std::size_t len = fcn.length (); + if (len >= 2 && fcn[len-2] == '.' && fcn[len-1] == 'm') + fcn = fcn.substr (0, len-2); - Vdebug_on_interrupt = false; - } - - // Process the "warn", "errs", "caught" and "intr" fields for a call of - // "dbstop (p)". - - void bp_table::dbstop_process_map_args (const octave_map& mv) - { - interpreter& interp = m_evaluator.get_interpreter (); - error_system& es = interp.get_error_system (); + std::size_t pos = dir.rfind (sys::file_ops::dir_sep_chars ()); - // process errs - // why so many levels of indirection needed? - bool fail = false; - Cell U = mv.contents ("errs"); - if (U.numel () != 1) - fail = (U.numel () > 1); - else + if (pos != std::string::npos && pos < dir.length () - 1) { - Array W = U.index (0); - if (W.isempty () || W(0).isempty ()) - es.debug_on_error (true); // like "dbstop if error" with no identifier - else if (! W(0).iscell ()) - fail = true; - else + if (dir[pos+1] == '@') { - Cell V = W(0).cell_value (); - for (int i = 0; i < V.numel (); i++) - { - m_errors_that_stop.insert (V(i).string_value ()); - es.debug_on_error (true); - } - } - } - - if (fail) - error ("dbstop: invalid 'errs' field"); - - // process caught - // why so many levels of indirection needed? - fail = false; - U = mv.contents ("caught"); - if (U.numel () != 1) - fail = (U.numel () > 1); - else - { - Array W = U.index (0); - if (W.isempty () || W(0).isempty ()) - es.debug_on_caught (true); // like "dbstop if caught error" with no ID - else if (! W(0).iscell ()) - fail = true; - else - { - Cell V = W(0).cell_value (); - for (int i = 0; i < V.numel (); i++) - { - m_caught_that_stop.insert (V(i).string_value ()); - es.debug_on_caught (true); - } - } - } - - if (fail) - error ("dbstop: invalid 'caught' field"); + m_class_name = dir.substr (pos+1); - // process warn - // why so many levels of indirection needed? - fail = false; - U = mv.contents ("warn"); - if (U.numel () != 1) - fail = (U.numel () > 1); - else - { - Array W = U.index (0); - if (W.isempty () || W(0).isempty ()) - es.debug_on_warning (true); // like "dbstop if warning" with no identifier - else if (! W(0).iscell ()) - fail = true; - else - { - Cell V = W(0).cell_value (); - for (int i = 0; i < V.numel (); i++) - { - m_warnings_that_stop.insert (V(i).string_value ()); - es.debug_on_warning (true); - } - } - } - - if (fail) - error ("dbstop: invalid 'warn' field"); - - // process interrupt - if (mv.isfield ("intr")) - Vdebug_on_interrupt = true; - } - - // Insert a breakpoint in function fcn at line within file fname, - // to stop only when condition is true. - // Record in m_bp_set that fname contains a breakpoint. + fcn = sys::file_ops::concat (m_class_name, fcn); - bool bp_table::add_breakpoint_1 (octave_user_code *fcn, - const std::string& fname, - const bp_table::bp_lines& line, - const std::string& condition, - bp_table::bp_lines& retval) - { - bool found = false; - - tree_statement_list *cmds = fcn->body (); - - std::string file = fcn->fcn_file_name (); - - if (cmds) - { - interpreter& interp = m_evaluator.get_interpreter (); - - event_manager& evmgr = interp.get_event_manager (); - - retval = cmds->add_breakpoint (evmgr, file, line, condition); - - for (auto& lineno : retval) - { - if (lineno != 0) - { - // Normalize to store only the file name. - // Otherwise, there can be an entry for both - // file>subfunction and file, which causes a crash on - // dbclear all - const char *s = strchr (fname.c_str (), '>'); - if (s) - m_bp_set.insert (fname.substr (0, s - fname.c_str ())); - else - m_bp_set.insert (fname); - found = true; - break; - } + dir = dir.substr (0, pos); } } - return found; - } - - // Cursory check that cond is a valid condition to use for a breakpoint. - // Currently allows conditions with side-effects, like 'y+=10' and 'y++'; - // it is odd that the former is not flagged by "is_assignment_expression". - // Throws an exception if not valid. + m_dir = dir; + m_fcn = fcn; - bool bp_table::condition_valid (const std::string& cond) - { - if (cond.length () > 0) - { - // ; to reject partial expr like "y==" - parser parser (cond + " ;", m_evaluator.get_interpreter ()); - parser.reset (); - int parse_status = parser.run (); - if (parse_status) - error ("dbstop: Cannot parse condition '%s'", cond.c_str ()); - else - { - tree_statement *stmt = nullptr; + interpreter& interp = tw.get_interpreter (); - std::shared_ptr stmt_list - = parser.statement_list (); + load_path& lp = interp.get_load_path (); - if (! stmt_list) - error ("dbstop: " - "condition is not empty, but has nothing to evaluate"); - else - { - if (stmt_list->length () == 1 - && (stmt = stmt_list->front ()) - && stmt->is_expression ()) - { - tree_expression *expr = stmt->expression (); - if (expr->is_assignment_expression ()) - error ("dbstop: condition cannot be an assignment. " - "Did you mean '=='?"); - } - else - error ("dbstop: condition must be an expression"); - } - } - } - - return true; + if (lp.contains_file_in_dir (m_file, m_dir)) + m_ok = true; } - enum dbstop_args - { - dbstop_in, - dbstop_at, - dbstop_if, - dbstop_none - }; + std::string file (void) const { return m_file; } + std::string dir (void) const { return m_fcn; } + std::string fcn (void) const { return m_fcn; } + std::string class_name (void) const { return m_class_name; } + + bool ok (void) const { return m_ok; } + +private: + + bool m_ok; + std::string m_file; + std::string m_dir; + std::string m_fcn; + std::string m_class_name; +}; + +// Clear all reasons to stop, other than breakpoints. - // FIXME: This function probably needs to be completely overhauled to - // correctly parse the full syntax of the dbstop command and properly - // reject incorrect forms. +void bp_table::dbclear_all_signals (void) +{ + interpreter& interp = m_evaluator.get_interpreter (); + error_system& es = interp.get_error_system (); + + es.debug_on_error (false); + bp_table::m_errors_that_stop.clear (); + + es.debug_on_caught (false); + bp_table::m_caught_that_stop.clear (); + + es.debug_on_warning (false); + bp_table::m_warnings_that_stop.clear (); + + Vdebug_on_interrupt = false; +} + +// Process the "warn", "errs", "caught" and "intr" fields for a call of +// "dbstop (p)". + +void bp_table::dbstop_process_map_args (const octave_map& mv) +{ + interpreter& interp = m_evaluator.get_interpreter (); + error_system& es = interp.get_error_system (); - // Parse parameters (args) of dbstop and dbclear commands. - // For dbstop, who=="dbstop"; for dbclear, who=="dbclear". - // The syntax is: dbstop [[in] symbol] [[at] [method | line [line [...]]]] [if condition] - // where the form of condition depends on whether or not a file or line has - // been seen. IF symbol and method are specified, then symbol should - // be a class name. Otherwise it should be a function name. - // Also execute "if [error|warning|interrupt|naninf]" clauses. + // process errs + // why so many levels of indirection needed? + bool fail = false; + Cell U = mv.contents ("errs"); + if (U.numel () != 1) + fail = (U.numel () > 1); + else + { + Array W = U.index (0); + if (W.isempty () || W(0).isempty ()) + es.debug_on_error (true); // like "dbstop if error" with no identifier + else if (! W(0).iscell ()) + fail = true; + else + { + Cell V = W(0).cell_value (); + for (int i = 0; i < V.numel (); i++) + { + m_errors_that_stop.insert (V(i).string_value ()); + es.debug_on_error (true); + } + } + } + + if (fail) + error ("dbstop: invalid 'errs' field"); - void bp_table::parse_dbfunction_params (const char *who, - const octave_value_list& args, - std::string& fcn_name, - std::string& class_name, - bp_table::bp_lines& lines, - std::string& cond) - { - int nargin = args.length (); - fcn_name = ""; - class_name = ""; - lines = bp_table::bp_lines (); + // process caught + // why so many levels of indirection needed? + fail = false; + U = mv.contents ("caught"); + if (U.numel () != 1) + fail = (U.numel () > 1); + else + { + Array W = U.index (0); + if (W.isempty () || W(0).isempty ()) + es.debug_on_caught (true); // like "dbstop if caught error" with no ID + else if (! W(0).iscell ()) + fail = true; + else + { + Cell V = W(0).cell_value (); + for (int i = 0; i < V.numel (); i++) + { + m_caught_that_stop.insert (V(i).string_value ()); + es.debug_on_caught (true); + } + } + } - if (nargin == 0 || ! args(0).is_string ()) - print_usage (who); + if (fail) + error ("dbstop: invalid 'caught' field"); - // elements already processed - bool seen_in = false; - bool seen_at = false; - bool seen_if = false; - int pos = 0; - dbstop_args tok = dbstop_none; - while (pos < nargin) - { - // allow "in" and "at" to be implicit - if (args(pos).is_string ()) - { - std::string arg = args(pos).string_value (); - if (arg == "in") - { - tok = dbstop_in; - pos++; - } - else if (arg == "at") - { - tok = dbstop_at; - pos++; - } - else if (arg == "if") - { - tok = dbstop_if; - pos++; - } - else if (atoi (args(pos).string_value ().c_str ()) > 0) - tok = dbstop_at; - else - tok = dbstop_in; - } - else - tok = dbstop_at; + // process warn + // why so many levels of indirection needed? + fail = false; + U = mv.contents ("warn"); + if (U.numel () != 1) + fail = (U.numel () > 1); + else + { + Array W = U.index (0); + if (W.isempty () || W(0).isempty ()) + es.debug_on_warning (true); // like "dbstop if warning" with no identifier + else if (! W(0).iscell ()) + fail = true; + else + { + Cell V = W(0).cell_value (); + for (int i = 0; i < V.numel (); i++) + { + m_warnings_that_stop.insert (V(i).string_value ()); + es.debug_on_warning (true); + } + } + } + + if (fail) + error ("dbstop: invalid 'warn' field"); + + // process interrupt + if (mv.isfield ("intr")) + Vdebug_on_interrupt = true; +} + +// Insert a breakpoint in function fcn at line within file fname, +// to stop only when condition is true. +// Record in m_bp_set that fname contains a breakpoint. + +bool bp_table::add_breakpoint_1 (octave_user_code *fcn, + const std::string& fname, + const bp_table::bp_lines& line, + const std::string& condition, + bp_table::bp_lines& retval) +{ + bool found = false; + + tree_statement_list *cmds = fcn->body (); + + std::string file = fcn->fcn_file_name (); + + if (cmds) + { + interpreter& interp = m_evaluator.get_interpreter (); + + event_manager& evmgr = interp.get_event_manager (); + + retval = cmds->add_breakpoint (evmgr, file, line, condition); - if (pos >= nargin) - error ("%s: '%s' missing argument", who, - (tok == dbstop_in - ? "in" : (tok == dbstop_at ? "at" : "if"))); + for (auto& lineno : retval) + { + if (lineno != 0) + { + // Normalize to store only the file name. + // Otherwise, there can be an entry for both + // file>subfunction and file, which causes a crash on + // dbclear all + const char *s = strchr (fname.c_str (), '>'); + if (s) + m_bp_set.insert (fname.substr (0, s - fname.c_str ())); + else + m_bp_set.insert (fname); + found = true; + break; + } + } + } + + return found; +} + +// Cursory check that cond is a valid condition to use for a breakpoint. +// Currently allows conditions with side-effects, like 'y+=10' and 'y++'; +// it is odd that the former is not flagged by "is_assignment_expression". +// Throws an exception if not valid. - // process the actual arguments - switch (tok) - { - case dbstop_in: - fcn_name = args(pos).string_value (); - if (seen_in) - error ("%s: Too many function names specified -- %s", - who, fcn_name.c_str ()); - else if (seen_at || seen_if) - error ("%s: function name must come before line number and 'if'", - who); - seen_in = true; - pos++; - break; +bool bp_table::condition_valid (const std::string& cond) +{ + if (cond.length () > 0) + { + // ; to reject partial expr like "y==" + parser parser (cond + " ;", m_evaluator.get_interpreter ()); + parser.reset (); + int parse_status = parser.run (); + if (parse_status) + error ("dbstop: Cannot parse condition '%s'", cond.c_str ()); + else + { + tree_statement *stmt = nullptr; + + std::shared_ptr stmt_list + = parser.statement_list (); - case dbstop_at: - if (seen_at) - error ("%s: Only one 'at' clause is allowed -- %s", - who, args(pos).string_value ().c_str ()); - else if (seen_if) - error ("%s: line number must come before 'if' clause\n", who); - seen_at = true; - - if (seen_if) - error ("%s: line number must come before 'if' clause\n", who); - else if (seen_in) - { - std::string arg = args(pos).string_value (); - - // FIXME: we really want to distinguish number - // vs. method name here. + if (! stmt_list) + error ("dbstop: " + "condition is not empty, but has nothing to evaluate"); + else + { + if (stmt_list->length () == 1 + && (stmt = stmt_list->front ()) + && stmt->is_expression ()) + { + tree_expression *expr = stmt->expression (); + if (expr->is_assignment_expression ()) + error ("dbstop: condition cannot be an assignment. " + "Did you mean '=='?"); + } + else + error ("dbstop: condition must be an expression"); + } + } + } - if (atoi (arg.c_str ()) == 0) - { - // We have class and function names but already - // stored the class name in fcn_name. - class_name = fcn_name; - fcn_name = arg; - pos++; - break; - } + return true; +} + +enum dbstop_args +{ + dbstop_in, + dbstop_at, + dbstop_if, + dbstop_none +}; + +// FIXME: This function probably needs to be completely overhauled to +// correctly parse the full syntax of the dbstop command and properly +// reject incorrect forms. - } - else - { - // It was a line number. Get function name from debugger. - if (m_evaluator.in_debug_repl ()) - fcn_name = m_evaluator.get_user_code ()->profiler_name (); - else - error ("%s: function name must come before line number " - "and 'if'", who); - seen_in = true; - } +// Parse parameters (args) of dbstop and dbclear commands. +// For dbstop, who=="dbstop"; for dbclear, who=="dbclear". +// The syntax is: dbstop [[in] symbol] [[at] [method | line [line [...]]]] [if condition] +// where the form of condition depends on whether or not a file or line has +// been seen. IF symbol and method are specified, then symbol should +// be a class name. Otherwise it should be a function name. +// Also execute "if [error|warning|interrupt|naninf]" clauses. + +void bp_table::parse_dbfunction_params (const char *who, + const octave_value_list& args, + std::string& fcn_name, + std::string& class_name, + bp_table::bp_lines& lines, + std::string& cond) +{ + int nargin = args.length (); + fcn_name = ""; + class_name = ""; + lines = bp_table::bp_lines (); + + if (nargin == 0 || ! args(0).is_string ()) + print_usage (who); - // Read a list of line numbers (or arrays thereof) - for ( ; pos < nargin; pos++) - { - if (args(pos).is_string ()) - { - int line = atoi (args(pos).string_value ().c_str ()); + // elements already processed + bool seen_in = false; + bool seen_at = false; + bool seen_if = false; + int pos = 0; + dbstop_args tok = dbstop_none; + while (pos < nargin) + { + // allow "in" and "at" to be implicit + if (args(pos).is_string ()) + { + std::string arg = args(pos).string_value (); + if (arg == "in") + { + tok = dbstop_in; + pos++; + } + else if (arg == "at") + { + tok = dbstop_at; + pos++; + } + else if (arg == "if") + { + tok = dbstop_if; + pos++; + } + else if (atoi (args(pos).string_value ().c_str ()) > 0) + tok = dbstop_at; + else + tok = dbstop_in; + } + else + tok = dbstop_at; - if (line > 0) - lines.insert (line); - else - break; // may be "if" or a method name - } - else if (args(pos).isnumeric ()) - { - const NDArray arg = args(pos).array_value (); + if (pos >= nargin) + error ("%s: '%s' missing argument", who, + (tok == dbstop_in + ? "in" : (tok == dbstop_at ? "at" : "if"))); - for (octave_idx_type j = 0; j < arg.numel (); j++) - lines.insert (static_cast (arg.elem (j))); - } - else - error ("%s: Invalid argument type %s", - who, args(pos).type_name ().c_str ()); - } - break; + // process the actual arguments + switch (tok) + { + case dbstop_in: + fcn_name = args(pos).string_value (); + if (seen_in) + error ("%s: Too many function names specified -- %s", + who, fcn_name.c_str ()); + else if (seen_at || seen_if) + error ("%s: function name must come before line number and 'if'", + who); + seen_in = true; + pos++; + break; + + case dbstop_at: + if (seen_at) + error ("%s: Only one 'at' clause is allowed -- %s", + who, args(pos).string_value ().c_str ()); + else if (seen_if) + error ("%s: line number must come before 'if' clause\n", who); + seen_at = true; + + if (seen_if) + error ("%s: line number must come before 'if' clause\n", who); + else if (seen_in) + { + std::string arg = args(pos).string_value (); + + // FIXME: we really want to distinguish number + // vs. method name here. - case dbstop_if: - if (seen_in) // conditional breakpoint - { - cond = ""; // remaining arguments form condition - for (; pos < nargin; pos++) - { - if (args(pos).is_string ()) - cond += ' ' + args(pos).string_value (); - else - error ("%s: arguments to 'if' must all be strings", who); - } + if (atoi (arg.c_str ()) == 0) + { + // We have class and function names but already + // stored the class name in fcn_name. + class_name = fcn_name; + fcn_name = arg; + pos++; + break; + } + + } + else + { + // It was a line number. Get function name from debugger. + if (m_evaluator.in_debug_repl ()) + fcn_name = m_evaluator.get_user_code ()->profiler_name (); + else + error ("%s: function name must come before line number " + "and 'if'", who); + seen_in = true; + } + + // Read a list of line numbers (or arrays thereof) + for ( ; pos < nargin; pos++) + { + if (args(pos).is_string ()) + { + int line = atoi (args(pos).string_value ().c_str ()); + + if (line > 0) + lines.insert (line); + else + break; // may be "if" or a method name + } + else if (args(pos).isnumeric ()) + { + const NDArray arg = args(pos).array_value (); - cond = cond.substr (1); // omit initial space - } - else // stop on event (error, warning, interrupt, NaN/inf) - { - std::string condition = args(pos).string_value (); - bool on_off = ! strcmp (who, "dbstop"); + for (octave_idx_type j = 0; j < arg.numel (); j++) + lines.insert (static_cast (arg.elem (j))); + } + else + error ("%s: Invalid argument type %s", + who, args(pos).type_name ().c_str ()); + } + break; + + case dbstop_if: + if (seen_in) // conditional breakpoint + { + cond = ""; // remaining arguments form condition + for (; pos < nargin; pos++) + { + if (args(pos).is_string ()) + cond += ' ' + args(pos).string_value (); + else + error ("%s: arguments to 'if' must all be strings", who); + } - // FIXME: the following seems a bit messy in the way it - // duplicates checks on CONDITION. + cond = cond.substr (1); // omit initial space + } + else // stop on event (error, warning, interrupt, NaN/inf) + { + std::string condition = args(pos).string_value (); + bool on_off = ! strcmp (who, "dbstop"); + + // FIXME: the following seems a bit messy in the way it + // duplicates checks on CONDITION. - if (condition == "error") - process_id_list (who, condition, args, nargin, pos, on_off, - m_errors_that_stop); - else if (condition == "warning") + if (condition == "error") + process_id_list (who, condition, args, nargin, pos, on_off, + m_errors_that_stop); + else if (condition == "warning") + process_id_list (who, condition, args, nargin, pos, on_off, + m_warnings_that_stop); + else if (condition == "caught" && nargin > pos+1 + && args(pos+1).string_value () == "error") + { + pos++; process_id_list (who, condition, args, nargin, pos, on_off, - m_warnings_that_stop); - else if (condition == "caught" && nargin > pos+1 - && args(pos+1).string_value () == "error") - { - pos++; - process_id_list (who, condition, args, nargin, pos, on_off, - m_caught_that_stop); - } - else if (condition == "interrupt") - { - Vdebug_on_interrupt = on_off; - } - else if (condition == "naninf") - { + m_caught_that_stop); + } + else if (condition == "interrupt") + { + Vdebug_on_interrupt = on_off; + } + else if (condition == "naninf") + { #if defined (DBSTOP_NANINF) - Vdebug_on_naninf = on_off; - enable_fpe (on_off); + Vdebug_on_naninf = on_off; + enable_fpe (on_off); #else - warning ("%s: condition '%s' not yet supported", - who, condition.c_str ()); + warning ("%s: condition '%s' not yet supported", + who, condition.c_str ()); #endif - } - else - error ("%s: invalid condition %s", - who, condition.c_str ()); + } + else + error ("%s: invalid condition %s", + who, condition.c_str ()); - pos = nargin; - } - break; + pos = nargin; + } + break; - default: // dbstop_none should never occur - break; - } - } - } + default: // dbstop_none should never occur + break; + } + } +} /* %!test @@ -549,603 +549,603 @@ %! assert (s.errs, {"Octave:undefined-function"}); */ - void bp_table::set_stop_flag (const char *who, const std::string& condition, - bool on_off) - { - interpreter& interp = m_evaluator.get_interpreter (); - error_system& es = interp.get_error_system (); +void bp_table::set_stop_flag (const char *who, const std::string& condition, + bool on_off) +{ + interpreter& interp = m_evaluator.get_interpreter (); + error_system& es = interp.get_error_system (); - if (condition == "error") - es.debug_on_error (on_off); - else if (condition == "warning") - es.debug_on_warning (on_off); - else if (condition == "caught") - es.debug_on_caught (on_off); - else - error ("%s: internal error in set_stop_flag", who); - } + if (condition == "error") + es.debug_on_error (on_off); + else if (condition == "warning") + es.debug_on_warning (on_off); + else if (condition == "caught") + es.debug_on_caught (on_off); + else + error ("%s: internal error in set_stop_flag", who); +} - void bp_table::process_id_list (const char *who, - const std::string& condition, - const octave_value_list& args, - int nargin, int& pos, bool on_off, - std::set& id_list) - { - pos++; +void bp_table::process_id_list (const char *who, + const std::string& condition, + const octave_value_list& args, + int nargin, int& pos, bool on_off, + std::set& id_list) +{ + pos++; - if (nargin > pos) // only affect a single error ID - { - if (! args(pos).is_string () || nargin > pos+1) - error ("%s: ID must be a single string", who); - else if (on_off) - { - id_list.insert (args(pos).string_value ()); - set_stop_flag (who, condition, true); - } - else - { - id_list.erase (args(pos).string_value ()); - if (id_list.empty ()) - set_stop_flag (who, condition, false); - } - } - else // unqualified. Turn all on or off - { - id_list.clear (); - set_stop_flag (who, condition, on_off); + if (nargin > pos) // only affect a single error ID + { + if (! args(pos).is_string () || nargin > pos+1) + error ("%s: ID must be a single string", who); + else if (on_off) + { + id_list.insert (args(pos).string_value ()); + set_stop_flag (who, condition, true); + } + else + { + id_list.erase (args(pos).string_value ()); + if (id_list.empty ()) + set_stop_flag (who, condition, false); + } + } + else // unqualified. Turn all on or off + { + id_list.clear (); + set_stop_flag (who, condition, on_off); - if (condition == "error") - { - // Matlab stops on both. - Vdebug_on_interrupt = on_off; - } - } - } + if (condition == "error") + { + // Matlab stops on both. + Vdebug_on_interrupt = on_off; + } + } +} - // Return the sub/nested/main function of MAIN_FCN that contains - // line number LINENO of the source file. - // If END_LINE != 0, *END_LINE is set to last line of the returned function. +// Return the sub/nested/main function of MAIN_FCN that contains +// line number LINENO of the source file. +// If END_LINE != 0, *END_LINE is set to last line of the returned function. - static octave_user_code * find_fcn_by_line (octave_user_code *main_fcn, - int lineno, - int *end_line = nullptr) - { - octave_user_code *retval = nullptr; - octave_user_code *next_fcn = nullptr; // 1st function starting after lineno +static octave_user_code * find_fcn_by_line (octave_user_code *main_fcn, + int lineno, + int *end_line = nullptr) +{ + octave_user_code *retval = nullptr; + octave_user_code *next_fcn = nullptr; // 1st function starting after lineno - // Find innermost nested (or parent) function containing lineno. - int earliest_end = std::numeric_limits::max (); + // Find innermost nested (or parent) function containing lineno. + int earliest_end = std::numeric_limits::max (); - std::map subfcns = main_fcn->subfunctions (); - for (const auto& str_val_p : subfcns) - { - if (str_val_p.second.is_user_function ()) - { - auto *dbg_subfcn = str_val_p.second.user_function_value (); + std::map subfcns = main_fcn->subfunctions (); + for (const auto& str_val_p : subfcns) + { + if (str_val_p.second.is_user_function ()) + { + auto *dbg_subfcn = str_val_p.second.user_function_value (); - // Check if lineno is within dbg_subfcn. - // FIXME: we could break when beginning_line() > lineno, - // but that makes the code "fragile" - // if the order of walking subfcns changes, - // for a minor speed improvement in non-critical code. - if (dbg_subfcn->ending_line () < earliest_end - && dbg_subfcn->ending_line () >= lineno - && dbg_subfcn->beginning_line () <= lineno) - { - earliest_end = dbg_subfcn->ending_line (); - retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end); - } + // Check if lineno is within dbg_subfcn. + // FIXME: we could break when beginning_line() > lineno, + // but that makes the code "fragile" + // if the order of walking subfcns changes, + // for a minor speed improvement in non-critical code. + if (dbg_subfcn->ending_line () < earliest_end + && dbg_subfcn->ending_line () >= lineno + && dbg_subfcn->beginning_line () <= lineno) + { + earliest_end = dbg_subfcn->ending_line (); + retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end); + } - // Find the first fcn starting after lineno. - // This is used if line is not inside any function. - if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn) - next_fcn = dbg_subfcn; - } - } + // Find the first fcn starting after lineno. + // This is used if line is not inside any function. + if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn) + next_fcn = dbg_subfcn; + } + } - // The breakpoint is either in the subfunction found above, - // or in the main function, which we check now. - if (main_fcn->is_user_function ()) - { - int e = dynamic_cast (main_fcn)->ending_line (); - if (e >= lineno && e < earliest_end) - retval = main_fcn; + // The breakpoint is either in the subfunction found above, + // or in the main function, which we check now. + if (main_fcn->is_user_function ()) + { + int e = dynamic_cast (main_fcn)->ending_line (); + if (e >= lineno && e < earliest_end) + retval = main_fcn; - if (! retval) - retval = next_fcn; - } - else // main_fcn is a script. - { - if (! retval) - retval = main_fcn; - } + if (! retval) + retval = next_fcn; + } + else // main_fcn is a script. + { + if (! retval) + retval = main_fcn; + } - if (end_line && earliest_end < *end_line) - *end_line = earliest_end; + if (end_line && earliest_end < *end_line) + *end_line = earliest_end; - return retval; - } + return retval; +} - // Given file name fname, find the subfunction at line and create - // a breakpoint there. Put the system into debug_mode. - int bp_table::add_breakpoint_in_function (const std::string& fname, - const std::string& class_name, - int line, - const std::string& condition) - { - bp_lines line_info; - line_info.insert (line); +// Given file name fname, find the subfunction at line and create +// a breakpoint there. Put the system into debug_mode. +int bp_table::add_breakpoint_in_function (const std::string& fname, + const std::string& class_name, + int line, + const std::string& condition) +{ + bp_lines line_info; + line_info.insert (line); - bp_lines result - = add_breakpoints_in_function (fname, class_name, line_info, condition); + bp_lines result + = add_breakpoints_in_function (fname, class_name, line_info, condition); - return result.empty () ? 0 : *(result.begin ()); - } + return result.empty () ? 0 : *(result.begin ()); +} - // Given file name fname, find the subfunction at line and create - // a breakpoint there. Put the system into debug_mode. - bp_table::bp_lines - bp_table::add_breakpoints_in_function (const std::string& fname, - const std::string& class_name, - const bp_table::bp_lines& lines, - const std::string& condition) - { - octave_user_code *main_fcn = m_evaluator.get_user_code (fname, class_name); +// Given file name fname, find the subfunction at line and create +// a breakpoint there. Put the system into debug_mode. +bp_table::bp_lines +bp_table::add_breakpoints_in_function (const std::string& fname, + const std::string& class_name, + const bp_table::bp_lines& lines, + const std::string& condition) +{ + octave_user_code *main_fcn = m_evaluator.get_user_code (fname, class_name); - if (! main_fcn) - error ("add_breakpoints_in_function: unable to find function '%s'\n", - fname.c_str ()); + if (! main_fcn) + error ("add_breakpoints_in_function: unable to find function '%s'\n", + fname.c_str ()); - condition_valid (condition); // Throw error if condition not valid. + condition_valid (condition); // Throw error if condition not valid. - bp_lines retval; + bp_lines retval; - for (const auto& lineno : lines) - { - octave_user_code *dbg_fcn = find_fcn_by_line (main_fcn, lineno); + for (const auto& lineno : lines) + { + octave_user_code *dbg_fcn = find_fcn_by_line (main_fcn, lineno); - // We've found the right (sub)function. Now insert the breakpoint. - bp_lines line_info; - line_info.insert (lineno); + // We've found the right (sub)function. Now insert the breakpoint. + bp_lines line_info; + line_info.insert (lineno); - bp_lines ret_one; - if (dbg_fcn && add_breakpoint_1 (dbg_fcn, fname, line_info, - condition, ret_one)) - { - if (! ret_one.empty ()) - { - int line = *(ret_one.begin ()); + bp_lines ret_one; + if (dbg_fcn && add_breakpoint_1 (dbg_fcn, fname, line_info, + condition, ret_one)) + { + if (! ret_one.empty ()) + { + int line = *(ret_one.begin ()); - if (line) - retval.insert (line); - } - } - } + if (line) + retval.insert (line); + } + } + } - m_evaluator.reset_debug_state (); + m_evaluator.reset_debug_state (); - return retval; - } + return retval; +} - int bp_table::add_breakpoint_in_file (const std::string& file, - int line, - const std::string& condition) - { - // Duplicates what the GUI was doing previously, but this action - // should not be specific to the GUI. +int bp_table::add_breakpoint_in_file (const std::string& file, + int line, + const std::string& condition) +{ + // Duplicates what the GUI was doing previously, but this action + // should not be specific to the GUI. - bp_file_info info (m_evaluator, file); + bp_file_info info (m_evaluator, file); - if (! info.ok ()) - return 0; + if (! info.ok ()) + return 0; - return add_breakpoint_in_function (info.fcn (), info.class_name (), - line, condition); - } + return add_breakpoint_in_function (info.fcn (), info.class_name (), + line, condition); +} - bp_table::bp_lines - bp_table::add_breakpoints_in_file (const std::string& file, - const bp_lines& lines, - const std::string& condition) - { - // Duplicates what the GUI was doing previously, but this action - // should not be specific to the GUI. +bp_table::bp_lines +bp_table::add_breakpoints_in_file (const std::string& file, + const bp_lines& lines, + const std::string& condition) +{ + // Duplicates what the GUI was doing previously, but this action + // should not be specific to the GUI. - bp_file_info info (m_evaluator, file); + bp_file_info info (m_evaluator, file); - if (! info.ok ()) - return bp_lines (); + if (! info.ok ()) + return bp_lines (); - return add_breakpoints_in_function (info.fcn (), info.class_name (), - lines, condition); - } + return add_breakpoints_in_function (info.fcn (), info.class_name (), + lines, condition); +} - int bp_table::remove_breakpoint_1 (octave_user_code *fcn, - const std::string& fname, - const bp_table::bp_lines& lines) - { - int retval = 0; +int bp_table::remove_breakpoint_1 (octave_user_code *fcn, + const std::string& fname, + const bp_table::bp_lines& lines) +{ + int retval = 0; - std::string file = fcn->fcn_file_name (); + std::string file = fcn->fcn_file_name (); - tree_statement_list *cmds = fcn->body (); + tree_statement_list *cmds = fcn->body (); - // FIXME: move the operation on cmds to the tree_statement_list class? + // FIXME: move the operation on cmds to the tree_statement_list class? - if (cmds) - { - octave_value_list results = cmds->list_breakpoints (); + if (cmds) + { + octave_value_list results = cmds->list_breakpoints (); - if (results.length () > 0) - { - interpreter& interp = m_evaluator.get_interpreter (); + if (results.length () > 0) + { + interpreter& interp = m_evaluator.get_interpreter (); - event_manager& evmgr = interp.get_event_manager (); + event_manager& evmgr = interp.get_event_manager (); - for (const auto& lineno : lines) - { - cmds->delete_breakpoint (lineno); + for (const auto& lineno : lines) + { + cmds->delete_breakpoint (lineno); - if (! file.empty ()) - evmgr.update_breakpoint (false, file, lineno); - } + if (! file.empty ()) + evmgr.update_breakpoint (false, file, lineno); + } - results = cmds->list_breakpoints (); + results = cmds->list_breakpoints (); - auto it = m_bp_set.find (fname); - if (results.empty () && it != m_bp_set.end ()) - m_bp_set.erase (it); - } + auto it = m_bp_set.find (fname); + if (results.empty () && it != m_bp_set.end ()) + m_bp_set.erase (it); + } - retval = results.length (); - } + retval = results.length (); + } - return retval; - } + return retval; +} - int - bp_table::remove_breakpoint_from_function (const std::string& fname, int line) - { - bp_lines line_info; - line_info.insert (line); +int +bp_table::remove_breakpoint_from_function (const std::string& fname, int line) +{ + bp_lines line_info; + line_info.insert (line); - return remove_breakpoints_from_function (fname, line_info); - } + return remove_breakpoints_from_function (fname, line_info); +} - int - bp_table::remove_breakpoints_from_function (const std::string& fname, - const bp_table::bp_lines& lines) - { - int retval = 0; +int +bp_table::remove_breakpoints_from_function (const std::string& fname, + const bp_table::bp_lines& lines) +{ + int retval = 0; - if (lines.empty ()) - { - bp_lines results = remove_all_breakpoints_from_function (fname); - retval = results.size (); - } - else - { - octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname); + if (lines.empty ()) + { + bp_lines results = remove_all_breakpoints_from_function (fname); + retval = results.size (); + } + else + { + octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname); - if (! dbg_fcn) - error ("remove_breakpoints_from_function: unable to find function %s\n", - fname.c_str ()); + if (! dbg_fcn) + error ("remove_breakpoints_from_function: unable to find function %s\n", + fname.c_str ()); - retval = remove_breakpoint_1 (dbg_fcn, fname, lines); + retval = remove_breakpoint_1 (dbg_fcn, fname, lines); - // Search subfunctions in the order they appear in the file. + // Search subfunctions in the order they appear in the file. - const std::list subfcn_names - = dbg_fcn->subfunction_names (); + const std::list subfcn_names + = dbg_fcn->subfunction_names (); - std::map subfcns - = dbg_fcn->subfunctions (); + std::map subfcns + = dbg_fcn->subfunctions (); - for (const auto& subf_nm : subfcn_names) - { - const auto q = subfcns.find (subf_nm); + for (const auto& subf_nm : subfcn_names) + { + const auto q = subfcns.find (subf_nm); - if (q != subfcns.end ()) - { - octave_user_code *dbg_subfcn = q->second.user_code_value (); + if (q != subfcns.end ()) + { + octave_user_code *dbg_subfcn = q->second.user_code_value (); - retval += remove_breakpoint_1 (dbg_subfcn, fname, lines); - } - } - } + retval += remove_breakpoint_1 (dbg_subfcn, fname, lines); + } + } + } - m_evaluator.reset_debug_state (); + m_evaluator.reset_debug_state (); - return retval; - } + return retval; +} - // Remove all breakpoints from a file, including those in subfunctions. +// Remove all breakpoints from a file, including those in subfunctions. - bp_table::bp_lines - bp_table::remove_all_breakpoints_from_function (const std::string& fname, - bool silent) - { - bp_lines retval; +bp_table::bp_lines +bp_table::remove_all_breakpoints_from_function (const std::string& fname, + bool silent) +{ + bp_lines retval; - octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname); + octave_user_code *dbg_fcn = m_evaluator.get_user_code (fname); - if (dbg_fcn) - { - std::string file = dbg_fcn->fcn_file_name (); + if (dbg_fcn) + { + std::string file = dbg_fcn->fcn_file_name (); - tree_statement_list *cmds = dbg_fcn->body (); + tree_statement_list *cmds = dbg_fcn->body (); - if (cmds) - { - interpreter& interp = m_evaluator.get_interpreter (); + if (cmds) + { + interpreter& interp = m_evaluator.get_interpreter (); - event_manager& evmgr = interp.get_event_manager (); + event_manager& evmgr = interp.get_event_manager (); - retval = cmds->remove_all_breakpoints (evmgr, file); + retval = cmds->remove_all_breakpoints (evmgr, file); - auto it = m_bp_set.find (fname); - if (it != m_bp_set.end ()) - m_bp_set.erase (it); - } - } - else if (! silent) - error ("remove_all_breakpoints_from_function: " - "unable to find function %s\n", fname.c_str ()); + auto it = m_bp_set.find (fname); + if (it != m_bp_set.end ()) + m_bp_set.erase (it); + } + } + else if (! silent) + error ("remove_all_breakpoints_from_function: " + "unable to find function %s\n", fname.c_str ()); - m_evaluator.reset_debug_state (); + m_evaluator.reset_debug_state (); - return retval; - } + return retval; +} - int - bp_table::remove_breakpoint_from_file (const std::string& file, int line) - { - // Duplicates what the GUI was doing previously, but this action - // should not be specific to the GUI. +int +bp_table::remove_breakpoint_from_file (const std::string& file, int line) +{ + // Duplicates what the GUI was doing previously, but this action + // should not be specific to the GUI. - bp_file_info info (m_evaluator, file); + bp_file_info info (m_evaluator, file); - if (! info.ok ()) - return 0; + if (! info.ok ()) + return 0; - return remove_breakpoint_from_function (info.fcn (), line); - } + return remove_breakpoint_from_function (info.fcn (), line); +} - int - bp_table::remove_breakpoints_from_file (const std::string& file, - const bp_lines& lines) - { - // Duplicates what the GUI was doing previously, but this action - // should not be specific to the GUI. +int +bp_table::remove_breakpoints_from_file (const std::string& file, + const bp_lines& lines) +{ + // Duplicates what the GUI was doing previously, but this action + // should not be specific to the GUI. - bp_file_info info (m_evaluator, file); + bp_file_info info (m_evaluator, file); - if (! info.ok ()) - return 0; + if (! info.ok ()) + return 0; - return remove_breakpoints_from_function (info.fcn (), lines); - } + return remove_breakpoints_from_function (info.fcn (), lines); +} - bp_table::bp_lines - bp_table::remove_all_breakpoints_from_file (const std::string& file, - bool silent) - { - // Duplicates what the GUI was doing previously, but this action - // should not be specific to the GUI. +bp_table::bp_lines +bp_table::remove_all_breakpoints_from_file (const std::string& file, + bool silent) +{ + // Duplicates what the GUI was doing previously, but this action + // should not be specific to the GUI. - bp_file_info info (m_evaluator, file); + bp_file_info info (m_evaluator, file); - if (! info.ok ()) - return bp_lines (); + if (! info.ok ()) + return bp_lines (); - return remove_all_breakpoints_from_function (info.fcn (), silent); - } + return remove_all_breakpoints_from_function (info.fcn (), silent); +} - void bp_table::remove_all_breakpoints (void) - { - // Odd loop structure required because delete will invalidate - // m_bp_set iterators. - for (auto it = m_bp_set.cbegin (), it_next = it; - it != m_bp_set.cend (); - it = it_next) - { - ++it_next; - remove_all_breakpoints_from_function (*it); - } +void bp_table::remove_all_breakpoints (void) +{ + // Odd loop structure required because delete will invalidate + // m_bp_set iterators. + for (auto it = m_bp_set.cbegin (), it_next = it; + it != m_bp_set.cend (); + it = it_next) + { + ++it_next; + remove_all_breakpoints_from_function (*it); + } - m_evaluator.reset_debug_state (); - } + m_evaluator.reset_debug_state (); +} - std::string find_bkpt_list (octave_value_list slist, std::string match) - { - std::string retval; +std::string find_bkpt_list (octave_value_list slist, std::string match) +{ + std::string retval; - for (int i = 0; i < slist.length (); i++) - { - if (slist(i).string_value () == match) - { - retval = slist(i).string_value (); - break; - } - } + for (int i = 0; i < slist.length (); i++) + { + if (slist(i).string_value () == match) + { + retval = slist(i).string_value (); + break; + } + } - return retval; - } + return retval; +} - bp_table::fname_bp_map - bp_table::get_breakpoint_list (const octave_value_list& fname_list) - { - fname_bp_map retval; +bp_table::fname_bp_map +bp_table::get_breakpoint_list (const octave_value_list& fname_list) +{ + fname_bp_map retval; - // make copy since changes may invalidate iters of m_bp_set. - std::set tmp_bp_set = m_bp_set; + // make copy since changes may invalidate iters of m_bp_set. + std::set tmp_bp_set = m_bp_set; - for (auto& bp_fname : tmp_bp_set) - { - if (fname_list.empty () - || find_bkpt_list (fname_list, bp_fname) != "") - { - octave_user_code *dbg_fcn = m_evaluator.get_user_code (bp_fname); + for (auto& bp_fname : tmp_bp_set) + { + if (fname_list.empty () + || find_bkpt_list (fname_list, bp_fname) != "") + { + octave_user_code *dbg_fcn = m_evaluator.get_user_code (bp_fname); - if (dbg_fcn) - { - tree_statement_list *cmds = dbg_fcn->body (); + if (dbg_fcn) + { + tree_statement_list *cmds = dbg_fcn->body (); - // FIXME: move the operation on cmds to the - // tree_statement_list class? - if (cmds) - { - std::list bkpts = cmds->breakpoints_and_conds (); + // FIXME: move the operation on cmds to the + // tree_statement_list class? + if (cmds) + { + std::list bkpts = cmds->breakpoints_and_conds (); - if (! bkpts.empty ()) - retval[bp_fname] = bkpts; - } + if (! bkpts.empty ()) + retval[bp_fname] = bkpts; + } - // look for breakpoints in subfunctions - const std::list subf_nm - = dbg_fcn->subfunction_names (); + // look for breakpoints in subfunctions + const std::list subf_nm + = dbg_fcn->subfunction_names (); - std::map subfcns - = dbg_fcn->subfunctions (); + std::map subfcns + = dbg_fcn->subfunctions (); - for (const auto& subfcn_nm : subf_nm) - { - const auto q = subfcns.find (subfcn_nm); + for (const auto& subfcn_nm : subf_nm) + { + const auto q = subfcns.find (subfcn_nm); - if (q != subfcns.end ()) - { - octave_user_code *dbg_subfcn - = q->second.user_code_value (); + if (q != subfcns.end ()) + { + octave_user_code *dbg_subfcn + = q->second.user_code_value (); - cmds = dbg_subfcn->body (); - if (cmds) - { - std::list bkpts - = cmds->breakpoints_and_conds (); + cmds = dbg_subfcn->body (); + if (cmds) + { + std::list bkpts + = cmds->breakpoints_and_conds (); - if (! bkpts.empty ()) - { - std::string key - = bp_fname + '>' + dbg_subfcn->name (); + if (! bkpts.empty ()) + { + std::string key + = bp_fname + '>' + dbg_subfcn->name (); - retval[key] = bkpts; - } - } - } - } - } - } - } + retval[key] = bkpts; + } + } + } + } + } + } + } - return retval; - } + return retval; +} - // Report the status of "dbstop if error ..." and "dbstop if warning ..." - // If to_screen is true, the output goes to octave_stdout; otherwise it is - // returned. - // If dbstop if error is true but no explicit IDs are specified, the return - // value will have an empty field called "errs". If IDs are specified, the - // "errs" field will have a row per ID. If dbstop if error is false, there - // is no "errs" field. The "warn" field is set similarly by dbstop if warning +// Report the status of "dbstop if error ..." and "dbstop if warning ..." +// If to_screen is true, the output goes to octave_stdout; otherwise it is +// returned. +// If dbstop if error is true but no explicit IDs are specified, the return +// value will have an empty field called "errs". If IDs are specified, the +// "errs" field will have a row per ID. If dbstop if error is false, there +// is no "errs" field. The "warn" field is set similarly by dbstop if warning - octave_map bp_table::stop_on_err_warn_status (bool to_screen) - { - octave_map retval; +octave_map bp_table::stop_on_err_warn_status (bool to_screen) +{ + octave_map retval; - interpreter& interp = m_evaluator.get_interpreter (); - error_system& es = interp.get_error_system (); + interpreter& interp = m_evaluator.get_interpreter (); + error_system& es = interp.get_error_system (); - // print dbstop if error information - if (es.debug_on_error ()) - { - if (m_errors_that_stop.empty ()) - { - if (to_screen) - octave_stdout << "stop if error\n"; - else - retval.assign ("errs", octave_value ("")); - } - else - { - Cell errs (dim_vector (bp_table::m_errors_that_stop.size (), 1)); - int i = 0; + // print dbstop if error information + if (es.debug_on_error ()) + { + if (m_errors_that_stop.empty ()) + { + if (to_screen) + octave_stdout << "stop if error\n"; + else + retval.assign ("errs", octave_value ("")); + } + else + { + Cell errs (dim_vector (bp_table::m_errors_that_stop.size (), 1)); + int i = 0; - for (const auto& e : m_errors_that_stop) - { - if (to_screen) - octave_stdout << "stop if error " << e << "\n"; - else - errs(i++) = e; - } - if (! to_screen) - retval.assign ("errs", octave_value (errs)); - } - } + for (const auto& e : m_errors_that_stop) + { + if (to_screen) + octave_stdout << "stop if error " << e << "\n"; + else + errs(i++) = e; + } + if (! to_screen) + retval.assign ("errs", octave_value (errs)); + } + } - // print dbstop if caught error information - if (es.debug_on_caught ()) - { - if (m_caught_that_stop.empty ()) - { - if (to_screen) - octave_stdout << "stop if caught error\n"; - else - retval.assign ("caught", octave_value ("")); - } - else - { - Cell errs (dim_vector (m_caught_that_stop.size (), 1)); - int i = 0; + // print dbstop if caught error information + if (es.debug_on_caught ()) + { + if (m_caught_that_stop.empty ()) + { + if (to_screen) + octave_stdout << "stop if caught error\n"; + else + retval.assign ("caught", octave_value ("")); + } + else + { + Cell errs (dim_vector (m_caught_that_stop.size (), 1)); + int i = 0; - for (const auto& e : m_caught_that_stop) - { - if (to_screen) - octave_stdout << "stop if caught error " << e << "\n"; - else - errs(i++) = e; - } - if (! to_screen) - retval.assign ("caught", octave_value (errs)); - } - } + for (const auto& e : m_caught_that_stop) + { + if (to_screen) + octave_stdout << "stop if caught error " << e << "\n"; + else + errs(i++) = e; + } + if (! to_screen) + retval.assign ("caught", octave_value (errs)); + } + } - // print dbstop if warning information - if (es.debug_on_warning ()) - { - if (m_warnings_that_stop.empty ()) - { - if (to_screen) - octave_stdout << "stop if warning\n"; - else - retval.assign ("warn", octave_value ("")); - } - else - { - Cell warn (dim_vector (m_warnings_that_stop.size (), 1)); - int i = 0; + // print dbstop if warning information + if (es.debug_on_warning ()) + { + if (m_warnings_that_stop.empty ()) + { + if (to_screen) + octave_stdout << "stop if warning\n"; + else + retval.assign ("warn", octave_value ("")); + } + else + { + Cell warn (dim_vector (m_warnings_that_stop.size (), 1)); + int i = 0; - for (const auto& w : m_warnings_that_stop) - { - if (to_screen) - octave_stdout << "stop if warning " << w << "\n"; - else - warn(i++) = w; - } - if (! to_screen) - retval.assign ("warn", octave_value (warn)); - } - } + for (const auto& w : m_warnings_that_stop) + { + if (to_screen) + octave_stdout << "stop if warning " << w << "\n"; + else + warn(i++) = w; + } + if (! to_screen) + retval.assign ("warn", octave_value (warn)); + } + } - // print dbstop if interrupt information - if (Vdebug_on_interrupt) - { - if (to_screen) - octave_stdout << "stop if interrupt\n"; - else - retval.assign ("intr", octave_value ("")); - } + // print dbstop if interrupt information + if (Vdebug_on_interrupt) + { + if (to_screen) + octave_stdout << "stop if interrupt\n"; + else + retval.assign ("intr", octave_value ("")); + } - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/bp-table.h diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/comment-list.cc --- a/libinterp/parse-tree/comment-list.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/comment-list.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,15 +34,15 @@ OCTAVE_BEGIN_NAMESPACE(octave) - comment_list * - comment_list::dup (void) const - { - comment_list *new_cl = new comment_list (); +comment_list * +comment_list::dup (void) const +{ + comment_list *new_cl = new comment_list (); - for (const auto& elt : *this) - new_cl->append (elt); + for (const auto& elt : *this) + new_cl->append (elt); - return new_cl; - } + return new_cl; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/comment-list.h --- a/libinterp/parse-tree/comment-list.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/comment-list.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,81 +34,81 @@ OCTAVE_BEGIN_NAMESPACE(octave) - extern std::string get_comment_text (void); - - extern char * get_comment_text_c_str (void); - - extern void save_comment_text (const std::string& text); - - class - comment_elt - { - public: +extern std::string get_comment_text (void); - enum comment_type - { - unknown, - block, - full_line, - end_of_line, - doc_string, - copyright - }; +extern char * get_comment_text_c_str (void); - comment_elt (const std::string& s = "", comment_type t = unknown) - : m_text (s), m_type (t) { } - - comment_elt (const comment_elt& oc) - : m_text (oc.m_text), m_type (oc.m_type) { } +extern void save_comment_text (const std::string& text); - comment_elt& operator = (const comment_elt& oc) - { - if (this != &oc) - { - m_text = oc.m_text; - m_type = oc.m_type; - } - - return *this; - } - - std::string text (void) const { return m_text; } - - comment_type type (void) const { return m_type; } +class +comment_elt +{ +public: - bool is_block (void) const { return m_type == block; } - bool is_full_line (void) const { return m_type == full_line; } - bool is_end_of_line (void) const { return m_type == end_of_line; } - bool is_doc_string (void) const { return m_type == doc_string; } - bool is_copyright (void) const { return m_type == copyright; } - - ~comment_elt (void) = default; - - private: - - // The text of the comment. - std::string m_text; - - // The type of comment. - comment_type m_type; + enum comment_type + { + unknown, + block, + full_line, + end_of_line, + doc_string, + copyright }; - class - comment_list : public base_list + comment_elt (const std::string& s = "", comment_type t = unknown) + : m_text (s), m_type (t) { } + + comment_elt (const comment_elt& oc) + : m_text (oc.m_text), m_type (oc.m_type) { } + + comment_elt& operator = (const comment_elt& oc) { - public: + if (this != &oc) + { + m_text = oc.m_text; + m_type = oc.m_type; + } + + return *this; + } - comment_list (void) { } + std::string text (void) const { return m_text; } + + comment_type type (void) const { return m_type; } + + bool is_block (void) const { return m_type == block; } + bool is_full_line (void) const { return m_type == full_line; } + bool is_end_of_line (void) const { return m_type == end_of_line; } + bool is_doc_string (void) const { return m_type == doc_string; } + bool is_copyright (void) const { return m_type == copyright; } - void append (const comment_elt& elt) - { base_list::append (elt); } + ~comment_elt (void) = default; + +private: + + // The text of the comment. + std::string m_text; + + // The type of comment. + comment_type m_type; +}; - void append (const std::string& s, - comment_elt::comment_type t = comment_elt::unknown) - { append (comment_elt (s, t)); } +class +comment_list : public base_list +{ +public: + + comment_list (void) { } - comment_list * dup (void) const; - }; + void append (const comment_elt& elt) + { base_list::append (elt); } + + void append (const std::string& s, + comment_elt::comment_type t = comment_elt::unknown) + { append (comment_elt (s, t)); } + + comment_list * dup (void) const; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/filepos.h --- a/libinterp/parse-tree/filepos.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/filepos.h Thu Dec 01 20:05:44 2022 -0800 @@ -30,45 +30,45 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class filepos - { - public: +class filepos +{ +public: - filepos (void) : m_line (0), m_column (0) { } + filepos (void) : m_line (0), m_column (0) { } - filepos (int l, int c) : m_line (l), m_column (c) { } + filepos (int l, int c) : m_line (l), m_column (c) { } - filepos (const filepos&) = default; + filepos (const filepos&) = default; - filepos& operator = (const filepos&) = default; + filepos& operator = (const filepos&) = default; - ~filepos (void) = default; + ~filepos (void) = default; - operator bool () { return m_line > 0 && m_column > 0; } + operator bool () { return m_line > 0 && m_column > 0; } - void line (int l) { m_line = l; } - void column (int c) { m_column = c; } + void line (int l) { m_line = l; } + void column (int c) { m_column = c; } - int line (void) const { return m_line; } - int column (void) const { return m_column; } + int line (void) const { return m_line; } + int column (void) const { return m_column; } - void increment_line (int val = 1) { m_line += val; } - void increment_column (int val = 1) { m_column += val; } + void increment_line (int val = 1) { m_line += val; } + void increment_column (int val = 1) { m_column += val; } - void decrement_line (int val = 1) { m_line -= val; } - void decrement_column (int val = 1) { m_column -= val; } + void decrement_line (int val = 1) { m_line -= val; } + void decrement_column (int val = 1) { m_column -= val; } - void next_line (void) - { - m_line++; - m_column = 1; - } + void next_line (void) + { + m_line++; + m_column = 1; + } - private: +private: - int m_line; - int m_column; - }; + int m_line; + int m_column; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/lex.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,837 +41,837 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; +class interpreter; - // Is the given string a keyword? - extern bool iskeyword (const std::string& s); +// Is the given string a keyword? +extern bool iskeyword (const std::string& s); + +// For communication between the lexer and parser. - // For communication between the lexer and parser. +class +lexical_feedback +{ +public: - class - lexical_feedback + // Track symbol table information when parsing functions. + + class symbol_table_context { public: - // Track symbol table information when parsing functions. - - class symbol_table_context - { - public: - - symbol_table_context (interpreter& interp) - : m_interpreter (interp), m_frame_stack () { } - - ~symbol_table_context (void) { clear (); } - - void clear (void); - - bool empty (void) const { return m_frame_stack.empty (); } - - std::size_t size (void) const { return m_frame_stack.size (); } - - void pop (void); - - void push (const symbol_scope& scope) - { - m_frame_stack.push_front (scope); - } - - symbol_scope curr_scope (void) const; - symbol_scope parent_scope (void) const; - - private: - - interpreter& m_interpreter; - - std::deque m_frame_stack; - }; - - // Track nesting of square brackets, curly braces, and parentheses. - - class bbp_nesting_level - { - private: - - enum bracket_type - { - BRACKET = 1, - BRACE = 2, - PAREN = 3, - ANON_FCN_BODY = 4 - }; - - public: - - bbp_nesting_level (void) : m_context () { } - - bbp_nesting_level (const bbp_nesting_level& nl) - : m_context (nl.m_context) - { } - - bbp_nesting_level& operator = (const bbp_nesting_level& nl) - { - if (&nl != this) - m_context = nl.m_context; - - return *this; - } + symbol_table_context (interpreter& interp) + : m_interpreter (interp), m_frame_stack () { } - ~bbp_nesting_level (void) = default; - - // Alias for clear function. - void reset (void) { clear (); } - - void bracket (void) { m_context.push (BRACKET); } - - bool is_bracket (void) - { - return ! m_context.empty () && m_context.top () == BRACKET; - } - - void brace (void) { m_context.push (BRACE); } - - bool is_brace (void) - { - return ! m_context.empty () && m_context.top () == BRACE; - } - - void paren (void) { m_context.push (PAREN); } - - bool is_paren (void) - { - return ! m_context.empty () && m_context.top () == PAREN; - } - - void anon_fcn_body (void) { m_context.push (ANON_FCN_BODY); } + ~symbol_table_context (void) { clear (); } - bool is_anon_fcn_body (void) - { - return ! m_context.empty () && m_context.top () == ANON_FCN_BODY; - } - - bool is_bracket_or_brace (void) - { - return (! m_context.empty () - && (m_context.top () == BRACKET || m_context.top () == BRACE)); - } - - bool none (void) { return m_context.empty (); } - - void remove (void) - { - if (! m_context.empty ()) - m_context.pop (); - } - - void clear (void) - { - while (! m_context.empty ()) - m_context.pop (); - } - - private: - - std::stack m_context; - }; - - class token_cache - { - public: - - // Store an "unlimited" number of tokens. + void clear (void); - // Tokens are allocated with new. Delete them when they are - // removed from the cache. - // - // One of the reasons for using this class instead of std::deque - // directly is that we can ensure that memory is cleaned up - // properly. It's more tedious to do that with deque since the - // deque destructor and clear method don't call delete on the - // elements that it stores. Another reason is that it makes it - // easier to change the implementation later if needed. - - token_cache (void) : m_buffer () { } - - // No copying! - - token_cache (const token_cache&) = delete; - - token_cache& operator = (const token_cache&) = delete; - - ~token_cache (void) { clear (); } - - void push (token *tok) - { - m_buffer.push_front (tok); - } - - void pop (void) - { - if (! empty ()) - { - delete m_buffer.back (); - m_buffer.pop_back (); - } - } + bool empty (void) const { return m_frame_stack.empty (); } - // Direct access. - token * at (std::size_t n) - { - return empty () ? nullptr : m_buffer.at (n); - } - - const token * at (std::size_t n) const - { - return empty () ? nullptr : m_buffer.at (n); - } - - // Most recently pushed. - token * front (void) - { - return empty () ? nullptr : m_buffer.front (); - } - - const token * front (void) const - { - return empty () ? nullptr : m_buffer.front (); - } - - token * back (void) - { - return empty () ? nullptr : m_buffer.back (); - } - - const token * back (void) const - { - return empty () ? nullptr : m_buffer.back (); - } - - // Number of elements currently in the buffer. - std::size_t size (void) const { return m_buffer.size (); } + std::size_t size (void) const { return m_frame_stack.size (); } - bool empty (void) const { return m_buffer.empty (); } - - void clear (void) - { - while (! empty ()) - pop (); - } - - private: - - std::deque m_buffer; - }; + void pop (void); - lexical_feedback (interpreter& interp) - : m_interpreter (interp), - m_end_of_input (false), - m_allow_command_syntax (true), - m_at_beginning_of_statement (true), - m_looking_at_anon_fcn_args (false), - m_looking_at_return_list (false), - m_looking_at_parameter_list (false), - m_looking_at_decl_list (false), - m_looking_at_matrix_or_assign_lhs (false), - m_looking_for_object_index (false), - m_looking_at_indirect_ref (false), - m_arguments_is_keyword (false), - m_classdef_element_names_are_keywords (false), - m_parsing_anon_fcn_body (false), - m_parsing_class_method (false), - m_parsing_classdef (false), - m_parsing_classdef_decl (false), - m_parsing_classdef_superclass (false), - m_maybe_classdef_get_set_method (false), - m_parsing_classdef_get_method (false), - m_parsing_classdef_set_method (false), - m_quote_is_transpose (false), - m_force_script (false), - m_reading_fcn_file (false), - m_reading_script_file (false), - m_reading_classdef_file (false), - m_buffer_function_text (false), - m_bracketflag (0), - m_braceflag (0), - m_looping (0), - m_defining_fcn (0), - m_looking_at_function_handle (0), - m_block_comment_nesting_level (0), - m_command_arg_paren_count (0), - m_token_count (0), - m_filepos (1, 1), - m_tok_beg (), - m_tok_end (), - m_string_text (), - m_current_input_line (), - m_comment_text (), - m_help_text (), - m_function_text (), - m_fcn_file_name (), - m_fcn_file_full_name (), - m_dir_name (), - m_package_name (), - m_looking_at_object_index (), - m_parsed_function_name (), - m_symtab_context (interp), - m_nesting_level (), - m_tokens () + void push (const symbol_scope& scope) { - init (); + m_frame_stack.push_front (scope); } - // No copying! - - lexical_feedback (const lexical_feedback&) = delete; - - lexical_feedback& operator = (const lexical_feedback&) = delete; - - ~lexical_feedback (void); - - void init (void); - - void reset (void); - - int previous_token_value (void) const; + symbol_scope curr_scope (void) const; + symbol_scope parent_scope (void) const; - bool previous_token_value_is (int tok_val) const; - - void mark_previous_token_trailing_space (void); - - bool space_follows_previous_token (void) const; - - bool previous_token_is_binop (void) const; - - bool previous_token_is_keyword (void) const; - - bool previous_token_may_be_command (void) const; - - void mark_as_variable (const std::string& nm); - void mark_as_variables (const std::list& lst); + private: interpreter& m_interpreter; - // true means that we have encountered eof on the input stream. - bool m_end_of_input; - - // true means command syntax is allowed. - bool m_allow_command_syntax; - - // true means we are at the beginning of a statement, where a - // command name is possible. - bool m_at_beginning_of_statement; - - // true means we are parsing an anonymous function argument list. - bool m_looking_at_anon_fcn_args; - - // true means we're parsing the return list for a function. - bool m_looking_at_return_list; - - // true means we're parsing the parameter list for a function. - bool m_looking_at_parameter_list; - - // true means we're parsing a declaration list (global or - // persistent). - bool m_looking_at_decl_list; - - // true means we're parsing a matrix or the left hand side of - // multi-value assignment statement. - bool m_looking_at_matrix_or_assign_lhs; - - // object index not possible until we've seen something. - bool m_looking_for_object_index; - - // true means we're looking at an indirect reference to a - // structure element. - bool m_looking_at_indirect_ref; - - // true means arguments is handled as keyword. - bool m_arguments_is_keyword; - - // true means "properties", "methods", "events", and "enumeration" - // are treated like keywords. - bool m_classdef_element_names_are_keywords; - - // true means we are parsing the body of an anonymous function. - bool m_parsing_anon_fcn_body; - - // true means we are parsing a class method in function or classdef file. - bool m_parsing_class_method; - - // true means we are parsing a classdef file - bool m_parsing_classdef; - - // true means we are parsing the initial classdef declaration - // portion of classdef file, from the "classdef" token through the - // optional list of superclasses. - bool m_parsing_classdef_decl; - - // true means we are parsing the superclass part of a classdef - // declaration. - bool m_parsing_classdef_superclass; - - // true means we are parsing a class method declaration line in a - // classdef file and can accept a property get or set method name. - // for example, "get.propertyname" is recognized as a function name. - bool m_maybe_classdef_get_set_method; - - // TRUE means we are parsing a classdef get.method. - bool m_parsing_classdef_get_method; - - // TRUE means we are parsing a classdef set.method. - bool m_parsing_classdef_set_method; - - // return transpose or start a string? - bool m_quote_is_transpose; - - // TRUE means treat the current file as a script even if the first - // token is "function" or "classdef". - bool m_force_script; - - // TRUE means we're parsing a function file. - bool m_reading_fcn_file; - - // TRUE means we're parsing a script file. - bool m_reading_script_file; - - // TRUE means we're parsing a classdef file. - bool m_reading_classdef_file; - - // TRUE means we should store the text of the function we are - // parsing. - bool m_buffer_function_text; - - // square bracket level count. - int m_bracketflag; - - // curly brace level count. - int m_braceflag; - - // true means we're in the middle of defining a loop. - int m_looping; - - // nonzero means we're in the middle of defining a function. - int m_defining_fcn; - - // nonzero means we are parsing a function handle. - int m_looking_at_function_handle; - - // nestng level for block comments. - int m_block_comment_nesting_level; - - // Parenthesis count for command argument parsing. - int m_command_arg_paren_count; - - // Count of tokens recognized by this lexer since initialized or - // since the last reset. - std::size_t m_token_count; - - // The current position in the file (line and column). - filepos m_filepos; - - // The positions of the beginning and end of the current token after - // calling update_token_positions. Also used apart from - // update_token_positions to handle the beginning and end of - // character strings. - filepos m_tok_beg; - filepos m_tok_end; - - // The current character string text. - std::string m_string_text; - - // The current line of input. - std::string m_current_input_line; - - // The current comment text. - std::string m_comment_text; - - // The current help text. - std::string m_help_text; - - // The text of functions entered on the command line. - std::string m_function_text; - - // Simple name of function file we are reading. - std::string m_fcn_file_name; - - // Full name of file we are reading. - std::string m_fcn_file_full_name; - - // Directory name where this file was found. May be relative. - std::string m_dir_name; - - // Name of +package containing this file, if any. - std::string m_package_name; - - // if the front of the list is true, the closest paren, brace, or - // bracket nesting is an index for an object. - std::list m_looking_at_object_index; - - // if the top of the stack is true, then we've already seen the name - // of the current function. should only matter if - // current_function_level > 0 - std::stack m_parsed_function_name; - - // Track current symbol table scope and context. - symbol_table_context m_symtab_context; - - // is the closest nesting level a square bracket, squiggly brace, - // a paren, or an anonymous function body? - bbp_nesting_level m_nesting_level; - - // Tokens generated by the lexer. - token_cache m_tokens; + std::deque m_frame_stack; }; - // base_lexer inherits from lexical_feedback because we will - // eventually have several different constructors and it is easier to - // initialize if everything is grouped in a parent class rather than - // listing all the members in the base_lexer class. + // Track nesting of square brackets, curly braces, and parentheses. + + class bbp_nesting_level + { + private: + + enum bracket_type + { + BRACKET = 1, + BRACE = 2, + PAREN = 3, + ANON_FCN_BODY = 4 + }; + + public: + + bbp_nesting_level (void) : m_context () { } + + bbp_nesting_level (const bbp_nesting_level& nl) + : m_context (nl.m_context) + { } + + bbp_nesting_level& operator = (const bbp_nesting_level& nl) + { + if (&nl != this) + m_context = nl.m_context; + + return *this; + } + + ~bbp_nesting_level (void) = default; + + // Alias for clear function. + void reset (void) { clear (); } + + void bracket (void) { m_context.push (BRACKET); } + + bool is_bracket (void) + { + return ! m_context.empty () && m_context.top () == BRACKET; + } + + void brace (void) { m_context.push (BRACE); } - class - base_lexer : public lexical_feedback + bool is_brace (void) + { + return ! m_context.empty () && m_context.top () == BRACE; + } + + void paren (void) { m_context.push (PAREN); } + + bool is_paren (void) + { + return ! m_context.empty () && m_context.top () == PAREN; + } + + void anon_fcn_body (void) { m_context.push (ANON_FCN_BODY); } + + bool is_anon_fcn_body (void) + { + return ! m_context.empty () && m_context.top () == ANON_FCN_BODY; + } + + bool is_bracket_or_brace (void) + { + return (! m_context.empty () + && (m_context.top () == BRACKET || m_context.top () == BRACE)); + } + + bool none (void) { return m_context.empty (); } + + void remove (void) + { + if (! m_context.empty ()) + m_context.pop (); + } + + void clear (void) + { + while (! m_context.empty ()) + m_context.pop (); + } + + private: + + std::stack m_context; + }; + + class token_cache { public: - // Handle buffering of input for lexer. - - class input_buffer - { - public: - - input_buffer (void) - : m_buffer (), m_offset (0), m_chars_left (0), m_eof (false) - { } - - void fill (const std::string& input, bool eof_arg); - - // Copy at most max_size characters to buf. - int copy_chunk (char *buf, std::size_t max_size, bool by_lines = false); - - bool empty (void) const { return m_chars_left == 0; } - - bool at_eof (void) const { return m_eof; } - - private: - - std::string m_buffer; - std::size_t m_offset; - std::size_t m_chars_left; - bool m_eof; - }; - - // Collect comment text. - - class - comment_buffer - { - public: - - comment_buffer (void) : m_comment_list (nullptr) { } - - ~comment_buffer (void) { delete m_comment_list; } + // Store an "unlimited" number of tokens. - void append (const std::string& s, comment_elt::comment_type t) - { - if (! m_comment_list) - m_comment_list = new comment_list (); - - m_comment_list->append (s, t); - } - - // Caller is expected to delete the returned value. - - comment_list * get_comment (void) - { - comment_list *retval = m_comment_list; - - m_comment_list = nullptr; - - return retval; - } + // Tokens are allocated with new. Delete them when they are + // removed from the cache. + // + // One of the reasons for using this class instead of std::deque + // directly is that we can ensure that memory is cleaned up + // properly. It's more tedious to do that with deque since the + // deque destructor and clear method don't call delete on the + // elements that it stores. Another reason is that it makes it + // easier to change the implementation later if needed. - void reset (void) - { - delete m_comment_list; - - m_comment_list = nullptr; - } - - private: - - comment_list *m_comment_list; - }; - - base_lexer (interpreter& interp) - : lexical_feedback (interp), m_scanner (nullptr), m_input_buf (), - m_comment_buf () - { - init (); - } + token_cache (void) : m_buffer () { } // No copying! - base_lexer (const base_lexer&) = delete; - - base_lexer& operator = (const base_lexer&) = delete; - - virtual ~base_lexer (void); - - void init (void); + token_cache (const token_cache&) = delete; - virtual bool is_push_lexer (void) const { return false; } - - virtual void reset (void); - - void prep_for_file (void); - - void begin_string (int state); - - virtual int fill_flex_buffer (char *buf, unsigned int max_size) = 0; + token_cache& operator = (const token_cache&) = delete; - bool at_end_of_buffer (void) const { return m_input_buf.empty (); } - - bool at_end_of_file (void) const { return m_input_buf.at_eof (); } - - int handle_end_of_input (void); - - char * flex_yytext (void); + ~token_cache (void) { clear (); } - int flex_yyleng (void); - - int text_yyinput (void); - - void xunput (char c, char *buf); - - void xunput (char c); - - void update_token_positions (int tok_len); + void push (token *tok) + { + m_buffer.push_front (tok); + } - bool looking_at_space (void); - - bool inside_any_object_index (void); - - int make_keyword_token (const std::string& s); - - bool fq_identifier_contains_keyword (const std::string& s); - - bool whitespace_is_significant (void); - - // We only provide specializations with base equal to 2, 10, or 16. - template - int handle_number (void); - - void handle_continuation (void); - - void finish_comment (comment_elt::comment_type typ); + void pop (void) + { + if (! empty ()) + { + delete m_buffer.back (); + m_buffer.pop_back (); + } + } - comment_list * get_comment (void) { return m_comment_buf.get_comment (); } - - int handle_close_bracket (int bracket_type); - - bool looks_like_command_arg (void); - - int handle_superclass_identifier (void); + // Direct access. + token * at (std::size_t n) + { + return empty () ? nullptr : m_buffer.at (n); + } - int handle_meta_identifier (void); - - int handle_fq_identifier (void); - - int handle_identifier (void); - - void maybe_warn_separator_insert (char sep); - - void warn_language_extension (const std::string& msg); + const token * at (std::size_t n) const + { + return empty () ? nullptr : m_buffer.at (n); + } - void maybe_warn_language_extension_comment (char c); - - void warn_language_extension_continuation (void); - - void warn_language_extension_operator (const std::string& op); - - void warn_deprecated_syntax (const std::string& msg); - - void push_token (token *); - - token * current_token (void); - - std::size_t pending_token_count (void) const; - - void display_token (int tok); + // Most recently pushed. + token * front (void) + { + return empty () ? nullptr : m_buffer.front (); + } - void fatal_error (const char *msg); - - bool debug_flag (void) const; - - bool display_tokens (void) const; - - void increment_token_count (void); + const token * front (void) const + { + return empty () ? nullptr : m_buffer.front (); + } - void lexer_debug (const char *pattern); - - // Internal state of the flex-generated lexer. - void *m_scanner; - - // Object that reads and buffers input. - input_buffer m_input_buf; - - // Object that collects comment text. - comment_buffer m_comment_buf; + token * back (void) + { + return empty () ? nullptr : m_buffer.back (); + } - virtual std::string input_source (void) const { return "unknown"; } - - virtual bool input_from_terminal (void) const { return false; } - - virtual bool input_from_file (void) const { return false; } - - virtual bool input_from_eval_string (void) const { return false; } + const token * back (void) const + { + return empty () ? nullptr : m_buffer.back (); + } - bool input_from_tmp_history_file (void); - - void push_start_state (int state); + // Number of elements currently in the buffer. + std::size_t size (void) const { return m_buffer.size (); } - void pop_start_state (void); - - void clear_start_state (void); - - int start_state (void) const { return start_state_stack.top (); } + bool empty (void) const { return m_buffer.empty (); } - void display_start_state (void) const; - - bool maybe_unput_comma_before_unary_op (int tok); - - int handle_op (int tok, bool bos = false, bool compat = true); - - int finish_command_arg (void); - - int handle_token (int tok, token *tok_val = nullptr); + void clear (void) + { + while (! empty ()) + pop (); + } - int count_token (int tok); - - int count_token_internal (int tok); + private: - int show_token (int tok); - - protected: - - std::stack start_state_stack; + std::deque m_buffer; }; - class - lexer : public base_lexer + lexical_feedback (interpreter& interp) + : m_interpreter (interp), + m_end_of_input (false), + m_allow_command_syntax (true), + m_at_beginning_of_statement (true), + m_looking_at_anon_fcn_args (false), + m_looking_at_return_list (false), + m_looking_at_parameter_list (false), + m_looking_at_decl_list (false), + m_looking_at_matrix_or_assign_lhs (false), + m_looking_for_object_index (false), + m_looking_at_indirect_ref (false), + m_arguments_is_keyword (false), + m_classdef_element_names_are_keywords (false), + m_parsing_anon_fcn_body (false), + m_parsing_class_method (false), + m_parsing_classdef (false), + m_parsing_classdef_decl (false), + m_parsing_classdef_superclass (false), + m_maybe_classdef_get_set_method (false), + m_parsing_classdef_get_method (false), + m_parsing_classdef_set_method (false), + m_quote_is_transpose (false), + m_force_script (false), + m_reading_fcn_file (false), + m_reading_script_file (false), + m_reading_classdef_file (false), + m_buffer_function_text (false), + m_bracketflag (0), + m_braceflag (0), + m_looping (0), + m_defining_fcn (0), + m_looking_at_function_handle (0), + m_block_comment_nesting_level (0), + m_command_arg_paren_count (0), + m_token_count (0), + m_filepos (1, 1), + m_tok_beg (), + m_tok_end (), + m_string_text (), + m_current_input_line (), + m_comment_text (), + m_help_text (), + m_function_text (), + m_fcn_file_name (), + m_fcn_file_full_name (), + m_dir_name (), + m_package_name (), + m_looking_at_object_index (), + m_parsed_function_name (), + m_symtab_context (interp), + m_nesting_level (), + m_tokens () + { + init (); + } + + // No copying! + + lexical_feedback (const lexical_feedback&) = delete; + + lexical_feedback& operator = (const lexical_feedback&) = delete; + + ~lexical_feedback (void); + + void init (void); + + void reset (void); + + int previous_token_value (void) const; + + bool previous_token_value_is (int tok_val) const; + + void mark_previous_token_trailing_space (void); + + bool space_follows_previous_token (void) const; + + bool previous_token_is_binop (void) const; + + bool previous_token_is_keyword (void) const; + + bool previous_token_may_be_command (void) const; + + void mark_as_variable (const std::string& nm); + void mark_as_variables (const std::list& lst); + + interpreter& m_interpreter; + + // true means that we have encountered eof on the input stream. + bool m_end_of_input; + + // true means command syntax is allowed. + bool m_allow_command_syntax; + + // true means we are at the beginning of a statement, where a + // command name is possible. + bool m_at_beginning_of_statement; + + // true means we are parsing an anonymous function argument list. + bool m_looking_at_anon_fcn_args; + + // true means we're parsing the return list for a function. + bool m_looking_at_return_list; + + // true means we're parsing the parameter list for a function. + bool m_looking_at_parameter_list; + + // true means we're parsing a declaration list (global or + // persistent). + bool m_looking_at_decl_list; + + // true means we're parsing a matrix or the left hand side of + // multi-value assignment statement. + bool m_looking_at_matrix_or_assign_lhs; + + // object index not possible until we've seen something. + bool m_looking_for_object_index; + + // true means we're looking at an indirect reference to a + // structure element. + bool m_looking_at_indirect_ref; + + // true means arguments is handled as keyword. + bool m_arguments_is_keyword; + + // true means "properties", "methods", "events", and "enumeration" + // are treated like keywords. + bool m_classdef_element_names_are_keywords; + + // true means we are parsing the body of an anonymous function. + bool m_parsing_anon_fcn_body; + + // true means we are parsing a class method in function or classdef file. + bool m_parsing_class_method; + + // true means we are parsing a classdef file + bool m_parsing_classdef; + + // true means we are parsing the initial classdef declaration + // portion of classdef file, from the "classdef" token through the + // optional list of superclasses. + bool m_parsing_classdef_decl; + + // true means we are parsing the superclass part of a classdef + // declaration. + bool m_parsing_classdef_superclass; + + // true means we are parsing a class method declaration line in a + // classdef file and can accept a property get or set method name. + // for example, "get.propertyname" is recognized as a function name. + bool m_maybe_classdef_get_set_method; + + // TRUE means we are parsing a classdef get.method. + bool m_parsing_classdef_get_method; + + // TRUE means we are parsing a classdef set.method. + bool m_parsing_classdef_set_method; + + // return transpose or start a string? + bool m_quote_is_transpose; + + // TRUE means treat the current file as a script even if the first + // token is "function" or "classdef". + bool m_force_script; + + // TRUE means we're parsing a function file. + bool m_reading_fcn_file; + + // TRUE means we're parsing a script file. + bool m_reading_script_file; + + // TRUE means we're parsing a classdef file. + bool m_reading_classdef_file; + + // TRUE means we should store the text of the function we are + // parsing. + bool m_buffer_function_text; + + // square bracket level count. + int m_bracketflag; + + // curly brace level count. + int m_braceflag; + + // true means we're in the middle of defining a loop. + int m_looping; + + // nonzero means we're in the middle of defining a function. + int m_defining_fcn; + + // nonzero means we are parsing a function handle. + int m_looking_at_function_handle; + + // nestng level for block comments. + int m_block_comment_nesting_level; + + // Parenthesis count for command argument parsing. + int m_command_arg_paren_count; + + // Count of tokens recognized by this lexer since initialized or + // since the last reset. + std::size_t m_token_count; + + // The current position in the file (line and column). + filepos m_filepos; + + // The positions of the beginning and end of the current token after + // calling update_token_positions. Also used apart from + // update_token_positions to handle the beginning and end of + // character strings. + filepos m_tok_beg; + filepos m_tok_end; + + // The current character string text. + std::string m_string_text; + + // The current line of input. + std::string m_current_input_line; + + // The current comment text. + std::string m_comment_text; + + // The current help text. + std::string m_help_text; + + // The text of functions entered on the command line. + std::string m_function_text; + + // Simple name of function file we are reading. + std::string m_fcn_file_name; + + // Full name of file we are reading. + std::string m_fcn_file_full_name; + + // Directory name where this file was found. May be relative. + std::string m_dir_name; + + // Name of +package containing this file, if any. + std::string m_package_name; + + // if the front of the list is true, the closest paren, brace, or + // bracket nesting is an index for an object. + std::list m_looking_at_object_index; + + // if the top of the stack is true, then we've already seen the name + // of the current function. should only matter if + // current_function_level > 0 + std::stack m_parsed_function_name; + + // Track current symbol table scope and context. + symbol_table_context m_symtab_context; + + // is the closest nesting level a square bracket, squiggly brace, + // a paren, or an anonymous function body? + bbp_nesting_level m_nesting_level; + + // Tokens generated by the lexer. + token_cache m_tokens; +}; + +// base_lexer inherits from lexical_feedback because we will +// eventually have several different constructors and it is easier to +// initialize if everything is grouped in a parent class rather than +// listing all the members in the base_lexer class. + +class +base_lexer : public lexical_feedback +{ +public: + + // Handle buffering of input for lexer. + + class input_buffer { public: - lexer (interpreter& interp) - : base_lexer (interp), m_reader (interp), m_initial_input (true) - { } - - lexer (FILE *file, interpreter& interp) - : base_lexer (interp), m_reader (interp, file), m_initial_input (true) + input_buffer (void) + : m_buffer (), m_offset (0), m_chars_left (0), m_eof (false) { } - lexer (FILE *file, interpreter& interp, const std::string& encoding) - : base_lexer (interp), m_reader (interp, file, encoding), - m_initial_input (true) - { } + void fill (const std::string& input, bool eof_arg); + + // Copy at most max_size characters to buf. + int copy_chunk (char *buf, std::size_t max_size, bool by_lines = false); + + bool empty (void) const { return m_chars_left == 0; } + + bool at_eof (void) const { return m_eof; } + + private: + + std::string m_buffer; + std::size_t m_offset; + std::size_t m_chars_left; + bool m_eof; + }; + + // Collect comment text. - lexer (const std::string& eval_string, interpreter& interp) - : base_lexer (interp), m_reader (interp, eval_string), - m_initial_input (true) - { } + class + comment_buffer + { + public: + + comment_buffer (void) : m_comment_list (nullptr) { } + + ~comment_buffer (void) { delete m_comment_list; } + + void append (const std::string& s, comment_elt::comment_type t) + { + if (! m_comment_list) + m_comment_list = new comment_list (); - // No copying! + m_comment_list->append (s, t); + } + + // Caller is expected to delete the returned value. - lexer (const lexer&) = delete; + comment_list * get_comment (void) + { + comment_list *retval = m_comment_list; - lexer& operator = (const lexer&) = delete; + m_comment_list = nullptr; + + return retval; + } void reset (void) { - m_initial_input = true; - - base_lexer::reset (); - } + delete m_comment_list; - std::string input_source (void) const - { - return m_reader.input_source (); - } - - bool input_from_terminal (void) const - { - return m_reader.input_from_terminal (); + m_comment_list = nullptr; } - bool input_from_file (void) const - { - return m_reader.input_from_file (); - } - - bool input_from_eval_string (void) const - { - return m_reader.input_from_eval_string (); - } + private: - int fill_flex_buffer (char *buf, unsigned int max_size); - - input_reader m_reader; - - // TRUE means we are filling the input buffer for the first time. - // Otherwise, we are requesting more input to complete the parse - // and, if printing a prompt, should use the secondary prompt - // string. - - bool m_initial_input; + comment_list *m_comment_list; }; - template <> int base_lexer::handle_number<2> (); - template <> int base_lexer::handle_number<10> (); - template <> int base_lexer::handle_number<16> (); + base_lexer (interpreter& interp) + : lexical_feedback (interp), m_scanner (nullptr), m_input_buf (), + m_comment_buf () + { + init (); + } + + // No copying! + + base_lexer (const base_lexer&) = delete; + + base_lexer& operator = (const base_lexer&) = delete; + + virtual ~base_lexer (void); + + void init (void); + + virtual bool is_push_lexer (void) const { return false; } + + virtual void reset (void); + + void prep_for_file (void); + + void begin_string (int state); + + virtual int fill_flex_buffer (char *buf, unsigned int max_size) = 0; + + bool at_end_of_buffer (void) const { return m_input_buf.empty (); } + + bool at_end_of_file (void) const { return m_input_buf.at_eof (); } + + int handle_end_of_input (void); - class - push_lexer : public base_lexer - { - public: + char * flex_yytext (void); + + int flex_yyleng (void); + + int text_yyinput (void); + + void xunput (char c, char *buf); + + void xunput (char c); + + void update_token_positions (int tok_len); + + bool looking_at_space (void); + + bool inside_any_object_index (void); + + int make_keyword_token (const std::string& s); + + bool fq_identifier_contains_keyword (const std::string& s); + + bool whitespace_is_significant (void); + + // We only provide specializations with base equal to 2, 10, or 16. + template + int handle_number (void); + + void handle_continuation (void); + + void finish_comment (comment_elt::comment_type typ); + + comment_list * get_comment (void) { return m_comment_buf.get_comment (); } + + int handle_close_bracket (int bracket_type); - push_lexer (interpreter& interp) - : base_lexer (interp) - { - append_input ("", false); - } + bool looks_like_command_arg (void); + + int handle_superclass_identifier (void); + + int handle_meta_identifier (void); + + int handle_fq_identifier (void); + + int handle_identifier (void); + + void maybe_warn_separator_insert (char sep); + + void warn_language_extension (const std::string& msg); + + void maybe_warn_language_extension_comment (char c); + + void warn_language_extension_continuation (void); + + void warn_language_extension_operator (const std::string& op); + + void warn_deprecated_syntax (const std::string& msg); + + void push_token (token *); + + token * current_token (void); + + std::size_t pending_token_count (void) const; + + void display_token (int tok); + + void fatal_error (const char *msg); - push_lexer (const std::string& input, interpreter& interp) - : base_lexer (interp) - { - append_input (input, false); - } + bool debug_flag (void) const; + + bool display_tokens (void) const; + + void increment_token_count (void); + + void lexer_debug (const char *pattern); + + // Internal state of the flex-generated lexer. + void *m_scanner; + + // Object that reads and buffers input. + input_buffer m_input_buf; + + // Object that collects comment text. + comment_buffer m_comment_buf; + + virtual std::string input_source (void) const { return "unknown"; } + + virtual bool input_from_terminal (void) const { return false; } + + virtual bool input_from_file (void) const { return false; } + + virtual bool input_from_eval_string (void) const { return false; } + + bool input_from_tmp_history_file (void); + + void push_start_state (int state); + + void pop_start_state (void); + + void clear_start_state (void); + + int start_state (void) const { return start_state_stack.top (); } - push_lexer (bool eof, interpreter& interp) - : base_lexer (interp) - { - append_input ("", eof); - } + void display_start_state (void) const; + + bool maybe_unput_comma_before_unary_op (int tok); + + int handle_op (int tok, bool bos = false, bool compat = true); + + int finish_command_arg (void); + + int handle_token (int tok, token *tok_val = nullptr); + + int count_token (int tok); + + int count_token_internal (int tok); + + int show_token (int tok); + +protected: + + std::stack start_state_stack; +}; + +class +lexer : public base_lexer +{ +public: + + lexer (interpreter& interp) + : base_lexer (interp), m_reader (interp), m_initial_input (true) + { } - push_lexer (const std::string& input, bool eof, interpreter& interp) - : base_lexer (interp) - { - append_input (input, eof); - } + lexer (FILE *file, interpreter& interp) + : base_lexer (interp), m_reader (interp, file), m_initial_input (true) + { } + + lexer (FILE *file, interpreter& interp, const std::string& encoding) + : base_lexer (interp), m_reader (interp, file, encoding), + m_initial_input (true) + { } + + lexer (const std::string& eval_string, interpreter& interp) + : base_lexer (interp), m_reader (interp, eval_string), + m_initial_input (true) + { } + + // No copying! + + lexer (const lexer&) = delete; + + lexer& operator = (const lexer&) = delete; + + void reset (void) + { + m_initial_input = true; + + base_lexer::reset (); + } + + std::string input_source (void) const + { + return m_reader.input_source (); + } + + bool input_from_terminal (void) const + { + return m_reader.input_from_terminal (); + } - // No copying! + bool input_from_file (void) const + { + return m_reader.input_from_file (); + } + + bool input_from_eval_string (void) const + { + return m_reader.input_from_eval_string (); + } + + int fill_flex_buffer (char *buf, unsigned int max_size); + + input_reader m_reader; - push_lexer (const push_lexer&) = delete; + // TRUE means we are filling the input buffer for the first time. + // Otherwise, we are requesting more input to complete the parse + // and, if printing a prompt, should use the secondary prompt + // string. + + bool m_initial_input; +}; - push_lexer& operator = (const push_lexer&) = delete; +template <> int base_lexer::handle_number<2> (); +template <> int base_lexer::handle_number<10> (); +template <> int base_lexer::handle_number<16> (); + +class +push_lexer : public base_lexer +{ +public: - bool is_push_lexer (void) const { return true; } + push_lexer (interpreter& interp) + : base_lexer (interp) + { + append_input ("", false); + } - void append_input (const std::string& input, bool eof); + push_lexer (const std::string& input, interpreter& interp) + : base_lexer (interp) + { + append_input (input, false); + } + + push_lexer (bool eof, interpreter& interp) + : base_lexer (interp) + { + append_input ("", eof); + } - std::string input_source (void) const { return "push buffer"; } + push_lexer (const std::string& input, bool eof, interpreter& interp) + : base_lexer (interp) + { + append_input (input, eof); + } + + // No copying! + + push_lexer (const push_lexer&) = delete; - int fill_flex_buffer (char *buf, unsigned int max_size); - }; + push_lexer& operator = (const push_lexer&) = delete; + + bool is_push_lexer (void) const { return true; } + + void append_input (const std::string& input, bool eof); + + std::string input_source (void) const { return "push buffer"; } + + int fill_flex_buffer (char *buf, unsigned int max_size); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/oct-lvalue.cc --- a/libinterp/parse-tree/oct-lvalue.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/oct-lvalue.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,214 +37,214 @@ OCTAVE_BEGIN_NAMESPACE(octave) - bool octave_lvalue::is_defined (void) const - { - return ! is_black_hole () && m_frame->is_defined (m_sym); - } +bool octave_lvalue::is_defined (void) const +{ + return ! is_black_hole () && m_frame->is_defined (m_sym); +} - bool octave_lvalue::is_undefined (void) const - { - return ! is_defined (); - } +bool octave_lvalue::is_undefined (void) const +{ + return ! is_defined (); +} - void octave_lvalue::define (const octave_value& v) - { - m_frame->assign (m_sym, v); - } +void octave_lvalue::define (const octave_value& v) +{ + m_frame->assign (m_sym, v); +} - void octave_lvalue::assign (octave_value::assign_op op, - const octave_value& rhs) - { - if (! is_black_hole ()) - m_frame->assign (op, m_sym, m_type, m_idx, rhs); - } +void octave_lvalue::assign (octave_value::assign_op op, + const octave_value& rhs) +{ + if (! is_black_hole ()) + m_frame->assign (op, m_sym, m_type, m_idx, rhs); +} - octave_idx_type octave_lvalue::numel (void) const - { - // Return 1 if there is no index because without an index there - // should be no way to have a cs-list here. Cs-lists may be passed - // around internally but they are not supposed to be stored as - // single symbols in a stack frame. +octave_idx_type octave_lvalue::numel (void) const +{ + // Return 1 if there is no index because without an index there + // should be no way to have a cs-list here. Cs-lists may be passed + // around internally but they are not supposed to be stored as + // single symbols in a stack frame. - std::size_t num_indices = m_idx.size (); + std::size_t num_indices = m_idx.size (); - if (num_indices == 0) + if (num_indices == 0) + return 1; + + switch (m_type[num_indices-1]) + { + case '(': return 1; - switch (m_type[num_indices-1]) + case '{': { - case '(': - return 1; + // FIXME: Duplicate code in '.' case below... - case '{': - { - // FIXME: Duplicate code in '.' case below... + // Evaluate, skipping the last index. - // Evaluate, skipping the last index. - - std::string tmp_type = m_type; - std::list tmp_idx = m_idx; + std::string tmp_type = m_type; + std::list tmp_idx = m_idx; - tmp_type.pop_back (); - tmp_idx.pop_back (); + tmp_type.pop_back (); + tmp_idx.pop_back (); - octave_value tmp = eval_for_numel (tmp_type, tmp_idx); + octave_value tmp = eval_for_numel (tmp_type, tmp_idx); + + octave_value_list tidx = m_idx.back (); - octave_value_list tidx = m_idx.back (); - - if (tmp.is_undefined ()) - { - if (tidx.has_magic_colon ()) - err_invalid_inquiry_subscript (); + if (tmp.is_undefined ()) + { + if (tidx.has_magic_colon ()) + err_invalid_inquiry_subscript (); - tmp = Cell (); - } - else if (tmp.is_zero_by_zero () - && (tmp.is_matrix_type () || tmp.is_string ())) - { - tmp = Cell (); - } + tmp = Cell (); + } + else if (tmp.is_zero_by_zero () + && (tmp.is_matrix_type () || tmp.is_string ())) + { + tmp = Cell (); + } - return tmp.xnumel (tidx); - } - break; + return tmp.xnumel (tidx); + } + break; + + case '.': + { + // Evaluate, skipping either the last index or the last two + // indices if we are looking at "(idx).field". - case '.': - { - // Evaluate, skipping either the last index or the last two - // indices if we are looking at "(idx).field". + std::string tmp_type = m_type; + std::list tmp_idx = m_idx; - std::string tmp_type = m_type; - std::list tmp_idx = m_idx; + tmp_type.pop_back (); + tmp_idx.pop_back (); + + bool paren_dot = num_indices > 1 && m_type[num_indices-2] == '('; - tmp_type.pop_back (); - tmp_idx.pop_back (); - - bool paren_dot = num_indices > 1 && m_type[num_indices-2] == '('; + // Index for paren operator, if any. + octave_value_list pidx; - // Index for paren operator, if any. - octave_value_list pidx; + if (paren_dot) + { + pidx = tmp_idx.back (); - if (paren_dot) - { - pidx = tmp_idx.back (); + tmp_type.pop_back (); + tmp_idx.pop_back (); + } - tmp_type.pop_back (); - tmp_idx.pop_back (); - } + octave_value tmp = eval_for_numel (tmp_type, tmp_idx); - octave_value tmp = eval_for_numel (tmp_type, tmp_idx); - - bool autoconv = (tmp.is_zero_by_zero () - && (tmp.is_matrix_type () || tmp.is_string () - || tmp.iscell ())); + bool autoconv = (tmp.is_zero_by_zero () + && (tmp.is_matrix_type () || tmp.is_string () + || tmp.iscell ())); - if (paren_dot) - { - // Use octave_map, not octave_scalar_map so that the - // dimensions are 0x0, not 1x1. + if (paren_dot) + { + // Use octave_map, not octave_scalar_map so that the + // dimensions are 0x0, not 1x1. - if (tmp.is_undefined ()) - { - if (pidx.has_magic_colon ()) - err_invalid_inquiry_subscript (); + if (tmp.is_undefined ()) + { + if (pidx.has_magic_colon ()) + err_invalid_inquiry_subscript (); - tmp = octave_map (); - } - else if (autoconv) tmp = octave_map (); + } + else if (autoconv) + tmp = octave_map (); - return tmp.xnumel (pidx); - } - else if (tmp.is_undefined () || autoconv) - return 1; - else - return tmp.xnumel (octave_value_list ()); - } - break; + return tmp.xnumel (pidx); + } + else if (tmp.is_undefined () || autoconv) + return 1; + else + return tmp.xnumel (octave_value_list ()); + } + break; - default: - panic_impossible (); - } - } + default: + panic_impossible (); + } +} - void octave_lvalue::set_index (const std::string& t, - const std::list& i) - { - if (! m_idx.empty ()) - error ("invalid index expression in assignment"); +void octave_lvalue::set_index (const std::string& t, + const std::list& i) +{ + if (! m_idx.empty ()) + error ("invalid index expression in assignment"); - m_type = t; - m_idx = i; - } + m_type = t; + m_idx = i; +} - bool octave_lvalue::index_is_empty (void) const - { - bool retval = false; +bool octave_lvalue::index_is_empty (void) const +{ + bool retval = false; - if (m_idx.size () == 1) - { - octave_value_list tmp = m_idx.front (); + if (m_idx.size () == 1) + { + octave_value_list tmp = m_idx.front (); - retval = (tmp.length () == 1 && tmp(0).isempty ()); - } + retval = (tmp.length () == 1 && tmp(0).isempty ()); + } - return retval; - } + return retval; +} - bool octave_lvalue::index_is_colon (void) const - { - bool retval = false; +bool octave_lvalue::index_is_colon (void) const +{ + bool retval = false; - if (m_idx.size () == 1) - { - octave_value_list tmp = m_idx.front (); + if (m_idx.size () == 1) + { + octave_value_list tmp = m_idx.front (); - retval = (tmp.length () == 1 && tmp(0).is_magic_colon ()); - } + retval = (tmp.length () == 1 && tmp(0).is_magic_colon ()); + } - return retval; - } + return retval; +} - void octave_lvalue::unary_op (octave_value::unary_op op) - { - if (! is_black_hole ()) - m_frame->non_const_unary_op (op, m_sym, m_type, m_idx); - } +void octave_lvalue::unary_op (octave_value::unary_op op) +{ + if (! is_black_hole ()) + m_frame->non_const_unary_op (op, m_sym, m_type, m_idx); +} - octave_value octave_lvalue::value (void) const - { - return (is_black_hole () - ? octave_value () : m_frame->value (m_sym, m_type, m_idx)); - } +octave_value octave_lvalue::value (void) const +{ + return (is_black_hole () + ? octave_value () : m_frame->value (m_sym, m_type, m_idx)); +} - octave_value - octave_lvalue::eval_for_numel (const std::string& type, - const std::list& idx) const - { - octave_value retval; +octave_value +octave_lvalue::eval_for_numel (const std::string& type, + const std::list& idx) const +{ + octave_value retval; - try - { - retval = m_frame->varval (m_sym); + try + { + retval = m_frame->varval (m_sym); - if (retval.is_constant () && ! idx.empty ()) - retval = retval.subsref (type, idx); - } - catch (const execution_exception&) - { - // Ignore an error and treat it as undefined. The error - // could happen because there is an index is out of range - // and we will be resizing a cell array. + if (retval.is_constant () && ! idx.empty ()) + retval = retval.subsref (type, idx); + } + catch (const execution_exception&) + { + // Ignore an error and treat it as undefined. The error + // could happen because there is an index is out of range + // and we will be resizing a cell array. - interpreter& interp = __get_interpreter__ (); + interpreter& interp = __get_interpreter__ (); - interp.recover_from_exception (); + interp.recover_from_exception (); - retval = octave_value (); - } + retval = octave_value (); + } - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/oct-lvalue.h --- a/libinterp/parse-tree/oct-lvalue.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/oct-lvalue.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,69 +36,69 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class octave_lvalue - { - public: +class octave_lvalue +{ +public: - octave_lvalue (const symbol_record& sr, - const std::shared_ptr& frame) - : m_sym (sr), m_frame (frame), m_black_hole (false), - m_type (), m_idx () - { } + octave_lvalue (const symbol_record& sr, + const std::shared_ptr& frame) + : m_sym (sr), m_frame (frame), m_black_hole (false), + m_type (), m_idx () + { } - octave_lvalue (const octave_lvalue&) = default; + octave_lvalue (const octave_lvalue&) = default; - octave_lvalue& operator = (const octave_lvalue&) = delete; + octave_lvalue& operator = (const octave_lvalue&) = delete; - ~octave_lvalue (void) = default; + ~octave_lvalue (void) = default; - bool is_black_hole (void) const { return m_black_hole; } + bool is_black_hole (void) const { return m_black_hole; } - void mark_black_hole (void) { m_black_hole = true; } + void mark_black_hole (void) { m_black_hole = true; } - bool is_defined (void) const; + bool is_defined (void) const; - bool is_undefined (void) const; + bool is_undefined (void) const; - bool isstruct (void) const { return value().isstruct (); } + bool isstruct (void) const { return value().isstruct (); } - void define (const octave_value& v); + void define (const octave_value& v); - void assign (octave_value::assign_op, const octave_value&); + void assign (octave_value::assign_op, const octave_value&); - octave_idx_type numel (void) const; + octave_idx_type numel (void) const; - void set_index (const std::string& t, - const std::list& i); + void set_index (const std::string& t, + const std::list& i); - void clear_index (void) { m_type = ""; m_idx.clear (); } + void clear_index (void) { m_type = ""; m_idx.clear (); } - std::string index_type (void) const { return m_type; } + std::string index_type (void) const { return m_type; } - bool index_is_empty (void) const; + bool index_is_empty (void) const; - bool index_is_colon (void) const; + bool index_is_colon (void) const; - void unary_op (octave_value::unary_op op); + void unary_op (octave_value::unary_op op); - octave_value value (void) const; + octave_value value (void) const; - private: +private: - octave_value - eval_for_numel (const std::string& type, - const std::list& idx) const; + octave_value + eval_for_numel (const std::string& type, + const std::list& idx) const; - symbol_record m_sym; + symbol_record m_sym; - std::shared_ptr m_frame; + std::shared_ptr m_frame; - bool m_black_hole; + bool m_black_hole; - std::string m_type; + std::string m_type; - std::list m_idx; - }; + std::list m_idx; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/parse.h --- a/libinterp/parse-tree/parse.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/parse.h Thu Dec 01 20:05:44 2022 -0800 @@ -48,54 +48,54 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class comment_list; - class parse_exception; - class tree; - class tree_anon_fcn_handle; - class tree_arg_size_spec; - class tree_arg_validation; - class tree_arg_validation_fcns; - class tree_args_block_attribute_list; - class tree_args_block_validation_list; - class tree_argument_list; - class tree_arguments_block; - class tree_array_list; - class tree_cell; - class tree_classdef; - class tree_classdef_attribute_list; - class tree_classdef_body; - class tree_classdef_enum_block; - class tree_classdef_enum_list; - class tree_classdef_events_block; - class tree_classdef_events_list; - class tree_classdef_methods_block; - class tree_classdef_methods_list; - class tree_classdef_properties_block; - class tree_classdef_property_list; - class tree_classdef_superclass_list; - class tree_colon_expression; - class tree_command; - class tree_constant; - class tree_decl_command; - class tree_decl_init_list; - class tree_expression; - class tree_fcn_handle; - class tree_function_def; - class tree_identifier; - class tree_if_clause; - class tree_if_command; - class tree_if_command_list; - class tree_index_expression; - 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; - class tree_switch_case; - class tree_switch_case_list; - class tree_switch_command; +class comment_list; +class parse_exception; +class tree; +class tree_anon_fcn_handle; +class tree_arg_size_spec; +class tree_arg_validation; +class tree_arg_validation_fcns; +class tree_args_block_attribute_list; +class tree_args_block_validation_list; +class tree_argument_list; +class tree_arguments_block; +class tree_array_list; +class tree_cell; +class tree_classdef; +class tree_classdef_attribute_list; +class tree_classdef_body; +class tree_classdef_enum_block; +class tree_classdef_enum_list; +class tree_classdef_events_block; +class tree_classdef_events_list; +class tree_classdef_methods_block; +class tree_classdef_methods_list; +class tree_classdef_properties_block; +class tree_classdef_property_list; +class tree_classdef_superclass_list; +class tree_colon_expression; +class tree_command; +class tree_constant; +class tree_decl_command; +class tree_decl_init_list; +class tree_expression; +class tree_fcn_handle; +class tree_function_def; +class tree_identifier; +class tree_if_clause; +class tree_if_command; +class tree_if_command_list; +class tree_index_expression; +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; +class tree_switch_case; +class tree_switch_case_list; +class tree_switch_command; OCTAVE_END_NAMESPACE(octave) @@ -106,852 +106,852 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class base_parser - { - private: - - class parent_scope_info - { - public: - - typedef std::pair value_type; - - typedef std::deque::iterator iterator; - typedef std::deque::const_iterator const_iterator; - - typedef std::deque::reverse_iterator reverse_iterator; - typedef std::deque::const_reverse_iterator const_reverse_iterator; - - parent_scope_info (void) = delete; - - parent_scope_info (base_parser& parser) - : m_parser (parser), m_info (), m_all_names () - { } - - // No copying! - - parent_scope_info (const parent_scope_info&) = delete; - - parent_scope_info& operator = (const parent_scope_info&) = delete; +class base_parser +{ +private: - ~parent_scope_info (void) = default; - - OCTINTERP_API std::size_t size (void) const; - - OCTINTERP_API void push (const value_type& elt); - - OCTINTERP_API void push (const symbol_scope& id); - - OCTINTERP_API void pop (void); - - OCTINTERP_API bool name_ok (const std::string& name); - - OCTINTERP_API bool name_current_scope (const std::string& name); - - OCTINTERP_API symbol_scope parent_scope (void) const; - - OCTINTERP_API std::string parent_name (void) const; - - OCTINTERP_API void clear (void); - - private: - - base_parser& m_parser; - std::deque m_info; - std::set m_all_names; - }; - + class parent_scope_info + { public: - OCTINTERP_API base_parser (base_lexer& lxr); + typedef std::pair value_type; + + typedef std::deque::iterator iterator; + typedef std::deque::const_iterator const_iterator; + + typedef std::deque::reverse_iterator reverse_iterator; + typedef std::deque::const_reverse_iterator const_reverse_iterator; + + parent_scope_info (void) = delete; + + parent_scope_info (base_parser& parser) + : m_parser (parser), m_info (), m_all_names () + { } // No copying! - base_parser (const base_parser&) = delete; + parent_scope_info (const parent_scope_info&) = delete; - base_parser& operator = (const base_parser&) = delete; + parent_scope_info& operator = (const parent_scope_info&) = delete; - virtual ~base_parser (void); + ~parent_scope_info (void) = default; - base_lexer& get_lexer (void) const { return m_lexer; } + OCTINTERP_API std::size_t size (void) const; + + OCTINTERP_API void push (const value_type& elt); - bool at_end_of_input (void) const { return m_lexer.m_end_of_input; } + OCTINTERP_API void push (const symbol_scope& id); - OCTINTERP_API void reset (void); + OCTINTERP_API void pop (void); - void classdef_object (const std::shared_ptr& obj) - { - m_classdef_object = obj; - } + OCTINTERP_API bool name_ok (const std::string& name); + + OCTINTERP_API bool name_current_scope (const std::string& name); + + OCTINTERP_API symbol_scope parent_scope (void) const; - std::shared_ptr classdef_object (void) const - { - return m_classdef_object; - } + OCTINTERP_API std::string parent_name (void) const; + + OCTINTERP_API void clear (void); - OCTINTERP_API void statement_list (std::shared_ptr& lst); + private: + + base_parser& m_parser; + std::deque m_info; + std::set m_all_names; + }; - std::shared_ptr statement_list (void) const - { - return m_stmt_list; - } +public: + + OCTINTERP_API base_parser (base_lexer& lxr); + + // No copying! - void parsing_subfunctions (bool flag) - { - m_parsing_subfunctions = flag; - } + base_parser (const base_parser&) = delete; + + base_parser& operator = (const base_parser&) = delete; + + virtual ~base_parser (void); - bool parsing_subfunctions (void) const - { - return m_parsing_subfunctions; - } + base_lexer& get_lexer (void) const { return m_lexer; } - void parsing_local_functions (bool flag) - { - m_parsing_local_functions = flag; - } + bool at_end_of_input (void) const { return m_lexer.m_end_of_input; } + + OCTINTERP_API void reset (void); - bool parsing_local_functions (void) const - { - return m_parsing_local_functions; - } + void classdef_object (const std::shared_ptr& obj) + { + m_classdef_object = obj; + } - int curr_fcn_depth (void) const - { - return m_curr_fcn_depth; - } + std::shared_ptr classdef_object (void) const + { + return m_classdef_object; + } + + OCTINTERP_API void statement_list (std::shared_ptr& lst); - void endfunction_found (bool flag) - { - m_endfunction_found = flag; - } + std::shared_ptr statement_list (void) const + { + return m_stmt_list; + } - bool endfunction_found (void) const - { - return m_endfunction_found; - } + void parsing_subfunctions (bool flag) + { + m_parsing_subfunctions = flag; + } - // Error messages for mismatched end tokens. - OCTINTERP_API void - end_token_error (token *tok, token::end_tok_type expected); + bool parsing_subfunctions (void) const + { + return m_parsing_subfunctions; + } - // Check to see that end tokens are properly matched. - OCTINTERP_API bool end_token_ok (token *tok, token::end_tok_type expected); + void parsing_local_functions (bool flag) + { + m_parsing_local_functions = flag; + } - // Handle pushing symbol table for new function scope. - OCTINTERP_API bool push_fcn_symtab (void); + bool parsing_local_functions (void) const + { + return m_parsing_local_functions; + } - // Build a constant. - OCTINTERP_API tree_constant * make_constant (token *tok_val); - - OCTINTERP_API tree_black_hole * make_black_hole (void); - - OCTINTERP_API tree_matrix * make_matrix (tree_argument_list *row); + int curr_fcn_depth (void) const + { + return m_curr_fcn_depth; + } - OCTINTERP_API tree_matrix * - append_matrix_row (tree_matrix *matrix, tree_argument_list *row); - - OCTINTERP_API tree_cell * make_cell (tree_argument_list *row); + void endfunction_found (bool flag) + { + m_endfunction_found = flag; + } - OCTINTERP_API tree_cell * - append_cell_row (tree_cell *cell, tree_argument_list *row); + bool endfunction_found (void) const + { + return m_endfunction_found; + } - // Build a function handle. - OCTINTERP_API tree_fcn_handle * make_fcn_handle (token *tok_val); + // Error messages for mismatched end tokens. + OCTINTERP_API void + end_token_error (token *tok, token::end_tok_type expected); - // Build an anonymous function handle. - OCTINTERP_API tree_anon_fcn_handle * - make_anon_fcn_handle (tree_parameter_list *param_list, - tree_expression *expr, const filepos& at_pos); + // Check to see that end tokens are properly matched. + OCTINTERP_API bool end_token_ok (token *tok, token::end_tok_type expected); + + // Handle pushing symbol table for new function scope. + OCTINTERP_API bool push_fcn_symtab (void); + + // Build a constant. + OCTINTERP_API tree_constant * make_constant (token *tok_val); + + OCTINTERP_API tree_black_hole * make_black_hole (void); - // Build a colon expression. - OCTINTERP_API tree_expression * - make_colon_expression (tree_expression *base, tree_expression *limit, - tree_expression *incr = nullptr); + OCTINTERP_API tree_matrix * make_matrix (tree_argument_list *row); + + OCTINTERP_API tree_matrix * + append_matrix_row (tree_matrix *matrix, tree_argument_list *row); - // Build a binary expression. - OCTINTERP_API tree_expression * - make_binary_op (int op, tree_expression *op1, token *tok_val, - tree_expression *op2); + OCTINTERP_API tree_cell * make_cell (tree_argument_list *row); - // Maybe convert EXPR to a braindead_shortcircuit expression. - OCTINTERP_API void - maybe_convert_to_braindead_shortcircuit (tree_expression*& expr); + OCTINTERP_API tree_cell * + append_cell_row (tree_cell *cell, tree_argument_list *row); + + // Build a function handle. + OCTINTERP_API tree_fcn_handle * make_fcn_handle (token *tok_val); - // Build a boolean expression. - OCTINTERP_API tree_expression * - make_boolean_op (int op, tree_expression *op1, token *tok_val, - tree_expression *op2); + // Build an anonymous function handle. + OCTINTERP_API tree_anon_fcn_handle * + make_anon_fcn_handle (tree_parameter_list *param_list, + tree_expression *expr, const filepos& at_pos); - // Build a prefix expression. - OCTINTERP_API tree_expression * - make_prefix_op (int op, tree_expression *op1, token *tok_val); + // Build a colon expression. + OCTINTERP_API tree_expression * + make_colon_expression (tree_expression *base, tree_expression *limit, + tree_expression *incr = nullptr); - // Build a postfix expression. - OCTINTERP_API tree_expression * - make_postfix_op (int op, tree_expression *op1, token *tok_val); + // Build a binary expression. + OCTINTERP_API tree_expression * + make_binary_op (int op, tree_expression *op1, token *tok_val, + tree_expression *op2); - // Build an unwind-protect command. - OCTINTERP_API tree_command * - make_unwind_command (token *unwind_tok, tree_statement_list *body, - tree_statement_list *cleanup, token *end_tok, - comment_list *lc, comment_list *mc); + // Maybe convert EXPR to a braindead_shortcircuit expression. + OCTINTERP_API void + maybe_convert_to_braindead_shortcircuit (tree_expression *&expr); + + // Build a boolean expression. + OCTINTERP_API tree_expression * + make_boolean_op (int op, tree_expression *op1, token *tok_val, + tree_expression *op2); - // Build a try-catch command. - OCTINTERP_API tree_command * - make_try_command (token *try_tok, tree_statement_list *body, - char catch_sep, tree_statement_list *cleanup, - token *end_tok, comment_list *lc, - comment_list *mc); + // Build a prefix expression. + OCTINTERP_API tree_expression * + make_prefix_op (int op, tree_expression *op1, token *tok_val); + + // Build a postfix expression. + OCTINTERP_API tree_expression * + make_postfix_op (int op, tree_expression *op1, token *tok_val); - // Build a while command. - OCTINTERP_API tree_command * - make_while_command (token *while_tok, tree_expression *expr, - tree_statement_list *body, token *end_tok, - comment_list *lc); + // Build an unwind-protect command. + OCTINTERP_API tree_command * + make_unwind_command (token *unwind_tok, tree_statement_list *body, + tree_statement_list *cleanup, token *end_tok, + comment_list *lc, comment_list *mc); - // Build a do-until command. - OCTINTERP_API tree_command * - make_do_until_command (token *until_tok, tree_statement_list *body, - tree_expression *expr, comment_list *lc); + // Build a try-catch command. + OCTINTERP_API tree_command * + make_try_command (token *try_tok, tree_statement_list *body, + char catch_sep, tree_statement_list *cleanup, + token *end_tok, comment_list *lc, + comment_list *mc); - // Build a for command. - OCTINTERP_API tree_command * - make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs, - tree_expression *expr, tree_expression *maxproc, + // Build a while command. + OCTINTERP_API tree_command * + make_while_command (token *while_tok, tree_expression *expr, tree_statement_list *body, token *end_tok, comment_list *lc); - // Build a break command. - OCTINTERP_API tree_command * make_break_command (token *break_tok); - - // Build a continue command. - OCTINTERP_API tree_command * make_continue_command (token *continue_tok); - - // Build a return command. - OCTINTERP_API tree_command * make_return_command (token *return_tok); - - // Build an spmd command. + // Build a do-until command. + OCTINTERP_API tree_command * + make_do_until_command (token *until_tok, tree_statement_list *body, + tree_expression *expr, comment_list *lc); - OCTINTERP_API tree_spmd_command * - make_spmd_command (token *spmd_tok, tree_statement_list *body, - token *end_tok, comment_list *lc, comment_list *tc); + // Build a for command. + OCTINTERP_API tree_command * + make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs, + tree_expression *expr, tree_expression *maxproc, + tree_statement_list *body, token *end_tok, + comment_list *lc); - // Start an if command. - OCTINTERP_API tree_if_command_list * - start_if_command (tree_expression *expr, tree_statement_list *list); + // Build a break command. + OCTINTERP_API tree_command * make_break_command (token *break_tok); - // Finish an if command. - OCTINTERP_API tree_if_command * - finish_if_command (token *if_tok, tree_if_command_list *list, - token *end_tok, comment_list *lc); + // Build a continue command. + OCTINTERP_API tree_command * make_continue_command (token *continue_tok); - // Build an elseif clause. - OCTINTERP_API tree_if_clause * - make_elseif_clause (token *elseif_tok, tree_expression *expr, - tree_statement_list *list, comment_list *lc); + // Build a return command. + OCTINTERP_API tree_command * make_return_command (token *return_tok); - OCTINTERP_API tree_if_clause * - make_else_clause (token *else_tok, comment_list *lc, - tree_statement_list *list); + // Build an spmd command. - OCTINTERP_API tree_if_command_list * - append_if_clause (tree_if_command_list *list, tree_if_clause *clause); + OCTINTERP_API tree_spmd_command * + make_spmd_command (token *spmd_tok, tree_statement_list *body, + token *end_tok, comment_list *lc, comment_list *tc); - // Finish a switch command. - OCTINTERP_API tree_switch_command * - finish_switch_command (token *switch_tok, tree_expression *expr, - tree_switch_case_list *list, token *end_tok, - comment_list *lc); + // Start an if command. + OCTINTERP_API tree_if_command_list * + start_if_command (tree_expression *expr, tree_statement_list *list); - OCTINTERP_API tree_switch_case_list * - make_switch_case_list (tree_switch_case *switch_case); + // Finish an if command. + OCTINTERP_API tree_if_command * + finish_if_command (token *if_tok, tree_if_command_list *list, + token *end_tok, comment_list *lc); - // Build a switch case. - OCTINTERP_API tree_switch_case * - make_switch_case (token *case_tok, tree_expression *expr, + // Build an elseif clause. + OCTINTERP_API tree_if_clause * + make_elseif_clause (token *elseif_tok, tree_expression *expr, tree_statement_list *list, comment_list *lc); - OCTINTERP_API tree_switch_case * - make_default_switch_case (token *default_tok, comment_list *lc, - tree_statement_list *list); + OCTINTERP_API tree_if_clause * + make_else_clause (token *else_tok, comment_list *lc, + tree_statement_list *list); - OCTINTERP_API tree_switch_case_list * - append_switch_case (tree_switch_case_list *list, tree_switch_case *elt); + OCTINTERP_API tree_if_command_list * + append_if_clause (tree_if_command_list *list, tree_if_clause *clause); - // Build an assignment to a variable. - OCTINTERP_API tree_expression * - make_assign_op (int op, tree_argument_list *lhs, token *eq_tok, - tree_expression *rhs); + // Finish a switch command. + OCTINTERP_API tree_switch_command * + finish_switch_command (token *switch_tok, tree_expression *expr, + tree_switch_case_list *list, token *end_tok, + comment_list *lc); - // Define a script. - OCTINTERP_API void - make_script (tree_statement_list *cmds, tree_statement *end_script); + OCTINTERP_API tree_switch_case_list * + make_switch_case_list (tree_switch_case *switch_case); - // Handle identifier that is recognized as a function name. - OCTINTERP_API tree_identifier * - make_fcn_name (tree_identifier *id); + // Build a switch case. + OCTINTERP_API tree_switch_case * + make_switch_case (token *case_tok, tree_expression *expr, + tree_statement_list *list, comment_list *lc); - // Define a function. - OCTINTERP_API tree_function_def * - make_function (token *fcn_tok, tree_parameter_list *ret_list, - tree_identifier *id, tree_parameter_list *param_list, - tree_statement_list *body, tree_statement *end_fcn_stmt, - comment_list *lc); + OCTINTERP_API tree_switch_case * + make_default_switch_case (token *default_tok, comment_list *lc, + tree_statement_list *list); - // Begin defining a function. - OCTINTERP_API octave_user_function * - start_function (tree_identifier *id, tree_parameter_list *param_list, - tree_statement_list *body, tree_statement *end_function); + OCTINTERP_API tree_switch_case_list * + append_switch_case (tree_switch_case_list *list, tree_switch_case *elt); + + // Build an assignment to a variable. + OCTINTERP_API tree_expression * + make_assign_op (int op, tree_argument_list *lhs, token *eq_tok, + tree_expression *rhs); - // Create a no-op statement for end_function. - OCTINTERP_API tree_statement * - make_end (const std::string& type, bool eof, - const filepos& beg_pos, const filepos& end_pos); + // Define a script. + OCTINTERP_API void + make_script (tree_statement_list *cmds, tree_statement *end_script); - // Do most of the work for defining a function. - OCTINTERP_API octave_user_function * - frob_function (tree_identifier *id, octave_user_function *fcn); + // Handle identifier that is recognized as a function name. + OCTINTERP_API tree_identifier * + make_fcn_name (tree_identifier *id); - // Finish defining a function. - OCTINTERP_API tree_function_def * - finish_function (tree_parameter_list *ret_list, - octave_user_function *fcn, comment_list *lc, - int l, int c); + // Define a function. + OCTINTERP_API tree_function_def * + make_function (token *fcn_tok, tree_parameter_list *ret_list, + tree_identifier *id, tree_parameter_list *param_list, + tree_statement_list *body, tree_statement *end_fcn_stmt, + comment_list *lc); - OCTINTERP_API tree_statement_list * - append_function_body (tree_statement_list *body, tree_statement_list *list); + // Begin defining a function. + OCTINTERP_API octave_user_function * + start_function (tree_identifier *id, tree_parameter_list *param_list, + tree_statement_list *body, tree_statement *end_function); - // Make an arguments validation block. - OCTINTERP_API tree_arguments_block * - make_arguments_block (token *arguments_tok, - tree_args_block_attribute_list *attr_list, - tree_args_block_validation_list *validation_list, - token *end_tok, comment_list *lc, comment_list *tc); + // Create a no-op statement for end_function. + OCTINTERP_API tree_statement * + make_end (const std::string& type, bool eof, + const filepos& beg_pos, const filepos& end_pos); - OCTINTERP_API tree_args_block_attribute_list * - make_args_attribute_list (tree_identifier *attribute_name); + // Do most of the work for defining a function. + OCTINTERP_API octave_user_function * + frob_function (tree_identifier *id, octave_user_function *fcn); - // Make an argument validation. - OCTINTERP_API tree_arg_validation * - make_arg_validation (tree_arg_size_spec *size_spec, - tree_identifier *class_name, - tree_arg_validation_fcns *validation_fcns, - tree_expression *default_value); + // Finish defining a function. + OCTINTERP_API tree_function_def * + finish_function (tree_parameter_list *ret_list, + octave_user_function *fcn, comment_list *lc, + int l, int c); + + OCTINTERP_API tree_statement_list * + append_function_body (tree_statement_list *body, tree_statement_list *list); - // Make an argument validation list. - OCTINTERP_API tree_args_block_validation_list * - make_args_validation_list (tree_arg_validation *arg_validation); + // Make an arguments validation block. + OCTINTERP_API tree_arguments_block * + make_arguments_block (token *arguments_tok, + tree_args_block_attribute_list *attr_list, + tree_args_block_validation_list *validation_list, + token *end_tok, comment_list *lc, comment_list *tc); - // Append an argument validation to an existing list. - OCTINTERP_API tree_args_block_validation_list * - append_args_validation_list (tree_args_block_validation_list *list, - tree_arg_validation *arg_validation); + OCTINTERP_API tree_args_block_attribute_list * + make_args_attribute_list (tree_identifier *attribute_name); - // Make an argument size specification object. - OCTINTERP_API tree_arg_size_spec * - make_arg_size_spec (tree_argument_list *size_args); - - // Make a list of argument validation functions. - OCTINTERP_API tree_arg_validation_fcns * - make_arg_validation_fcns (tree_argument_list *fcn_args); + // Make an argument validation. + OCTINTERP_API tree_arg_validation * + make_arg_validation (tree_arg_size_spec *size_spec, + tree_identifier *class_name, + tree_arg_validation_fcns *validation_fcns, + tree_expression *default_value); - // Reset state after parsing function. - OCTINTERP_API void - recover_from_parsing_function (void); - - OCTINTERP_API tree_classdef * - make_classdef (token *tok_val, tree_classdef_attribute_list *a, - tree_identifier *id, tree_classdef_superclass_list *sc, - tree_classdef_body *body, token *end_tok, - comment_list *lc, comment_list *tc); + // Make an argument validation list. + OCTINTERP_API tree_args_block_validation_list * + make_args_validation_list (tree_arg_validation *arg_validation); - OCTINTERP_API tree_classdef_properties_block * - make_classdef_properties_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_property_list *plist, - token *end_tok, comment_list *lc, - comment_list *tc); + // Append an argument validation to an existing list. + OCTINTERP_API tree_args_block_validation_list * + append_args_validation_list (tree_args_block_validation_list *list, + tree_arg_validation *arg_validation); - OCTINTERP_API tree_classdef_property_list * - make_classdef_property_list (tree_classdef_property *prop); + // Make an argument size specification object. + OCTINTERP_API tree_arg_size_spec * + make_arg_size_spec (tree_argument_list *size_args); + + // Make a list of argument validation functions. + OCTINTERP_API tree_arg_validation_fcns * + make_arg_validation_fcns (tree_argument_list *fcn_args); - OCTINTERP_API tree_classdef_property * - make_classdef_property (comment_list *lc, tree_identifier *id, - tree_arg_validation *av); + // Reset state after parsing function. + OCTINTERP_API void + recover_from_parsing_function (void); + + OCTINTERP_API tree_classdef * + make_classdef (token *tok_val, tree_classdef_attribute_list *a, + tree_identifier *id, tree_classdef_superclass_list *sc, + tree_classdef_body *body, token *end_tok, + comment_list *lc, comment_list *tc); - OCTINTERP_API tree_classdef_property_list * - append_classdef_property (tree_classdef_property_list *list, - tree_classdef_property *elt); + OCTINTERP_API tree_classdef_properties_block * + make_classdef_properties_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + token *end_tok, comment_list *lc, + comment_list *tc); - OCTINTERP_API tree_classdef_methods_block * - make_classdef_methods_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_methods_list *mlist, - token *end_tok, comment_list *lc, - comment_list *tc); + OCTINTERP_API tree_classdef_property_list * + make_classdef_property_list (tree_classdef_property *prop); - OCTINTERP_API tree_classdef_events_block * - make_classdef_events_block (token *tok_val, - tree_classdef_attribute_list *a, - tree_classdef_events_list *elist, - token *end_tok, comment_list *lc, - comment_list *tc); + OCTINTERP_API tree_classdef_property * + make_classdef_property (comment_list *lc, tree_identifier *id, + tree_arg_validation *av); - OCTINTERP_API tree_classdef_events_list * - make_classdef_events_list (tree_classdef_event *e); + OCTINTERP_API tree_classdef_property_list * + append_classdef_property (tree_classdef_property_list *list, + tree_classdef_property *elt); - OCTINTERP_API tree_classdef_event * - make_classdef_event (comment_list *lc, tree_identifier *id); + OCTINTERP_API tree_classdef_methods_block * + make_classdef_methods_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + token *end_tok, comment_list *lc, + comment_list *tc); - OCTINTERP_API tree_classdef_events_list * - append_classdef_event (tree_classdef_events_list *list, - tree_classdef_event *elt); - - OCTINTERP_API tree_classdef_enum_block * - make_classdef_enum_block (token *tok_val, + OCTINTERP_API tree_classdef_events_block * + make_classdef_events_block (token *tok_val, tree_classdef_attribute_list *a, - tree_classdef_enum_list *elist, + tree_classdef_events_list *elist, token *end_tok, comment_list *lc, comment_list *tc); - OCTINTERP_API tree_classdef_enum_list * - make_classdef_enum_list (tree_classdef_enum *e); - - OCTINTERP_API tree_classdef_enum * - make_classdef_enum (tree_identifier *id, tree_expression *expr, - comment_list *lc); + OCTINTERP_API tree_classdef_events_list * + make_classdef_events_list (tree_classdef_event *e); - OCTINTERP_API tree_classdef_enum_list * - append_classdef_enum (tree_classdef_enum_list *list, - tree_classdef_enum *elt); + OCTINTERP_API tree_classdef_event * + make_classdef_event (comment_list *lc, tree_identifier *id); - OCTINTERP_API tree_classdef_superclass_list * - make_classdef_superclass_list (tree_classdef_superclass *sc); - - OCTINTERP_API tree_classdef_superclass * - make_classdef_superclass (token *fqident); + OCTINTERP_API tree_classdef_events_list * + append_classdef_event (tree_classdef_events_list *list, + tree_classdef_event *elt); - OCTINTERP_API tree_classdef_superclass_list * - append_classdef_superclass (tree_classdef_superclass_list *list, - tree_classdef_superclass *elt); - - OCTINTERP_API tree_classdef_attribute_list * - make_classdef_attribute_list (tree_classdef_attribute *attr); + OCTINTERP_API tree_classdef_enum_block * + make_classdef_enum_block (token *tok_val, + tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + token *end_tok, comment_list *lc, + comment_list *tc); - OCTINTERP_API tree_classdef_attribute * - make_classdef_attribute (tree_identifier *id, - tree_expression *expr = nullptr); + OCTINTERP_API tree_classdef_enum_list * + make_classdef_enum_list (tree_classdef_enum *e); - OCTINTERP_API tree_classdef_attribute * - make_not_classdef_attribute (tree_identifier *id); - - OCTINTERP_API tree_classdef_attribute_list * - append_classdef_attribute (tree_classdef_attribute_list *list, - tree_classdef_attribute *elt); + OCTINTERP_API tree_classdef_enum * + make_classdef_enum (tree_identifier *id, tree_expression *expr, + comment_list *lc); - OCTINTERP_API tree_classdef_body * - make_classdef_body (tree_classdef_properties_block *pb); + OCTINTERP_API tree_classdef_enum_list * + append_classdef_enum (tree_classdef_enum_list *list, + tree_classdef_enum *elt); - OCTINTERP_API tree_classdef_body * - make_classdef_body (tree_classdef_methods_block *mb); - - OCTINTERP_API tree_classdef_body * - make_classdef_body (tree_classdef_events_block *evb); + OCTINTERP_API tree_classdef_superclass_list * + make_classdef_superclass_list (tree_classdef_superclass *sc); - OCTINTERP_API tree_classdef_body * - make_classdef_body (tree_classdef_enum_block *enb); + OCTINTERP_API tree_classdef_superclass * + make_classdef_superclass (token *fqident); - OCTINTERP_API tree_classdef_body * - append_classdef_properties_block (tree_classdef_body *body, - tree_classdef_properties_block *block); - - OCTINTERP_API tree_classdef_body * - append_classdef_methods_block (tree_classdef_body *body, - tree_classdef_methods_block *block); + OCTINTERP_API tree_classdef_superclass_list * + append_classdef_superclass (tree_classdef_superclass_list *list, + tree_classdef_superclass *elt); - OCTINTERP_API tree_classdef_body * - append_classdef_events_block (tree_classdef_body *body, - tree_classdef_events_block *block); + OCTINTERP_API tree_classdef_attribute_list * + make_classdef_attribute_list (tree_classdef_attribute *attr); - OCTINTERP_API tree_classdef_body * - append_classdef_enum_block (tree_classdef_body *body, - tree_classdef_enum_block *block); + OCTINTERP_API tree_classdef_attribute * + make_classdef_attribute (tree_identifier *id, + tree_expression *expr = nullptr); - OCTINTERP_API octave_user_function * - start_classdef_external_method (tree_identifier *id, - tree_parameter_list *pl); + OCTINTERP_API tree_classdef_attribute * + make_not_classdef_attribute (tree_identifier *id); - OCTINTERP_API tree_function_def * - finish_classdef_external_method (octave_user_function *fcn, - tree_parameter_list *ret_list, - comment_list *cl); - - OCTINTERP_API tree_classdef_methods_list * - make_classdef_methods_list (tree_function_def *fcn_def); + OCTINTERP_API tree_classdef_attribute_list * + append_classdef_attribute (tree_classdef_attribute_list *list, + tree_classdef_attribute *elt); - OCTINTERP_API tree_classdef_methods_list * - append_classdef_method (tree_classdef_methods_list *list, - tree_function_def *fcn_def); + OCTINTERP_API tree_classdef_body * + make_classdef_body (tree_classdef_properties_block *pb); - OCTINTERP_API bool - finish_classdef_file (tree_classdef *cls, - tree_statement_list *local_fcns); + OCTINTERP_API tree_classdef_body * + make_classdef_body (tree_classdef_methods_block *mb); - // Make an index expression. - OCTINTERP_API tree_index_expression * - make_index_expression (tree_expression *expr, - tree_argument_list *args, char type); + OCTINTERP_API tree_classdef_body * + make_classdef_body (tree_classdef_events_block *evb); - // Make an indirect reference expression. - OCTINTERP_API tree_index_expression * - make_indirect_ref (tree_expression *expr, const std::string&); + OCTINTERP_API tree_classdef_body * + make_classdef_body (tree_classdef_enum_block *enb); - // Make an indirect reference expression with dynamic field name. - OCTINTERP_API tree_index_expression * - make_indirect_ref (tree_expression *expr, tree_expression *field); - - // Make a declaration command. - OCTINTERP_API tree_decl_command * - make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst); + OCTINTERP_API tree_classdef_body * + append_classdef_properties_block (tree_classdef_body *body, + tree_classdef_properties_block *block); - OCTINTERP_API tree_decl_init_list * - make_decl_init_list (tree_decl_elt *elt); + OCTINTERP_API tree_classdef_body * + append_classdef_methods_block (tree_classdef_body *body, + tree_classdef_methods_block *block); - OCTINTERP_API tree_decl_elt * - make_decl_elt (tree_identifier *id, token *eq_op = nullptr, - tree_expression *expr = nullptr); - - OCTINTERP_API tree_decl_init_list * - append_decl_init_list (tree_decl_init_list *list, tree_decl_elt *elt); + OCTINTERP_API tree_classdef_body * + append_classdef_events_block (tree_classdef_body *body, + tree_classdef_events_block *block); - // Validate an function parameter list. - OCTINTERP_API bool - validate_param_list (tree_parameter_list *lst, - tree_parameter_list::in_or_out type); - // Validate matrix or cell - OCTINTERP_API bool validate_array_list (tree_expression *e); + OCTINTERP_API tree_classdef_body * + append_classdef_enum_block (tree_classdef_body *body, + tree_classdef_enum_block *block); - // Validate matrix object used in "[lhs] = ..." assignments. - OCTINTERP_API tree_argument_list * - validate_matrix_for_assignment (tree_expression *e); + OCTINTERP_API octave_user_function * + start_classdef_external_method (tree_identifier *id, + tree_parameter_list *pl); - // Finish building an array_list (common action for finish_matrix - // and finish_cell). - OCTINTERP_API tree_expression * - finish_array_list (tree_array_list *a, token *open_delim, - token *close_delim); - - // Finish building a matrix list. - OCTINTERP_API tree_expression * - finish_matrix (tree_matrix *m, token *open_delim, token *close_delim); + OCTINTERP_API tree_function_def * + finish_classdef_external_method (octave_user_function *fcn, + tree_parameter_list *ret_list, + comment_list *cl); - // Finish building a cell list. - OCTINTERP_API tree_expression * - finish_cell (tree_cell *c, token *open_delim, token *close_delim); + OCTINTERP_API tree_classdef_methods_list * + make_classdef_methods_list (tree_function_def *fcn_def); - OCTINTERP_API tree_identifier * - make_identifier (token *ident); - - OCTINTERP_API tree_superclass_ref * - make_superclass_ref (token *superclassref); + OCTINTERP_API tree_classdef_methods_list * + append_classdef_method (tree_classdef_methods_list *list, + tree_function_def *fcn_def); - OCTINTERP_API tree_metaclass_query * - make_metaclass_query (token *metaquery); + OCTINTERP_API bool + finish_classdef_file (tree_classdef *cls, + tree_statement_list *local_fcns); - // Set the print flag for a statement based on the separator type. - OCTINTERP_API tree_statement_list * - set_stmt_print_flag (tree_statement_list *, char, bool); - - // Finish building a statement. - template - OCTINTERP_API tree_statement * make_statement (T *arg); + // Make an index expression. + OCTINTERP_API tree_index_expression * + make_index_expression (tree_expression *expr, + tree_argument_list *args, char type); - // Create a statement list. - OCTINTERP_API tree_statement_list * - make_statement_list (tree_statement *stmt); - - // Append a statement to an existing statement list. - OCTINTERP_API tree_statement_list * - append_statement_list (tree_statement_list *list, char sep, - tree_statement *stmt, bool warn_missing_semi); + // Make an indirect reference expression. + OCTINTERP_API tree_index_expression * + make_indirect_ref (tree_expression *expr, const std::string&); - OCTINTERP_API tree_argument_list * - make_argument_list (tree_expression *expr); - - OCTINTERP_API tree_argument_list * - append_argument_list (tree_argument_list *list, tree_expression *expr); - - OCTINTERP_API tree_parameter_list * - make_parameter_list (tree_parameter_list::in_or_out io); + // Make an indirect reference expression with dynamic field name. + OCTINTERP_API tree_index_expression * + make_indirect_ref (tree_expression *expr, tree_expression *field); - OCTINTERP_API tree_parameter_list * - make_parameter_list (tree_parameter_list::in_or_out io, tree_decl_elt *t); + // Make a declaration command. + OCTINTERP_API tree_decl_command * + make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst); - OCTINTERP_API tree_parameter_list * - make_parameter_list (tree_parameter_list::in_or_out io, - tree_identifier *id); + OCTINTERP_API tree_decl_init_list * + make_decl_init_list (tree_decl_elt *elt); - OCTINTERP_API tree_parameter_list * - append_parameter_list (tree_parameter_list *list, tree_decl_elt *t); + OCTINTERP_API tree_decl_elt * + make_decl_elt (tree_identifier *id, token *eq_op = nullptr, + tree_expression *expr = nullptr); - OCTINTERP_API tree_parameter_list * - append_parameter_list (tree_parameter_list *list, tree_identifier *id); - - // Don't allow parsing command syntax. If the parser/lexer is - // reset, this setting is also reset to the default (allow command - // syntax). - OCTINTERP_API void disallow_command_syntax (void); + OCTINTERP_API tree_decl_init_list * + append_decl_init_list (tree_decl_init_list *list, tree_decl_elt *elt); - // Generic error messages. - OCTINTERP_API void bison_error (const std::string& s); - OCTINTERP_API void bison_error (const std::string& s, const filepos& pos); - OCTINTERP_API void bison_error (const std::string& s, int line, int column); - OCTINTERP_API void bison_error (const std::list& pe); - OCTINTERP_API void bison_error (const parse_exception& pe); + // Validate an function parameter list. + OCTINTERP_API bool + validate_param_list (tree_parameter_list *lst, + tree_parameter_list::in_or_out type); + // Validate matrix or cell + OCTINTERP_API bool validate_array_list (tree_expression *e); - friend OCTINTERP_API octave_value - parse_fcn_file (interpreter& interp, const std::string& full_file, - const std::string& file, const std::string& dir_name, - const std::string& dispatch_type, - const std::string& package_name, bool require_file, - bool force_script, bool autoload, bool relative_lookup); + // Validate matrix object used in "[lhs] = ..." assignments. + OCTINTERP_API tree_argument_list * + validate_matrix_for_assignment (tree_expression *e); - // Thih interface allows push or pull parsers to be used - // equivalently, provided that the push parser also owns its input - // method (see below). Alternatively, the push parser interface may - // use a separate run method and completely separate input from - // lexical analysis and parsing. + // Finish building an array_list (common action for finish_matrix + // and finish_cell). + OCTINTERP_API tree_expression * + finish_array_list (tree_array_list *a, token *open_delim, + token *close_delim); - virtual int run (void) = 0; - - // Check primary script or function generated by the parser for - // semantic errors. - OCTINTERP_API bool validate_primary_fcn (void); + // Finish building a matrix list. + OCTINTERP_API tree_expression * + finish_matrix (tree_matrix *m, token *open_delim, token *close_delim); - OCTINTERP_API bool finish_input (tree_statement_list *lst, - bool at_eof = false); - - protected: + // Finish building a cell list. + OCTINTERP_API tree_expression * + finish_cell (tree_cell *c, token *open_delim, token *close_delim); - // Contains error message if Bison-generated parser returns non-zero - // status. - std::string m_parse_error_msg; + OCTINTERP_API tree_identifier * + make_identifier (token *ident); - // Have we found an explicit end to a function? - bool m_endfunction_found; + OCTINTERP_API tree_superclass_ref * + make_superclass_ref (token *superclassref); - // TRUE means we are in the process of autoloading a function. - bool m_autoloading; - - // TRUE means the current function file was found in a relative path - // element. - bool m_fcn_file_from_relative_lookup; + OCTINTERP_API tree_metaclass_query * + make_metaclass_query (token *metaquery); - // FALSE if we are still at the primary function. Subfunctions can - // only be declared inside function files. - bool m_parsing_subfunctions; + // Set the print flag for a statement based on the separator type. + OCTINTERP_API tree_statement_list * + set_stmt_print_flag (tree_statement_list *, char, bool); - // TRUE if we are parsing local functions defined at after a - // classdef block. Local functions can only be declared inside - // classdef files. - bool m_parsing_local_functions; + // Finish building a statement. + template + OCTINTERP_API tree_statement * make_statement (T *arg); - // Maximum function depth detected. Used to determine whether - // we have nested functions or just implicitly ended subfunctions. - int m_max_fcn_depth; - - // = 0 currently outside any function. - // = 1 inside the primary function or a subfunction. - // > 1 means we are looking at a function definition that seems to be - // inside a function. Note that the function still might not be a - // nested function. - int m_curr_fcn_depth; + // Create a statement list. + OCTINTERP_API tree_statement_list * + make_statement_list (tree_statement *stmt); - // Scope where we install all subfunctions and nested functions. Only - // used while reading function files. - symbol_scope m_primary_fcn_scope; + // Append a statement to an existing statement list. + OCTINTERP_API tree_statement_list * + append_statement_list (tree_statement_list *list, char sep, + tree_statement *stmt, bool warn_missing_semi); - // Name of the current class when we are parsing class methods or - // constructors. - std::string m_curr_class_name; + OCTINTERP_API tree_argument_list * + make_argument_list (tree_expression *expr); - // Name of the current package when we are parsing an element contained - // in a package directory (+-directory). - std::string m_curr_package_name; + OCTINTERP_API tree_argument_list * + append_argument_list (tree_argument_list *list, tree_expression *expr); - // Nested function scopes and names currently being parsed. - parent_scope_info m_function_scopes; + OCTINTERP_API tree_parameter_list * + make_parameter_list (tree_parameter_list::in_or_out io); - // Pointer to the primary user function or user script function. - octave_value m_primary_fcn; + OCTINTERP_API tree_parameter_list * + make_parameter_list (tree_parameter_list::in_or_out io, tree_decl_elt *t); - // List of subfunction names, initially in the order they are - // installed in the symbol table, then ordered as they appear in the - // file. Eventually stashed in the primary function object. - std::list m_subfunction_names; + OCTINTERP_API tree_parameter_list * + make_parameter_list (tree_parameter_list::in_or_out io, + tree_identifier *id); - // Pointer to the classdef object we just parsed, if any. - std::shared_ptr m_classdef_object; - - // Result of parsing input. - std::shared_ptr m_stmt_list; - - // State of the lexer. - base_lexer& m_lexer; + OCTINTERP_API tree_parameter_list * + append_parameter_list (tree_parameter_list *list, tree_decl_elt *t); - // Internal state of the Bison parser. - void *m_parser_state; + OCTINTERP_API tree_parameter_list * + append_parameter_list (tree_parameter_list *list, tree_identifier *id); - private: - - // Maybe print a warning if an assignment expression is used as the - // test in a logical expression. - OCTINTERP_API void maybe_warn_assign_as_truth_value (tree_expression *expr); + // Don't allow parsing command syntax. If the parser/lexer is + // reset, this setting is also reset to the default (allow command + // syntax). + OCTINTERP_API void disallow_command_syntax (void); - // Maybe print a warning about switch labels that aren't constants. - OCTINTERP_API void maybe_warn_variable_switch_label (tree_expression *expr); + // Generic error messages. + OCTINTERP_API void bison_error (const std::string& s); + OCTINTERP_API void bison_error (const std::string& s, const filepos& pos); + OCTINTERP_API void bison_error (const std::string& s, int line, int column); + OCTINTERP_API void bison_error (const std::list& pe); + OCTINTERP_API void bison_error (const parse_exception& pe); - // Maybe print a warning. - OCTINTERP_API void maybe_warn_missing_semi (tree_statement_list *); - }; - - // Publish externally used friend functions. - - extern OCTINTERP_API octave_value + friend OCTINTERP_API octave_value parse_fcn_file (interpreter& interp, const std::string& full_file, const std::string& file, const std::string& dir_name, const std::string& dispatch_type, const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup); - class parser : public base_parser - { - public: + // Thih interface allows push or pull parsers to be used + // equivalently, provided that the push parser also owns its input + // method (see below). Alternatively, the push parser interface may + // use a separate run method and completely separate input from + // lexical analysis and parsing. - parser (interpreter& interp) - : base_parser (*(new lexer (interp))) - { } + virtual int run (void) = 0; + + // Check primary script or function generated by the parser for + // semantic errors. + OCTINTERP_API bool validate_primary_fcn (void); - parser (FILE *file, interpreter& interp) - : base_parser (*(new lexer (file, interp))) - { } + OCTINTERP_API bool finish_input (tree_statement_list *lst, + bool at_eof = false); + +protected: - parser (FILE *file, interpreter& interp, std::string encoding) - : base_parser (*(new lexer (file, interp, encoding))) - { } + // Contains error message if Bison-generated parser returns non-zero + // status. + std::string m_parse_error_msg; + + // Have we found an explicit end to a function? + bool m_endfunction_found; + + // TRUE means we are in the process of autoloading a function. + bool m_autoloading; - parser (const std::string& eval_string, interpreter& interp) - : base_parser (*(new lexer (eval_string, interp))) - { } + // TRUE means the current function file was found in a relative path + // element. + bool m_fcn_file_from_relative_lookup; - // The lexer must be allocated with new. The parser object - // takes ownership of and deletes the lexer object in its - // destructor. + // FALSE if we are still at the primary function. Subfunctions can + // only be declared inside function files. + bool m_parsing_subfunctions; + + // TRUE if we are parsing local functions defined at after a + // classdef block. Local functions can only be declared inside + // classdef files. + bool m_parsing_local_functions; - parser (lexer *lxr) - : base_parser (*lxr) - { } + // Maximum function depth detected. Used to determine whether + // we have nested functions or just implicitly ended subfunctions. + int m_max_fcn_depth; - // No copying! + // = 0 currently outside any function. + // = 1 inside the primary function or a subfunction. + // > 1 means we are looking at a function definition that seems to be + // inside a function. Note that the function still might not be a + // nested function. + int m_curr_fcn_depth; - parser (const parser&) = delete; + // Scope where we install all subfunctions and nested functions. Only + // used while reading function files. + symbol_scope m_primary_fcn_scope; - parser& operator = (const parser&) = delete; + // Name of the current class when we are parsing class methods or + // constructors. + std::string m_curr_class_name; - ~parser (void) = default; + // Name of the current package when we are parsing an element contained + // in a package directory (+-directory). + std::string m_curr_package_name; - OCTINTERP_API int run (void); - }; + // Nested function scopes and names currently being parsed. + parent_scope_info m_function_scopes; + + // Pointer to the primary user function or user script function. + octave_value m_primary_fcn; - class push_parser : public base_parser - { - public: + // List of subfunction names, initially in the order they are + // installed in the symbol table, then ordered as they appear in the + // file. Eventually stashed in the primary function object. + std::list m_subfunction_names; - push_parser (interpreter& interp) - : base_parser (*(new push_lexer (interp))), - m_interpreter (interp), m_reader () - { } + // Pointer to the classdef object we just parsed, if any. + std::shared_ptr m_classdef_object; + + // Result of parsing input. + std::shared_ptr m_stmt_list; + + // State of the lexer. + base_lexer& m_lexer; - // The parser assumes ownership of READER, which must be created - // with new. + // Internal state of the Bison parser. + void *m_parser_state; + +private: - push_parser (interpreter& interp, input_reader *reader) - : base_parser (*(new push_lexer (interp))), - m_interpreter (interp), m_reader (reader) - { } + // Maybe print a warning if an assignment expression is used as the + // test in a logical expression. + OCTINTERP_API void maybe_warn_assign_as_truth_value (tree_expression *expr); + + // Maybe print a warning about switch labels that aren't constants. + OCTINTERP_API void maybe_warn_variable_switch_label (tree_expression *expr); + + // Maybe print a warning. + OCTINTERP_API void maybe_warn_missing_semi (tree_statement_list *); +}; - // No copying! - - push_parser (const push_parser&) = delete; +// Publish externally used friend functions. - push_parser& operator = (const push_parser&) = delete; +extern OCTINTERP_API octave_value +parse_fcn_file (interpreter& interp, const std::string& full_file, + const std::string& file, const std::string& dir_name, + const std::string& dispatch_type, + const std::string& package_name, bool require_file, + bool force_script, bool autoload, bool relative_lookup); - ~push_parser (void) = default; +class parser : public base_parser +{ +public: + + parser (interpreter& interp) + : base_parser (*(new lexer (interp))) + { } - // Use the push parser in the same way as the pull parser. The - // parser arranges for input through the M_READER object. See, for - // example, interpreter::main_loop. + parser (FILE *file, interpreter& interp) + : base_parser (*(new lexer (file, interp))) + { } + + parser (FILE *file, interpreter& interp, std::string encoding) + : base_parser (*(new lexer (file, interp, encoding))) + { } + + parser (const std::string& eval_string, interpreter& interp) + : base_parser (*(new lexer (eval_string, interp))) + { } - OCTINTERP_API int run (void); + // The lexer must be allocated with new. The parser object + // takes ownership of and deletes the lexer object in its + // destructor. + + parser (lexer *lxr) + : base_parser (*lxr) + { } - // Parse INPUT. M_READER is not used. The user is responsible for - // collecting input. + // No copying! + + parser (const parser&) = delete; - OCTINTERP_API int run (const std::string& input, bool eof); + parser& operator = (const parser&) = delete; + + ~parser (void) = default; - private: + OCTINTERP_API int run (void); +}; + +class push_parser : public base_parser +{ +public: - interpreter& m_interpreter; + push_parser (interpreter& interp) + : base_parser (*(new push_lexer (interp))), + m_interpreter (interp), m_reader () + { } - std::shared_ptr m_reader; - }; + // The parser assumes ownership of READER, which must be created + // with new. - extern OCTINTERP_API std::string - get_help_from_file (const std::string& nm, bool& symbol_found, - std::string& file); + push_parser (interpreter& interp, input_reader *reader) + : base_parser (*(new push_lexer (interp))), + m_interpreter (interp), m_reader (reader) + { } + + // No copying! - extern OCTINTERP_API std::string - get_help_from_file (const std::string& nm, bool& symbol_found); + push_parser (const push_parser&) = delete; + + push_parser& operator = (const push_parser&) = delete; + + ~push_parser (void) = default; + + // Use the push parser in the same way as the pull parser. The + // parser arranges for input through the M_READER object. See, for + // example, interpreter::main_loop. - extern OCTINTERP_API octave_value - load_fcn_from_file (const std::string& file_name, - const std::string& dir_name = "", - const std::string& dispatch_type = "", - const std::string& package_name = "", - const std::string& fcn_name = "", - bool autoload = false); + OCTINTERP_API int run (void); + + // Parse INPUT. M_READER is not used. The user is responsible for + // collecting input. + + OCTINTERP_API int run (const std::string& input, bool eof); + +private: + + interpreter& m_interpreter; + + std::shared_ptr m_reader; +}; - extern OCTINTERP_API void - source_file (const std::string& file_name, - const std::string& context = "", - bool verbose = false, bool require_file = true); +extern OCTINTERP_API std::string +get_help_from_file (const std::string& nm, bool& symbol_found, + std::string& file); + +extern OCTINTERP_API std::string +get_help_from_file (const std::string& nm, bool& symbol_found); - extern OCTINTERP_API octave_value_list - feval (const char *name, - const octave_value_list& args = octave_value_list (), - int nargout = 0); +extern OCTINTERP_API octave_value +load_fcn_from_file (const std::string& file_name, + const std::string& dir_name = "", + const std::string& dispatch_type = "", + const std::string& package_name = "", + const std::string& fcn_name = "", + bool autoload = false); - extern OCTINTERP_API octave_value_list - feval (const std::string& name, - const octave_value_list& args = octave_value_list (), - int nargout = 0); +extern OCTINTERP_API void +source_file (const std::string& file_name, + const std::string& context = "", + bool verbose = false, bool require_file = true); - extern OCTINTERP_API octave_value_list - feval (octave_function *fcn, - const octave_value_list& args = octave_value_list (), - int nargout = 0); +extern OCTINTERP_API octave_value_list +feval (const char *name, + const octave_value_list& args = octave_value_list (), + int nargout = 0); + +extern OCTINTERP_API octave_value_list +feval (const std::string& name, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - extern OCTINTERP_API octave_value_list - feval (const octave_value& val, - const octave_value_list& args = octave_value_list (), - int nargout = 0); +extern OCTINTERP_API octave_value_list +feval (octave_function *fcn, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - extern OCTINTERP_API octave_value_list - feval (const octave_value_list& args, int nargout = 0); +extern OCTINTERP_API octave_value_list +feval (const octave_value& val, + const octave_value_list& args = octave_value_list (), + int nargout = 0); - extern OCTINTERP_API void - cleanup_statement_list (tree_statement_list **lst); +extern OCTINTERP_API octave_value_list +feval (const octave_value_list& args, int nargout = 0); + +extern OCTINTERP_API void +cleanup_statement_list (tree_statement_list **lst); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/profiler.cc --- a/libinterp/parse-tree/profiler.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/profiler.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,350 +37,350 @@ OCTAVE_BEGIN_NAMESPACE(octave) - profiler::stats::stats (void) - : m_time (0.0), m_calls (0), m_recursive (false), - m_parents (), m_children () - { } +profiler::stats::stats (void) + : m_time (0.0), m_calls (0), m_recursive (false), + m_parents (), m_children () +{ } + +octave_value +profiler::stats::function_set_value (const function_set& list) +{ + const octave_idx_type n = list.size (); + + RowVector retval (n); + octave_idx_type i = 0; + for (const auto& nm : list) + retval(i++) = nm; - octave_value - profiler::stats::function_set_value (const function_set& list) - { - const octave_idx_type n = list.size (); + return retval; +} + +profiler::tree_node::tree_node (tree_node *p, octave_idx_type f) + : m_parent (p), m_fcn_id (f), m_children (), m_time (0.0), m_calls (0) +{ } - RowVector retval (n); - octave_idx_type i = 0; - for (const auto& nm : list) - retval(i++) = nm; +profiler::tree_node::~tree_node () +{ + for (auto& idx_tnode : m_children) + delete idx_tnode.second; +} + +profiler::tree_node * +profiler::tree_node::enter (octave_idx_type fcn) +{ + tree_node *retval; - return retval; - } + child_map::iterator pos = m_children.find (fcn); + if (pos == m_children.end ()) + { + retval = new tree_node (this, fcn); + m_children[fcn] = retval; + } + else + retval = pos->second; - profiler::tree_node::tree_node (tree_node *p, octave_idx_type f) - : m_parent (p), m_fcn_id (f), m_children (), m_time (0.0), m_calls (0) - { } + ++retval->m_calls; + return retval; +} - profiler::tree_node::~tree_node () - { - for (auto& idx_tnode : m_children) - delete idx_tnode.second; - } +profiler::tree_node * +profiler::tree_node::exit (octave_idx_type /* fcn */) +{ + // FIXME: These panic_unless statements don't make sense if profile() is + // called from within a function hierarchy to begin with. See bug #39587. + // panic_unless (m_parent); + // panic_unless (m_fcn_id == fcn); - profiler::tree_node* - profiler::tree_node::enter (octave_idx_type fcn) - { - tree_node *retval; + return m_parent; +} + +void +profiler::tree_node::build_flat (flat_profile& data) const +{ + // If this is not the top-level node, + // update profile entry for this function. + if (m_fcn_id != 0) + { + stats& entry = data[m_fcn_id - 1]; - child_map::iterator pos = m_children.find (fcn); - if (pos == m_children.end ()) - { - retval = new tree_node (this, fcn); - m_children[fcn] = retval; - } - else - retval = pos->second; + entry.m_time += m_time; + entry.m_calls += m_calls; + + panic_unless (m_parent); + if (m_parent->m_fcn_id != 0) + { + entry.m_parents.insert (m_parent->m_fcn_id); + data[m_parent->m_fcn_id - 1].m_children.insert (m_fcn_id); + } - ++retval->m_calls; - return retval; - } + if (! entry.m_recursive) + for (const tree_node *i = m_parent; i; i = i->m_parent) + if (i->m_fcn_id == m_fcn_id) + { + entry.m_recursive = true; + break; + } + } - profiler::tree_node* - profiler::tree_node::exit (octave_idx_type /* fcn */) - { - // FIXME: These panic_unless statements don't make sense if profile() is - // called from within a function hierarchy to begin with. See bug #39587. - // panic_unless (m_parent); - // panic_unless (m_fcn_id == fcn); + // Recurse on children. + for (const auto& idx_tnode : m_children) + idx_tnode.second->build_flat (data); +} + +octave_value +profiler::tree_node::get_hierarchical (double *total) const +{ + // Note that we don't generate the entry just for this node, but + // rather a struct-array with entries for all children. This way, the + // top-node (for which we don't want a real entry) generates already + // the final hierarchical profile data. + + const octave_idx_type n = m_children.size (); - return m_parent; - } + Cell rv_indices (n, 1); + Cell rv_times (n, 1); + Cell rv_totals (n, 1); + Cell rv_calls (n, 1); + Cell rv_children (n, 1); + + octave_idx_type i = 0; + for (const auto& idx_tnode : m_children) + { + const tree_node& entry = *idx_tnode.second; + double child_total = entry.m_time; - void - profiler::tree_node::build_flat (flat_profile& data) const - { - // If this is not the top-level node, - // update profile entry for this function. - if (m_fcn_id != 0) - { - stats& entry = data[m_fcn_id - 1]; + rv_indices(i) = octave_value (idx_tnode.first); + rv_times(i) = octave_value (entry.m_time); + rv_calls(i) = octave_value (entry.m_calls); + rv_children(i) = entry.get_hierarchical (&child_total); + rv_totals(i) = octave_value (child_total); + + if (total) + *total += child_total; - entry.m_time += m_time; - entry.m_calls += m_calls; + ++i; + } + + octave_map retval; - panic_unless (m_parent); - if (m_parent->m_fcn_id != 0) - { - entry.m_parents.insert (m_parent->m_fcn_id); - data[m_parent->m_fcn_id - 1].m_children.insert (m_fcn_id); - } + retval.assign ("Index", rv_indices); + retval.assign ("SelfTime", rv_times); + retval.assign ("TotalTime", rv_totals); + retval.assign ("NumCalls", rv_calls); + retval.assign ("Children", rv_children); + + return retval; +} - if (! entry.m_recursive) - for (const tree_node *i = m_parent; i; i = i->m_parent) - if (i->m_fcn_id == m_fcn_id) - { - entry.m_recursive = true; - break; - } - } +profiler::profiler (void) + : m_known_functions (), m_fcn_index (), + m_enabled (false), m_call_tree (new tree_node (nullptr, 0)), + m_active_fcn (nullptr), m_last_time (-1.0) +{ } + +profiler::~profiler (void) +{ + delete m_call_tree; +} - // Recurse on children. - for (const auto& idx_tnode : m_children) - idx_tnode.second->build_flat (data); - } +void +profiler::set_active (bool value) +{ + m_enabled = value; +} - octave_value - profiler::tree_node::get_hierarchical (double *total) const - { - // Note that we don't generate the entry just for this node, but - // rather a struct-array with entries for all children. This way, the - // top-node (for which we don't want a real entry) generates already - // the final hierarchical profile data. +void +profiler::enter_function (const std::string& fcn) +{ + // The enter class will check and only call us if the profiler is active. + panic_unless (enabled ()); + panic_unless (m_call_tree); + + // If there is already an active function, add to its time before + // pushing the new one. + if (m_active_fcn && m_active_fcn != m_call_tree) + add_current_time (); - const octave_idx_type n = m_children.size (); + // Map the function's name to its index. + octave_idx_type fcn_idx; + fcn_index_map::iterator pos = m_fcn_index.find (fcn); + if (pos == m_fcn_index.end ()) + { + m_known_functions.push_back (fcn); + fcn_idx = m_known_functions.size (); + m_fcn_index[fcn] = fcn_idx; + } + else + fcn_idx = pos->second; - Cell rv_indices (n, 1); - Cell rv_times (n, 1); - Cell rv_totals (n, 1); - Cell rv_calls (n, 1); - Cell rv_children (n, 1); + if (! m_active_fcn) + m_active_fcn = m_call_tree; + + m_active_fcn = m_active_fcn->enter (fcn_idx); + + m_last_time = query_time (); - octave_idx_type i = 0; - for (const auto& idx_tnode : m_children) - { - const tree_node& entry = *idx_tnode.second; - double child_total = entry.m_time; +} - rv_indices(i) = octave_value (idx_tnode.first); - rv_times(i) = octave_value (entry.m_time); - rv_calls(i) = octave_value (entry.m_calls); - rv_children(i) = entry.get_hierarchical (&child_total); - rv_totals(i) = octave_value (child_total); +void +profiler::exit_function (const std::string& fcn) +{ + if (m_active_fcn) + { + panic_unless (m_call_tree); + // FIXME: This panic_unless statements doesn't make sense if profile() + // is called from within a function hierarchy to begin with. + // See bug #39587. + // panic_unless (m_active_fcn != m_call_tree); - if (total) - *total += child_total; + // Usually, if we are disabled this function is not even called. But + // the call disabling the profiler is an exception. So also check here + // and only record the time if enabled. + if (enabled ()) + add_current_time (); - ++i; - } + fcn_index_map::iterator pos = m_fcn_index.find (fcn); + // FIXME: This panic_unless statements doesn't make sense if profile() + // is called from within a function hierarchy to begin with. + // See bug #39587. + // panic_unless (pos != m_fcn_index.end ()); + m_active_fcn = m_active_fcn->exit (pos->second); - octave_map retval; + // If this was an "inner call", we resume executing the parent function + // up the stack. So note the start-time for this! + m_last_time = query_time (); + } +} - retval.assign ("Index", rv_indices); - retval.assign ("SelfTime", rv_times); - retval.assign ("TotalTime", rv_totals); - retval.assign ("NumCalls", rv_calls); - retval.assign ("Children", rv_children); +void +profiler::reset (void) +{ + if (enabled ()) + error ("profile: can't reset active profiler"); + + m_known_functions.clear (); + m_fcn_index.clear (); - return retval; - } + if (m_call_tree) + { + delete m_call_tree; + m_call_tree = new tree_node (nullptr, 0); + m_active_fcn = nullptr; + } - profiler::profiler (void) - : m_known_functions (), m_fcn_index (), - m_enabled (false), m_call_tree (new tree_node (nullptr, 0)), - m_active_fcn (nullptr), m_last_time (-1.0) - { } + m_last_time = -1.0; +} + +octave_value +profiler::get_flat (void) const +{ + octave_value retval; - profiler::~profiler (void) - { - delete m_call_tree; - } + const octave_idx_type n = m_known_functions.size (); + + flat_profile flat (n); - void - profiler::set_active (bool value) - { - m_enabled = value; - } + if (m_call_tree) + { + m_call_tree->build_flat (flat); + + Cell rv_names (n, 1); + Cell rv_times (n, 1); + Cell rv_calls (n, 1); + Cell rv_recursive (n, 1); + Cell rv_parents (n, 1); + Cell rv_children (n, 1); - void - profiler::enter_function (const std::string& fcn) - { - // The enter class will check and only call us if the profiler is active. - panic_unless (enabled ()); - panic_unless (m_call_tree); + for (octave_idx_type i = 0; i != n; ++i) + { + rv_names(i) = octave_value (m_known_functions[i]); + rv_times(i) = octave_value (flat[i].m_time); + rv_calls(i) = octave_value (flat[i].m_calls); + rv_recursive(i) = octave_value (flat[i].m_recursive); + rv_parents(i) = stats::function_set_value (flat[i].m_parents); + rv_children(i) = stats::function_set_value (flat[i].m_children); + } + + octave_map m; - // If there is already an active function, add to its time before - // pushing the new one. - if (m_active_fcn && m_active_fcn != m_call_tree) - add_current_time (); + m.assign ("FunctionName", rv_names); + m.assign ("TotalTime", rv_times); + m.assign ("NumCalls", rv_calls); + m.assign ("IsRecursive", rv_recursive); + m.assign ("Parents", rv_parents); + m.assign ("Children", rv_children); - // Map the function's name to its index. - octave_idx_type fcn_idx; - fcn_index_map::iterator pos = m_fcn_index.find (fcn); - if (pos == m_fcn_index.end ()) + retval = m; + } + else + { + static const char *fn[] = { - m_known_functions.push_back (fcn); - fcn_idx = m_known_functions.size (); - m_fcn_index[fcn] = fcn_idx; - } - else - fcn_idx = pos->second; - - if (! m_active_fcn) - m_active_fcn = m_call_tree; - - m_active_fcn = m_active_fcn->enter (fcn_idx); - - m_last_time = query_time (); - - } + "FunctionName", + "TotalTime", + "NumCalls", + "IsRecursive", + "Parents", + "Children", + nullptr + }; - void - profiler::exit_function (const std::string& fcn) - { - if (m_active_fcn) - { - panic_unless (m_call_tree); - // FIXME: This panic_unless statements doesn't make sense if profile() - // is called from within a function hierarchy to begin with. - // See bug #39587. - // panic_unless (m_active_fcn != m_call_tree); - - // Usually, if we are disabled this function is not even called. But - // the call disabling the profiler is an exception. So also check here - // and only record the time if enabled. - if (enabled ()) - add_current_time (); - - fcn_index_map::iterator pos = m_fcn_index.find (fcn); - // FIXME: This panic_unless statements doesn't make sense if profile() - // is called from within a function hierarchy to begin with. - // See bug #39587. - // panic_unless (pos != m_fcn_index.end ()); - m_active_fcn = m_active_fcn->exit (pos->second); + static octave_map m (dim_vector (0, 1), string_vector (fn)); - // If this was an "inner call", we resume executing the parent function - // up the stack. So note the start-time for this! - m_last_time = query_time (); - } - } - - void - profiler::reset (void) - { - if (enabled ()) - error ("profile: can't reset active profiler"); - - m_known_functions.clear (); - m_fcn_index.clear (); - - if (m_call_tree) - { - delete m_call_tree; - m_call_tree = new tree_node (nullptr, 0); - m_active_fcn = nullptr; - } + retval = m; + } - m_last_time = -1.0; - } - - octave_value - profiler::get_flat (void) const - { - octave_value retval; - - const octave_idx_type n = m_known_functions.size (); + return retval; +} - flat_profile flat (n); - - if (m_call_tree) - { - m_call_tree->build_flat (flat); - - Cell rv_names (n, 1); - Cell rv_times (n, 1); - Cell rv_calls (n, 1); - Cell rv_recursive (n, 1); - Cell rv_parents (n, 1); - Cell rv_children (n, 1); +octave_value +profiler::get_hierarchical (void) const +{ + octave_value retval; - for (octave_idx_type i = 0; i != n; ++i) - { - rv_names(i) = octave_value (m_known_functions[i]); - rv_times(i) = octave_value (flat[i].m_time); - rv_calls(i) = octave_value (flat[i].m_calls); - rv_recursive(i) = octave_value (flat[i].m_recursive); - rv_parents(i) = stats::function_set_value (flat[i].m_parents); - rv_children(i) = stats::function_set_value (flat[i].m_children); - } - - octave_map m; - - m.assign ("FunctionName", rv_names); - m.assign ("TotalTime", rv_times); - m.assign ("NumCalls", rv_calls); - m.assign ("IsRecursive", rv_recursive); - m.assign ("Parents", rv_parents); - m.assign ("Children", rv_children); + if (m_call_tree) + retval = m_call_tree->get_hierarchical (); + else + { + static const char *fn[] = + { + "Index", + "SelfTime", + "NumCalls", + "Children", + nullptr + }; - retval = m; - } - else - { - static const char *fn[] = - { - "FunctionName", - "TotalTime", - "NumCalls", - "IsRecursive", - "Parents", - "Children", - nullptr - }; + static octave_map m (dim_vector (0, 1), string_vector (fn)); - static octave_map m (dim_vector (0, 1), string_vector (fn)); + retval = m; + } - retval = m; - } - - return retval; - } + return retval; +} - octave_value - profiler::get_hierarchical (void) const - { - octave_value retval; +double +profiler::query_time (void) const +{ + sys::time now; - if (m_call_tree) - retval = m_call_tree->get_hierarchical (); - else - { - static const char *fn[] = - { - "Index", - "SelfTime", - "NumCalls", - "Children", - nullptr - }; - - static octave_map m (dim_vector (0, 1), string_vector (fn)); - - retval = m; - } + // FIXME: is this volatile declaration really needed? + // See bug #34210 for additional details. + volatile double dnow = now.double_value (); - return retval; - } - - double - profiler::query_time (void) const - { - sys::time now; - - // FIXME: is this volatile declaration really needed? - // See bug #34210 for additional details. - volatile double dnow = now.double_value (); + return dnow; +} - return dnow; - } +void +profiler::add_current_time (void) +{ + if (m_active_fcn) + { + const double t = query_time (); - void - profiler::add_current_time (void) - { - if (m_active_fcn) - { - const double t = query_time (); - - m_active_fcn->add_time (t - m_last_time); - } - } + m_active_fcn->add_time (t - m_last_time); + } +} // Enable or disable the profiler data collection. DEFMETHOD (__profiler_enable__, interp, args, , diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/profiler.h --- a/libinterp/parse-tree/profiler.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/profiler.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,187 +38,187 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTINTERP_API - profiler +class +OCTINTERP_API +profiler +{ +public: + + // This is a utility class that can be used to call the enter/exit + // functions in a manner protected from stack unwinding. + template class enter + { + private: + + profiler& m_profiler; + std::string m_fcn; + bool m_enabled; + + public: + + enter (profiler& p, const T& t) : m_profiler (p) + { + // A profiling block cannot be active if the profiler is not + m_enabled = m_profiler.enabled (); + + if (m_enabled) + { + m_fcn = t.profiler_name (); + + // NOTE: The test f != "" must be kept to prevent a blank + // line showing up in profiler statistics. See bug + // #39524. The root cause is that the function name is + // not set for the recurring readline hook function. + if (m_fcn == "") + m_enabled = false; // Inactive profiling block + else + m_profiler.enter_function (m_fcn); + } + } + + // No copying! + + enter (const enter&) = delete; + + enter& operator = (const enter&) = delete; + + ~enter (void) + { + if (m_enabled) + m_profiler.exit_function (m_fcn); + } + }; + + profiler (void); + + // No copying! + + profiler (const profiler&) = delete; + + profiler& operator = (const profiler&) = delete; + + virtual ~profiler (void); + + bool enabled (void) const { return m_enabled; } + void set_active (bool); + + void reset (void); + + octave_value get_flat (void) const; + octave_value get_hierarchical (void) const; + +private: + + // One entry in the flat profile (i.e., a collection of data for a single + // function). This is filled in when building the flat profile from the + // hierarchical call tree. + struct stats + { + public: + stats (void); + + typedef std::set function_set; + + // Convert a function_set list to an Octave array of indices. + static octave_value function_set_value (const function_set&); + + //-------- + + double m_time; + std::size_t m_calls; + + bool m_recursive; + + function_set m_parents; + function_set m_children; + }; + + typedef std::vector flat_profile; + + // Store data for one node in the call-tree of the hierarchical profiler + // data we collect. + class tree_node { public: - // This is a utility class that can be used to call the enter/exit - // functions in a manner protected from stack unwinding. - template class enter - { - private: - - profiler& m_profiler; - std::string m_fcn; - bool m_enabled; - - public: - - enter (profiler& p, const T& t) : m_profiler (p) - { - // A profiling block cannot be active if the profiler is not - m_enabled = m_profiler.enabled (); - - if (m_enabled) - { - m_fcn = t.profiler_name (); + tree_node (tree_node *, octave_idx_type); - // NOTE: The test f != "" must be kept to prevent a blank - // line showing up in profiler statistics. See bug - // #39524. The root cause is that the function name is - // not set for the recurring readline hook function. - if (m_fcn == "") - m_enabled = false; // Inactive profiling block - else - m_profiler.enter_function (m_fcn); - } - } - - // No copying! - - enter (const enter&) = delete; - - enter& operator = (const enter&) = delete; - - ~enter (void) - { - if (m_enabled) - m_profiler.exit_function (m_fcn); - } - }; - - profiler (void); + virtual ~tree_node (void); // No copying! - profiler (const profiler&) = delete; + tree_node (const tree_node&) = delete; + + tree_node& operator = (const tree_node&) = delete; - profiler& operator = (const profiler&) = delete; + void add_time (double dt) { m_time += dt; } - virtual ~profiler (void); + // Enter a child function. It is created in the list of children if it + // wasn't already there. The now-active child node is returned. + tree_node * enter (octave_idx_type); - bool enabled (void) const { return m_enabled; } - void set_active (bool); + // Exit function. As a sanity-check, it is verified that the currently + // active function actually is the one handed in here. Returned is the + // then-active node, which is our parent. + tree_node * exit (octave_idx_type); - void reset (void); + void build_flat (flat_profile&) const; - octave_value get_flat (void) const; - octave_value get_hierarchical (void) const; + // Get the hierarchical profile for this node and its children. If total + // is set, accumulate total time of the subtree in that variable as + // additional return value. + octave_value get_hierarchical (double *total = nullptr) const; private: - // One entry in the flat profile (i.e., a collection of data for a single - // function). This is filled in when building the flat profile from the - // hierarchical call tree. - struct stats - { - public: - stats (void); - - typedef std::set function_set; - - // Convert a function_set list to an Octave array of indices. - static octave_value function_set_value (const function_set&); + tree_node *m_parent; + octave_idx_type m_fcn_id; - //-------- - - double m_time; - std::size_t m_calls; + typedef std::map child_map; + child_map m_children; - bool m_recursive; - - function_set m_parents; - function_set m_children; - }; - - typedef std::vector flat_profile; + // This is only time spent *directly* on this level, excluding children! + double m_time; - // Store data for one node in the call-tree of the hierarchical profiler - // data we collect. - class tree_node - { - public: - - tree_node (tree_node*, octave_idx_type); - - virtual ~tree_node (void); - - // No copying! - - tree_node (const tree_node&) = delete; + std::size_t m_calls; + }; - tree_node& operator = (const tree_node&) = delete; - - void add_time (double dt) { m_time += dt; } + // Each function we see in the profiler is given a unique index (which + // simply counts starting from 1). We thus have to map profiler-names to + // those indices. For all other stuff, we identify functions by their + // index. - // Enter a child function. It is created in the list of children if it - // wasn't already there. The now-active child node is returned. - tree_node *enter (octave_idx_type); + typedef std::vector function_set; + typedef std::map fcn_index_map; - // Exit function. As a sanity-check, it is verified that the currently - // active function actually is the one handed in here. Returned is the - // then-active node, which is our parent. - tree_node *exit (octave_idx_type); - - void build_flat (flat_profile&) const; + function_set m_known_functions; + fcn_index_map m_fcn_index; - // Get the hierarchical profile for this node and its children. If total - // is set, accumulate total time of the subtree in that variable as - // additional return value. - octave_value get_hierarchical (double *total = nullptr) const; - - private: - - tree_node *m_parent; - octave_idx_type m_fcn_id; - - typedef std::map child_map; - child_map m_children; + bool m_enabled; - // This is only time spent *directly* on this level, excluding children! - double m_time; - - std::size_t m_calls; - }; + tree_node *m_call_tree; + tree_node *m_active_fcn; - // Each function we see in the profiler is given a unique index (which - // simply counts starting from 1). We thus have to map profiler-names to - // those indices. For all other stuff, we identify functions by their - // index. - - typedef std::vector function_set; - typedef std::map fcn_index_map; + // Store last timestamp we had, when the currently active function was + // called. + double m_last_time; - function_set m_known_functions; - fcn_index_map m_fcn_index; - - bool m_enabled; - - tree_node *m_call_tree; - tree_node *m_active_fcn; - - // Store last timestamp we had, when the currently active function was - // called. - double m_last_time; + // These are private as only the unwind-protecting inner class enter + // should be allowed to call them. + void enter_function (const std::string&); + void exit_function (const std::string&); - // These are private as only the unwind-protecting inner class enter - // should be allowed to call them. - void enter_function (const std::string&); - void exit_function (const std::string&); + // Query a timestamp, used for timing calls (obviously). + // This is not static because in the future, maybe we want a flag + // in the profiler or something to choose between cputime, wall-time, + // user-time, system-time, ... + double query_time (void) const; - // Query a timestamp, used for timing calls (obviously). - // This is not static because in the future, maybe we want a flag - // in the profiler or something to choose between cputime, wall-time, - // user-time, system-time, ... - double query_time (void) const; - - // Add the time elapsed since last_time to the function we're currently in. - // This is called from two different positions, thus it is useful to have - // it as a separate function. - void add_current_time (void); - }; + // Add the time elapsed since last_time to the function we're currently in. + // This is called from two different positions, thus it is useful to have + // it as a separate function. + void add_current_time (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-anon-scopes.cc --- a/libinterp/parse-tree/pt-anon-scopes.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-anon-scopes.cc Thu Dec 01 20:05:44 2022 -0800 @@ -35,91 +35,91 @@ OCTAVE_BEGIN_NAMESPACE(octave) - tree_anon_scopes::tree_anon_scopes (tree_anon_fcn_handle& anon_fh) - : tree_walker (), m_params (), m_vars () - { - visit_anon_fcn_handle (anon_fh); - } +tree_anon_scopes::tree_anon_scopes (tree_anon_fcn_handle& anon_fh) + : tree_walker (), m_params (), m_vars () +{ + visit_anon_fcn_handle (anon_fh); +} - void - tree_anon_scopes::visit_anon_fcn_handle (tree_anon_fcn_handle& afh) - { - tree_parameter_list *param_list = afh.parameter_list (); - tree_expression *expr = afh.expression (); +void +tree_anon_scopes::visit_anon_fcn_handle (tree_anon_fcn_handle& afh) +{ + tree_parameter_list *param_list = afh.parameter_list (); + tree_expression *expr = afh.expression (); - // Collect names of parameters. + // Collect names of parameters. - if (param_list) - { - std::list pnames = param_list->variable_names (); + if (param_list) + { + std::list pnames = param_list->variable_names (); - for (const auto& nm : pnames) - m_params.insert (nm); + for (const auto& nm : pnames) + m_params.insert (nm); - // Hmm, should this be included in the list returned from - // tree_parameter_list::variable_names? - if (param_list->takes_varargs ()) - m_params.insert ("varargin"); - } + // Hmm, should this be included in the list returned from + // tree_parameter_list::variable_names? + if (param_list->takes_varargs ()) + m_params.insert ("varargin"); + } - // Further walk the tree to find free variables in this expression - // and any nested definitions of additional anonymous functions. + // Further walk the tree to find free variables in this expression + // and any nested definitions of additional anonymous functions. - if (expr) - expr->accept (*this); - } + if (expr) + expr->accept (*this); +} - // The rest of visit_... methods is only for walking the tree. Many of - // them, in particular all methods for commands, are not applicable to - // anonymous functions. Only parts of the tree are walked which could - // contain further (nested) anonymous function definitions (so - // e.g. identifiers and left hand sides of assignments are ignored). +// The rest of visit_... methods is only for walking the tree. Many of +// them, in particular all methods for commands, are not applicable to +// anonymous functions. Only parts of the tree are walked which could +// contain further (nested) anonymous function definitions (so +// e.g. identifiers and left hand sides of assignments are ignored). - void - tree_anon_scopes::visit_identifier (tree_identifier& id) - { - std::string nm = id.name (); +void +tree_anon_scopes::visit_identifier (tree_identifier& id) +{ + std::string nm = id.name (); - if (m_params.find (nm) == m_params.end ()) - m_vars.insert (nm); - } + if (m_params.find (nm) == m_params.end ()) + m_vars.insert (nm); +} - void - tree_anon_scopes::visit_parameter_list (tree_parameter_list&) - { - // In visit_anon_fcn_handle we only accept/visit the body of - // anonymous function definitions, not the parameter list. +void +tree_anon_scopes::visit_parameter_list (tree_parameter_list&) +{ + // In visit_anon_fcn_handle we only accept/visit the body of + // anonymous function definitions, not the parameter list. - panic_impossible (); - } + panic_impossible (); +} - void - tree_anon_scopes::visit_statement (tree_statement& stmt) - { - tree_command *cmd = stmt.command (); +void +tree_anon_scopes::visit_statement (tree_statement& stmt) +{ + tree_command *cmd = stmt.command (); - if (cmd) - panic_impossible (); - else - { - tree_expression *expr = stmt.expression (); + if (cmd) + panic_impossible (); + else + { + tree_expression *expr = stmt.expression (); - if (expr) - expr->accept (*this); - } - } + if (expr) + expr->accept (*this); + } +} - void - tree_anon_scopes::visit_statement_list (tree_statement_list& lst) - { - for (auto& p : lst) - { - tree_statement *elt = p; +void +tree_anon_scopes::visit_statement_list (tree_statement_list& lst) +{ + for (auto& p : lst) + { + tree_statement *elt = p; - if (elt) - elt->accept (*this); - } - } + if (elt) + elt->accept (*this); + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-anon-scopes.h --- a/libinterp/parse-tree/pt-anon-scopes.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-anon-scopes.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,51 +33,51 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // In possibly nested definitions of anonymous functions, collect - // their scopes and the symbol records therein. +// In possibly nested definitions of anonymous functions, collect +// their scopes and the symbol records therein. - class - tree_anon_scopes : public tree_walker - { - public: +class +tree_anon_scopes : public tree_walker +{ +public: - tree_anon_scopes (void) = delete; + tree_anon_scopes (void) = delete; - tree_anon_scopes (tree_anon_fcn_handle& anon_fh); + tree_anon_scopes (tree_anon_fcn_handle& anon_fh); - // No copying! + // No copying! - tree_anon_scopes (const tree_anon_scopes&) = delete; + tree_anon_scopes (const tree_anon_scopes&) = delete; - tree_anon_scopes& operator = (const tree_anon_scopes&) = delete; + tree_anon_scopes& operator = (const tree_anon_scopes&) = delete; - ~tree_anon_scopes (void) = default; + ~tree_anon_scopes (void) = default; - std::set fcn_parameters (void) const { return m_params; } + std::set fcn_parameters (void) const { return m_params; } - std::set free_variables (void) const { return m_vars; } + std::set free_variables (void) const { return m_vars; } - // The following methods, though public, don't belong to the - // intended user interface of this class. + // The following methods, though public, don't belong to the + // intended user interface of this class. - void visit_anon_fcn_handle (tree_anon_fcn_handle&); + void visit_anon_fcn_handle (tree_anon_fcn_handle&); - void visit_identifier (tree_identifier&); + void visit_identifier (tree_identifier&); - void visit_parameter_list (tree_parameter_list&); + void visit_parameter_list (tree_parameter_list&); - void visit_statement (tree_statement&); + void visit_statement (tree_statement&); - void visit_statement_list (tree_statement_list&); + void visit_statement_list (tree_statement_list&); - private: +private: - // Variable names that are function parameters. - std::set m_params; + // Variable names that are function parameters. + std::set m_params; - // Other variable names. - std::set m_vars; - }; + // Other variable names. + std::set m_vars; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-arg-list.cc --- a/libinterp/parse-tree/pt-arg-list.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-arg-list.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,113 +41,113 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Argument lists. +// Argument lists. - tree_argument_list::~tree_argument_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_argument_list::~tree_argument_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - void - tree_argument_list::append (const element_type& s) - { - base_list::append (s); +void +tree_argument_list::append (const element_type& s) +{ + base_list::append (s); - if (! m_list_includes_magic_tilde && s && s->is_identifier ()) - { - tree_identifier *id = dynamic_cast (s); - m_list_includes_magic_tilde = id && id->is_black_hole (); - } - } + if (! m_list_includes_magic_tilde && s && s->is_identifier ()) + { + tree_identifier *id = dynamic_cast (s); + m_list_includes_magic_tilde = id && id->is_black_hole (); + } +} - bool - tree_argument_list::all_elements_are_constant (void) const - { - for (const tree_expression *elt : *this) - { - if (! elt->is_constant ()) - return false; - } +bool +tree_argument_list::all_elements_are_constant (void) const +{ + for (const tree_expression *elt : *this) + { + if (! elt->is_constant ()) + return false; + } - return true; - } + return true; +} - bool - tree_argument_list::is_valid_lvalue_list (void) const - { - bool retval = true; +bool +tree_argument_list::is_valid_lvalue_list (void) const +{ + bool retval = true; - for (const tree_expression *elt : *this) - { - // There is no need for a separate check for the magic "~" because it - // is represented by tree_black_hole, and that is derived from - // tree_identifier. - if (! (elt->is_identifier () || elt->is_index_expression ())) - { - retval = false; - break; - } - } + for (const tree_expression *elt : *this) + { + // There is no need for a separate check for the magic "~" because it + // is represented by tree_black_hole, and that is derived from + // tree_identifier. + if (! (elt->is_identifier () || elt->is_index_expression ())) + { + retval = false; + break; + } + } - return retval; - } + return retval; +} - string_vector - tree_argument_list::get_arg_names (void) const - { - int len = length (); +string_vector +tree_argument_list::get_arg_names (void) const +{ + int len = length (); - string_vector retval (len); + string_vector retval (len); - int k = 0; + int k = 0; - for (tree_expression *elt : *this) - retval(k++) = elt->str_print_code (); + for (tree_expression *elt : *this) + retval(k++) = elt->str_print_code (); - return retval; - } + return retval; +} - std::list - tree_argument_list::variable_names (void) const - { - std::list retval; +std::list +tree_argument_list::variable_names (void) const +{ + std::list retval; - for (tree_expression *elt : *this) - { - if (elt->is_identifier ()) - { - tree_identifier *id = dynamic_cast (elt); + for (tree_expression *elt : *this) + { + if (elt->is_identifier ()) + { + tree_identifier *id = dynamic_cast (elt); - retval.push_back (id->name ()); - } - else if (elt->is_index_expression ()) - { - tree_index_expression *idx_expr - = dynamic_cast (elt); + retval.push_back (id->name ()); + } + else if (elt->is_index_expression ()) + { + tree_index_expression *idx_expr + = dynamic_cast (elt); - retval.push_back (idx_expr->name ()); - } - } + retval.push_back (idx_expr->name ()); + } + } - return retval; - } + return retval; +} - tree_argument_list * - tree_argument_list::dup (symbol_scope& scope) const - { - tree_argument_list *new_list = new tree_argument_list (); +tree_argument_list * +tree_argument_list::dup (symbol_scope& scope) const +{ + tree_argument_list *new_list = new tree_argument_list (); - new_list->m_simple_assign_lhs = m_simple_assign_lhs; + new_list->m_simple_assign_lhs = m_simple_assign_lhs; - for (const tree_expression *elt : *this) - new_list->append (elt ? elt->dup (scope) : nullptr); + for (const tree_expression *elt : *this) + new_list->append (elt ? elt->dup (scope) : nullptr); - return new_list; - } + return new_list; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-arg-list.h --- a/libinterp/parse-tree/pt-arg-list.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-arg-list.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,80 +40,80 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_evaluator; - class tree_expression; +class symbol_scope; +class tree_evaluator; +class tree_expression; - // Argument lists. Used to hold the list of expressions that are the - // arguments in a function call or index expression. +// Argument lists. Used to hold the list of expressions that are the +// arguments in a function call or index expression. - class tree_argument_list : public base_list - { - public: +class tree_argument_list : public base_list +{ +public: - typedef tree_expression* element_type; + typedef tree_expression *element_type; - tree_argument_list (void) - : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false) - { } + tree_argument_list (void) + : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false) + { } - tree_argument_list (tree_expression *t) - : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false) - { append (t); } + tree_argument_list (tree_expression *t) + : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false) + { append (t); } - // No copying! + // No copying! - tree_argument_list (const tree_argument_list&) = delete; + tree_argument_list (const tree_argument_list&) = delete; - tree_argument_list& operator = (const tree_argument_list&) = delete; + tree_argument_list& operator = (const tree_argument_list&) = delete; - ~tree_argument_list (void); + ~tree_argument_list (void); - bool has_magic_tilde (void) const - { - return m_list_includes_magic_tilde; - } + bool has_magic_tilde (void) const + { + return m_list_includes_magic_tilde; + } - bool includes_magic_tilde (void) const - { - return m_list_includes_magic_tilde; - } + bool includes_magic_tilde (void) const + { + return m_list_includes_magic_tilde; + } - tree_expression * remove_front (void) - { - auto p = begin (); - tree_expression *retval = *p; - erase (p); - return retval; - } + tree_expression * remove_front (void) + { + auto p = begin (); + tree_expression *retval = *p; + erase (p); + return retval; + } - void append (const element_type& s); + void append (const element_type& s); - void mark_as_simple_assign_lhs (void) { m_simple_assign_lhs = true; } + void mark_as_simple_assign_lhs (void) { m_simple_assign_lhs = true; } - bool is_simple_assign_lhs (void) { return m_simple_assign_lhs; } + bool is_simple_assign_lhs (void) { return m_simple_assign_lhs; } - bool all_elements_are_constant (void) const; + bool all_elements_are_constant (void) const; - bool is_valid_lvalue_list (void) const; + bool is_valid_lvalue_list (void) const; - string_vector get_arg_names (void) const; + string_vector get_arg_names (void) const; - std::list variable_names (void) const; + std::list variable_names (void) const; - tree_argument_list * dup (symbol_scope& scope) const; + tree_argument_list * dup (symbol_scope& scope) const; - void accept (tree_walker& tw) - { - tw.visit_argument_list (*this); - } + void accept (tree_walker& tw) + { + tw.visit_argument_list (*this); + } - private: +private: - bool m_list_includes_magic_tilde; + bool m_list_includes_magic_tilde; - bool m_simple_assign_lhs; - }; + bool m_simple_assign_lhs; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-args-block.cc --- a/libinterp/parse-tree/pt-args-block.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-args-block.cc Thu Dec 01 20:05:44 2022 -0800 @@ -31,14 +31,14 @@ OCTAVE_BEGIN_NAMESPACE(octave) - tree_args_block_validation_list::~tree_args_block_validation_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_args_block_validation_list::~tree_args_block_validation_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-args-block.h --- a/libinterp/parse-tree/pt-args-block.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-args-block.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,250 +41,250 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_arg_size_spec - { - public: +class tree_arg_size_spec +{ +public: - tree_arg_size_spec (tree_argument_list *size_args) - : m_size_args (size_args) - { } + tree_arg_size_spec (tree_argument_list *size_args) + : m_size_args (size_args) + { } - // No copying! + // No copying! - tree_arg_size_spec (const tree_arg_size_spec&) = delete; + tree_arg_size_spec (const tree_arg_size_spec&) = delete; - tree_arg_size_spec& operator = (const tree_arg_size_spec&) = delete; + tree_arg_size_spec& operator = (const tree_arg_size_spec&) = delete; - ~tree_arg_size_spec (void) - { - delete m_size_args; - } + ~tree_arg_size_spec (void) + { + delete m_size_args; + } - tree_argument_list * size_args (void) { return m_size_args; } + tree_argument_list * size_args (void) { return m_size_args; } - void accept (tree_walker& tw) - { - tw.visit_arg_size_spec (*this); - } + void accept (tree_walker& tw) + { + tw.visit_arg_size_spec (*this); + } - private: +private: - tree_argument_list *m_size_args; - }; + tree_argument_list *m_size_args; +}; - class tree_arg_validation_fcns - { - public: +class tree_arg_validation_fcns +{ +public: - tree_arg_validation_fcns (tree_argument_list *fcn_args) - : m_fcn_args (fcn_args) - { } + tree_arg_validation_fcns (tree_argument_list *fcn_args) + : m_fcn_args (fcn_args) + { } - // No copying! + // No copying! - tree_arg_validation_fcns (const tree_arg_validation_fcns&) = delete; + tree_arg_validation_fcns (const tree_arg_validation_fcns&) = delete; - tree_arg_validation_fcns& operator = (const tree_arg_validation_fcns&) = delete; + tree_arg_validation_fcns& operator = (const tree_arg_validation_fcns&) = delete; - ~tree_arg_validation_fcns (void) - { - delete m_fcn_args; - } + ~tree_arg_validation_fcns (void) + { + delete m_fcn_args; + } - tree_argument_list * fcn_args (void) { return m_fcn_args; } + tree_argument_list * fcn_args (void) { return m_fcn_args; } - void accept (tree_walker& tw) - { - tw.visit_arg_validation_fcns (*this); - } + void accept (tree_walker& tw) + { + tw.visit_arg_validation_fcns (*this); + } - private: +private: - tree_argument_list *m_fcn_args; - }; + tree_argument_list *m_fcn_args; +}; - class tree_arg_validation - { - public: +class tree_arg_validation +{ +public: - tree_arg_validation (tree_arg_size_spec *size_spec, - tree_identifier *class_name, - tree_arg_validation_fcns *validation_fcns, - tree_expression *default_value) - : m_arg_name (nullptr), m_size_spec (size_spec), - m_class_name (class_name), m_validation_fcns (validation_fcns), - m_default_value (default_value) - { } + tree_arg_validation (tree_arg_size_spec *size_spec, + tree_identifier *class_name, + tree_arg_validation_fcns *validation_fcns, + tree_expression *default_value) + : m_arg_name (nullptr), m_size_spec (size_spec), + m_class_name (class_name), m_validation_fcns (validation_fcns), + m_default_value (default_value) + { } - // No copying! + // No copying! - tree_arg_validation (const tree_arg_validation&) = delete; + tree_arg_validation (const tree_arg_validation&) = delete; - tree_arg_validation& operator = (const tree_arg_validation&) = delete; + tree_arg_validation& operator = (const tree_arg_validation&) = delete; - ~tree_arg_validation (void) - { - delete m_arg_name; - delete m_size_spec; - delete m_class_name; - delete m_validation_fcns; - delete m_default_value; - } + ~tree_arg_validation (void) + { + delete m_arg_name; + delete m_size_spec; + delete m_class_name; + delete m_validation_fcns; + delete m_default_value; + } - void arg_name (tree_expression *name) - { - m_arg_name = name; - } + void arg_name (tree_expression *name) + { + m_arg_name = name; + } - tree_expression * identifier_expression (void) { return m_arg_name; } + tree_expression * identifier_expression (void) { return m_arg_name; } - tree_arg_size_spec * size_spec (void) { return m_size_spec; } + tree_arg_size_spec * size_spec (void) { return m_size_spec; } - tree_identifier * class_name (void) { return m_class_name; } + tree_identifier * class_name (void) { return m_class_name; } - tree_arg_validation_fcns * - validation_fcns (void) { return m_validation_fcns; } + tree_arg_validation_fcns * + validation_fcns (void) { return m_validation_fcns; } - tree_expression * - initializer_expression (void) { return m_default_value; } + tree_expression * + initializer_expression (void) { return m_default_value; } - void accept (tree_walker& tw) - { - tw.visit_arg_validation (*this); - } + void accept (tree_walker& tw) + { + tw.visit_arg_validation (*this); + } - private: +private: - // May be a simple identifier or an identifier followed by a single - // field name. - tree_expression *m_arg_name; - tree_arg_size_spec *m_size_spec; - tree_identifier *m_class_name; - tree_arg_validation_fcns *m_validation_fcns; - tree_expression *m_default_value; - }; + // May be a simple identifier or an identifier followed by a single + // field name. + tree_expression *m_arg_name; + tree_arg_size_spec *m_size_spec; + tree_identifier *m_class_name; + tree_arg_validation_fcns *m_validation_fcns; + tree_expression *m_default_value; +}; - class tree_args_block_validation_list - : public base_list - { - public: +class tree_args_block_validation_list + : public base_list +{ +public: - tree_args_block_validation_list (void) { } + tree_args_block_validation_list (void) { } - tree_args_block_validation_list (tree_arg_validation *a) { append (a); } + tree_args_block_validation_list (tree_arg_validation *a) { append (a); } - tree_args_block_validation_list (const base_list& a) - : base_list (a) - { } + tree_args_block_validation_list (const base_list& a) + : base_list (a) + { } - // No copying! + // No copying! - tree_args_block_validation_list (const tree_args_block_validation_list&) = delete; + tree_args_block_validation_list (const tree_args_block_validation_list&) = delete; - tree_args_block_validation_list& operator = (const tree_args_block_validation_list&) = delete; + tree_args_block_validation_list& operator = (const tree_args_block_validation_list&) = delete; - ~tree_args_block_validation_list (void); + ~tree_args_block_validation_list (void); - void accept (tree_walker& tw) - { - tw.visit_args_block_validation_list (*this); - } - }; + void accept (tree_walker& tw) + { + tw.visit_args_block_validation_list (*this); + } +}; - // FIXME: Maybe make this object an actual list even though we don't - // currently need it? +// FIXME: Maybe make this object an actual list even though we don't +// currently need it? - class tree_args_block_attribute_list - { - public: +class tree_args_block_attribute_list +{ +public: - tree_args_block_attribute_list (tree_identifier *attr = nullptr) - : m_attr (attr) - { } + tree_args_block_attribute_list (tree_identifier *attr = nullptr) + : m_attr (attr) + { } - // No copying! + // No copying! - tree_args_block_attribute_list (const tree_args_block_attribute_list&) = delete; + tree_args_block_attribute_list (const tree_args_block_attribute_list&) = delete; - tree_args_block_attribute_list& operator = (const tree_args_block_attribute_list&) = delete; + tree_args_block_attribute_list& operator = (const tree_args_block_attribute_list&) = delete; - ~tree_args_block_attribute_list (void) - { - delete m_attr; - } + ~tree_args_block_attribute_list (void) + { + delete m_attr; + } - tree_identifier * attribute (void) { return m_attr; } + tree_identifier * attribute (void) { return m_attr; } - void accept (tree_walker& tw) - { - tw.visit_args_block_attribute_list (*this); - } + void accept (tree_walker& tw) + { + tw.visit_args_block_attribute_list (*this); + } - private: +private: - tree_identifier *m_attr; - }; + tree_identifier *m_attr; +}; - // Arguments block. +// Arguments block. - class tree_arguments_block : public tree_command - { - public: +class tree_arguments_block : public tree_command +{ +public: - tree_arguments_block (tree_args_block_attribute_list *attr_list, - tree_args_block_validation_list *validation_list, - int l = -1, int c = -1) - : tree_command (l, c), m_attr_list (attr_list), - m_validation_list (validation_list), - m_lead_comm (nullptr), m_trail_comm (nullptr) - { } + tree_arguments_block (tree_args_block_attribute_list *attr_list, + tree_args_block_validation_list *validation_list, + int l = -1, int c = -1) + : tree_command (l, c), m_attr_list (attr_list), + m_validation_list (validation_list), + m_lead_comm (nullptr), m_trail_comm (nullptr) + { } - // No copying! + // No copying! - tree_arguments_block (const tree_arguments_block&) = delete; + tree_arguments_block (const tree_arguments_block&) = delete; - tree_arguments_block& operator = (const tree_arguments_block&) = delete; + tree_arguments_block& operator = (const tree_arguments_block&) = delete; - ~tree_arguments_block (void) - { - delete m_attr_list; - delete m_validation_list; + ~tree_arguments_block (void) + { + delete m_attr_list; + delete m_validation_list; - delete m_lead_comm; - delete m_trail_comm; - } + delete m_lead_comm; + delete m_trail_comm; + } - tree_args_block_attribute_list * attribute_list (void) - { - return m_attr_list; - } + tree_args_block_attribute_list * attribute_list (void) + { + return m_attr_list; + } - tree_args_block_validation_list * validation_list (void) - { - return m_validation_list; - } + tree_args_block_validation_list * validation_list (void) + { + return m_validation_list; + } - comment_list * leading_comment (void) { return m_lead_comm; } + comment_list * leading_comment (void) { return m_lead_comm; } - comment_list * trailing_comment (void) { return m_trail_comm; } + comment_list * trailing_comment (void) { return m_trail_comm; } - void accept (tree_walker& tw) - { - tw.visit_arguments_block (*this); - } + void accept (tree_walker& tw) + { + tw.visit_arguments_block (*this); + } - private: +private: - tree_args_block_attribute_list *m_attr_list; + tree_args_block_attribute_list *m_attr_list; - tree_args_block_validation_list *m_validation_list; + tree_args_block_validation_list *m_validation_list; - // Comment preceding ARGUMENTS token. - comment_list *m_lead_comm; + // Comment preceding ARGUMENTS token. + comment_list *m_lead_comm; - // Comment preceding ENDARGUMENTS token. - comment_list *m_trail_comm; - }; + // Comment preceding ENDARGUMENTS token. + comment_list *m_trail_comm; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-array-list.cc --- a/libinterp/parse-tree/pt-array-list.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-array-list.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,57 +34,57 @@ OCTAVE_BEGIN_NAMESPACE(octave) - tree_array_list::~tree_array_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_array_list::~tree_array_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - bool - tree_array_list::all_elements_are_constant (void) const - { - for (const tree_argument_list *elt : *this) - { - octave_quit (); +bool +tree_array_list::all_elements_are_constant (void) const +{ + for (const tree_argument_list *elt : *this) + { + octave_quit (); - if (! elt->all_elements_are_constant ()) - return false; - } + if (! elt->all_elements_are_constant ()) + return false; + } - return true; - } + return true; +} - void - tree_array_list::copy_base (const tree_array_list& array_list) - { - tree_expression::copy_base (array_list); - } +void +tree_array_list::copy_base (const tree_array_list& array_list) +{ + tree_expression::copy_base (array_list); +} - void - tree_array_list::copy_base (const tree_array_list& array_list, - symbol_scope& scope) - { - for (const tree_argument_list *elt : array_list) - append (elt ? elt->dup (scope) : nullptr); +void +tree_array_list::copy_base (const tree_array_list& array_list, + symbol_scope& scope) +{ + for (const tree_argument_list *elt : array_list) + append (elt ? elt->dup (scope) : nullptr); - copy_base (*this); - } + copy_base (*this); +} - tree_expression * - tree_array_list::dup (symbol_scope&) const - { - panic_impossible (); - return nullptr; - } +tree_expression * +tree_array_list::dup (symbol_scope&) const +{ + panic_impossible (); + return nullptr; +} - void - tree_array_list::accept (tree_walker&) - { - panic_impossible (); - } +void +tree_array_list::accept (tree_walker&) +{ + panic_impossible (); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-array-list.h --- a/libinterp/parse-tree/pt-array-list.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-array-list.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,56 +34,56 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_walker; +class symbol_scope; +class tree_walker; - // Base class for cell arrays and matrices. +// Base class for cell arrays and matrices. - class tree_array_list : public tree_expression, - public base_list - { - public: +class tree_array_list : public tree_expression, + public base_list +{ +public: - typedef base_list::iterator iterator; - typedef base_list::const_iterator const_iterator; + typedef base_list::iterator iterator; + typedef base_list::const_iterator const_iterator; - protected: +protected: - tree_array_list (tree_argument_list *row = nullptr, int l = -1, int c = -1) - : tree_expression (l, c), base_list () - { - if (row) - append (row); - } + tree_array_list (tree_argument_list *row = nullptr, int l = -1, int c = -1) + : tree_expression (l, c), base_list () + { + if (row) + append (row); + } - public: +public: - // No copying! + // No copying! - tree_array_list (const tree_array_list&) = delete; + tree_array_list (const tree_array_list&) = delete; - tree_array_list& operator = (const tree_array_list&) = delete; + tree_array_list& operator = (const tree_array_list&) = delete; - ~tree_array_list (void); + ~tree_array_list (void); - bool all_elements_are_constant (void) const; + bool all_elements_are_constant (void) const; - // FIXME: should we import the functions from the base class and - // overload them here, or should we use a different name so we don't - // have to do this? Without the using declaration or a name change, - // the base class functions will be hidden. That may be OK, but it - // can also cause some confusion. - using tree_expression::copy_base; + // FIXME: should we import the functions from the base class and + // overload them here, or should we use a different name so we don't + // have to do this? Without the using declaration or a name change, + // the base class functions will be hidden. That may be OK, but it + // can also cause some confusion. + using tree_expression::copy_base; - void copy_base (const tree_array_list& array_list); + void copy_base (const tree_array_list& array_list); - void copy_base (const tree_array_list& array_list, - symbol_scope& scope); + void copy_base (const tree_array_list& array_list, + symbol_scope& scope); - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - void accept (tree_walker& tw); - }; + void accept (tree_walker& tw); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-assign.cc --- a/libinterp/parse-tree/pt-assign.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-assign.cc Thu Dec 01 20:05:44 2022 -0800 @@ -38,317 +38,317 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Simple assignment expressions. +// Simple assignment expressions. - tree_simple_assignment::tree_simple_assignment (tree_expression *le, - tree_expression *re, - bool plhs, int l, int c, - octave_value::assign_op t) - : tree_expression (l, c), m_lhs (le), m_rhs (re), m_preserve (plhs), - m_ans_assign (), m_etype (t) - { } +tree_simple_assignment::tree_simple_assignment (tree_expression *le, + tree_expression *re, + bool plhs, int l, int c, + octave_value::assign_op t) + : tree_expression (l, c), m_lhs (le), m_rhs (re), m_preserve (plhs), + m_ans_assign (), m_etype (t) +{ } - tree_simple_assignment::~tree_simple_assignment (void) - { - if (! m_preserve) - delete m_lhs; +tree_simple_assignment::~tree_simple_assignment (void) +{ + if (! m_preserve) + delete m_lhs; - delete m_rhs; - } + delete m_rhs; +} - std::string - tree_simple_assignment::oper (void) const - { - return octave_value::assign_op_as_string (m_etype); - } +std::string +tree_simple_assignment::oper (void) const +{ + return octave_value::assign_op_as_string (m_etype); +} - tree_expression * - tree_simple_assignment::dup (symbol_scope& scope) const - { - tree_simple_assignment *new_sa - = new tree_simple_assignment (m_lhs ? m_lhs->dup (scope) : nullptr, - m_rhs ? m_rhs->dup (scope) : nullptr, - m_preserve, m_etype); +tree_expression * +tree_simple_assignment::dup (symbol_scope& scope) const +{ + tree_simple_assignment *new_sa + = new tree_simple_assignment (m_lhs ? m_lhs->dup (scope) : nullptr, + m_rhs ? m_rhs->dup (scope) : nullptr, + m_preserve, m_etype); - new_sa->copy_base (*this); + new_sa->copy_base (*this); - return new_sa; - } + return new_sa; +} - octave_value - tree_simple_assignment::evaluate (tree_evaluator& tw, int) - { - octave_value val; +octave_value +tree_simple_assignment::evaluate (tree_evaluator& tw, int) +{ + octave_value val; - if (m_rhs) - { - try + if (m_rhs) + { + try + { + octave_lvalue ult = m_lhs->lvalue (tw); + + std::list lvalue_list; + lvalue_list.push_back (ult); + + unwind_action act ([&tw] (const std::list *lvl) { - octave_lvalue ult = m_lhs->lvalue (tw); - - std::list lvalue_list; - lvalue_list.push_back (ult); - - unwind_action act ([&tw] (const std::list *lvl) - { - tw.set_lvalue_list (lvl); - }, tw.lvalue_list ()); - tw.set_lvalue_list (&lvalue_list); + tw.set_lvalue_list (lvl); + }, tw.lvalue_list ()); + tw.set_lvalue_list (&lvalue_list); - if (ult.numel () != 1) - err_invalid_structure_assignment (); + if (ult.numel () != 1) + err_invalid_structure_assignment (); - octave_value rhs_val = m_rhs->evaluate (tw); + octave_value rhs_val = m_rhs->evaluate (tw); - if (rhs_val.is_undefined ()) - error ("value on right hand side of assignment is undefined"); + if (rhs_val.is_undefined ()) + error ("value on right hand side of assignment is undefined"); - if (rhs_val.is_cs_list ()) - { - const octave_value_list lst = rhs_val.list_value (); + if (rhs_val.is_cs_list ()) + { + const octave_value_list lst = rhs_val.list_value (); - if (lst.empty ()) - error ("invalid number of elements on RHS of assignment"); + if (lst.empty ()) + error ("invalid number of elements on RHS of assignment"); - rhs_val = lst(0); - } + rhs_val = lst(0); + } - ult.assign (m_etype, rhs_val); + ult.assign (m_etype, rhs_val); - if (m_etype == octave_value::op_asn_eq) - val = rhs_val; - else - val = ult.value (); + if (m_etype == octave_value::op_asn_eq) + val = rhs_val; + else + val = ult.value (); - if (print_result () && tw.statement_printing_enabled ()) - { - // We clear any index here so that we can - // get the new value of the referenced - // object below, instead of the indexed - // value (which should be the same as the - // right hand side value). + if (print_result () && tw.statement_printing_enabled ()) + { + // We clear any index here so that we can + // get the new value of the referenced + // object below, instead of the indexed + // value (which should be the same as the + // right hand side value). - ult.clear_index (); + ult.clear_index (); - octave_value lhs_val = ult.value (); + octave_value lhs_val = ult.value (); - octave_value_list args = ovl (lhs_val); - args.stash_name_tags (string_vector (m_lhs->name ())); - feval ("display", args); - } - } - catch (index_exception& ie) - { - ie.set_var (m_lhs->name ()); - std::string msg = ie.message (); - error_with_id (ie.err_id (), "%s", msg.c_str ()); - } - } + octave_value_list args = ovl (lhs_val); + args.stash_name_tags (string_vector (m_lhs->name ())); + feval ("display", args); + } + } + catch (index_exception& ie) + { + ie.set_var (m_lhs->name ()); + std::string msg = ie.message (); + error_with_id (ie.err_id (), "%s", msg.c_str ()); + } + } - return val; - } + return val; +} - // Multi-valued assignment expressions. +// Multi-valued assignment expressions. - tree_multi_assignment::tree_multi_assignment (tree_argument_list *lst, - tree_expression *r, - bool plhs, int l, int c) - : tree_expression (l, c), m_lhs (lst), m_rhs (r), m_preserve (plhs) - { } +tree_multi_assignment::tree_multi_assignment (tree_argument_list *lst, + tree_expression *r, + bool plhs, int l, int c) + : tree_expression (l, c), m_lhs (lst), m_rhs (r), m_preserve (plhs) +{ } - tree_multi_assignment::~tree_multi_assignment (void) - { - if (! m_preserve) - delete m_lhs; +tree_multi_assignment::~tree_multi_assignment (void) +{ + if (! m_preserve) + delete m_lhs; - delete m_rhs; - } + delete m_rhs; +} - std::string - tree_multi_assignment::oper (void) const - { - return octave_value::assign_op_as_string (op_type ()); - } +std::string +tree_multi_assignment::oper (void) const +{ + return octave_value::assign_op_as_string (op_type ()); +} - tree_expression * - tree_multi_assignment::dup (symbol_scope&) const - { - panic_impossible (); - return nullptr; - } +tree_expression * +tree_multi_assignment::dup (symbol_scope&) const +{ + panic_impossible (); + return nullptr; +} - octave_value_list - tree_multi_assignment::evaluate_n (tree_evaluator& tw, int) - { - octave_value_list val; +octave_value_list +tree_multi_assignment::evaluate_n (tree_evaluator& tw, int) +{ + octave_value_list val; - if (m_rhs) - { - std::list lvalue_list = tw.make_lvalue_list (m_lhs); + if (m_rhs) + { + std::list lvalue_list = tw.make_lvalue_list (m_lhs); - unwind_action act ([&tw] (const std::list *lvl) - { - tw.set_lvalue_list (lvl); - }, tw.lvalue_list ()); - tw.set_lvalue_list (&lvalue_list); + unwind_action act ([&tw] (const std::list *lvl) + { + tw.set_lvalue_list (lvl); + }, tw.lvalue_list ()); + tw.set_lvalue_list (&lvalue_list); - octave_idx_type n_out = 0; + octave_idx_type n_out = 0; - for (const auto& lval : lvalue_list) - n_out += lval.numel (); + for (const auto& lval : lvalue_list) + n_out += lval.numel (); - // The following trick is used to keep rhs_val constant. - const octave_value_list rhs_val1 = m_rhs->evaluate_n (tw, n_out); - const octave_value_list rhs_val = (rhs_val1.length () == 1 - && rhs_val1(0).is_cs_list () - ? rhs_val1(0).list_value () - : rhs_val1); + // The following trick is used to keep rhs_val constant. + const octave_value_list rhs_val1 = m_rhs->evaluate_n (tw, n_out); + const octave_value_list rhs_val = (rhs_val1.length () == 1 + && rhs_val1(0).is_cs_list () + ? rhs_val1(0).list_value () + : rhs_val1); - tw.set_lvalue_list (nullptr); + tw.set_lvalue_list (nullptr); - octave_idx_type k = 0; + octave_idx_type k = 0; - octave_idx_type n = rhs_val.length (); + octave_idx_type n = rhs_val.length (); - // To avoid copying per elements and possible optimizations, we - // postpone joining the final values. - std::list retval_list; + // To avoid copying per elements and possible optimizations, we + // postpone joining the final values. + std::list retval_list; - auto q = m_lhs->begin (); + auto q = m_lhs->begin (); - for (octave_lvalue ult : lvalue_list) - { - tree_expression *lhs_elt = *q++; + for (octave_lvalue ult : lvalue_list) + { + tree_expression *lhs_elt = *q++; - octave_idx_type nel = ult.numel (); + octave_idx_type nel = ult.numel (); - if (nel != 1) - { - // Huge kluge so that wrapper scripts with lines like - // - // [varargout{1:nargout}] = fcn (args); - // - // or - // - // varargout = cell (1, nargout); - // [varargout{1:nargout}] = fcn (args); - // - // or - // - // varargout = cell (1, nargout); - // [varargout{:}] = fcn (args); - // - // Will work the same as calling fcn directly when nargout - // is 0 and fcn produces more than one output even when - // nargout is 0. See also bug #43813. + if (nel != 1) + { + // Huge kluge so that wrapper scripts with lines like + // + // [varargout{1:nargout}] = fcn (args); + // + // or + // + // varargout = cell (1, nargout); + // [varargout{1:nargout}] = fcn (args); + // + // or + // + // varargout = cell (1, nargout); + // [varargout{:}] = fcn (args); + // + // Will work the same as calling fcn directly when nargout + // is 0 and fcn produces more than one output even when + // nargout is 0. See also bug #43813. - if (lvalue_list.size () == 1 && nel == 0 && n > 0 - && ! ult.is_black_hole () && ult.index_type () == "{" - && (ult.index_is_empty () - || (ult.is_defined () && ult.index_is_colon ()))) - { - // Convert undefined lvalue with empty index to a cell - // array with a single value and indexed by 1 to - // handle a single output. + if (lvalue_list.size () == 1 && nel == 0 && n > 0 + && ! ult.is_black_hole () && ult.index_type () == "{" + && (ult.index_is_empty () + || (ult.is_defined () && ult.index_is_colon ()))) + { + // Convert undefined lvalue with empty index to a cell + // array with a single value and indexed by 1 to + // handle a single output. - nel = 1; + nel = 1; - ult.define (Cell (1, 1)); + ult.define (Cell (1, 1)); - ult.clear_index (); - std::list idx; - idx.push_back (octave_value_list (octave_value (1))); - ult.set_index ("{", idx); - } + ult.clear_index (); + std::list idx; + idx.push_back (octave_value_list (octave_value (1))); + ult.set_index ("{", idx); + } - if (k + nel > n) - error ("some elements undefined in return list"); + if (k + nel > n) + error ("some elements undefined in return list"); - // This element of the return list expects a - // comma-separated list of values. Slicing avoids - // copying. + // This element of the return list expects a + // comma-separated list of values. Slicing avoids + // copying. - octave_value_list ovl = rhs_val.slice (k, nel); + octave_value_list ovl = rhs_val.slice (k, nel); - ult.assign (octave_value::op_asn_eq, octave_value (ovl)); + ult.assign (octave_value::op_asn_eq, octave_value (ovl)); - retval_list.push_back (ovl); + retval_list.push_back (ovl); - k += nel; - } - else - { - if (k < n) - { - if (ult.is_black_hole ()) - { - k++; - continue; - } - else - { - octave_value tmp = rhs_val(k); + k += nel; + } + else + { + if (k < n) + { + if (ult.is_black_hole ()) + { + k++; + continue; + } + else + { + octave_value tmp = rhs_val(k); - if (tmp.is_undefined ()) - error ("element number %" OCTAVE_IDX_TYPE_FORMAT - " undefined in return list", k+1); + if (tmp.is_undefined ()) + error ("element number %" OCTAVE_IDX_TYPE_FORMAT + " undefined in return list", k+1); - ult.assign (octave_value::op_asn_eq, tmp); + ult.assign (octave_value::op_asn_eq, tmp); - retval_list.push_back (tmp); + retval_list.push_back (tmp); - k++; - } - } - else - { - // This can happen for a function like - // - // function varargout = f () - // varargout{1} = nargout; - // endfunction - // - // called with - // - // [a, ~] = f (); - // - // Then the list of of RHS values will contain one - // element but we are iterating over the list of all - // RHS values. We shouldn't complain that a value we - // don't need is missing from the list. + k++; + } + } + else + { + // This can happen for a function like + // + // function varargout = f () + // varargout{1} = nargout; + // endfunction + // + // called with + // + // [a, ~] = f (); + // + // Then the list of of RHS values will contain one + // element but we are iterating over the list of all + // RHS values. We shouldn't complain that a value we + // don't need is missing from the list. - if (! ult.is_black_hole ()) - error ("element number %" OCTAVE_IDX_TYPE_FORMAT - " undefined in return list", k+1); + if (! ult.is_black_hole ()) + error ("element number %" OCTAVE_IDX_TYPE_FORMAT + " undefined in return list", k+1); - k++; - continue; - } - } + k++; + continue; + } + } - if (print_result () && tw.statement_printing_enabled ()) - { - // We clear any index here so that we can get - // the new value of the referenced object below, - // instead of the indexed value (which should be - // the same as the right hand side value). + if (print_result () && tw.statement_printing_enabled ()) + { + // We clear any index here so that we can get + // the new value of the referenced object below, + // instead of the indexed value (which should be + // the same as the right hand side value). - ult.clear_index (); + ult.clear_index (); - octave_value lhs_val = ult.value (); + octave_value lhs_val = ult.value (); - octave_value_list args = ovl (lhs_val); - args.stash_name_tags (string_vector (lhs_elt->name ())); - feval ("display", args); - } - } + octave_value_list args = ovl (lhs_val); + args.stash_name_tags (string_vector (lhs_elt->name ())); + feval ("display", args); + } + } - // Concatenate return values. - val = retval_list; - } + // Concatenate return values. + val = retval_list; + } - return val; - } + return val; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-assign.h --- a/libinterp/parse-tree/pt-assign.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-assign.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,147 +40,147 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class octave_lvalue; - class tree_argument_list; +class symbol_scope; +class octave_lvalue; +class tree_argument_list; - // Simple assignment expressions. +// Simple assignment expressions. - class tree_simple_assignment : public tree_expression - { - public: +class tree_simple_assignment : public tree_expression +{ +public: - tree_simple_assignment (bool plhs = false, int l = -1, int c = -1, - octave_value::assign_op t = octave_value::op_asn_eq) - : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), - m_preserve (plhs), m_ans_assign (), m_etype (t) - { } + tree_simple_assignment (bool plhs = false, int l = -1, int c = -1, + octave_value::assign_op t = octave_value::op_asn_eq) + : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), + m_preserve (plhs), m_ans_assign (), m_etype (t) + { } - tree_simple_assignment (tree_expression *le, tree_expression *re, - bool plhs = false, int l = -1, int c = -1, - octave_value::assign_op t = octave_value::op_asn_eq); + tree_simple_assignment (tree_expression *le, tree_expression *re, + bool plhs = false, int l = -1, int c = -1, + octave_value::assign_op t = octave_value::op_asn_eq); - // No copying! + // No copying! - tree_simple_assignment (const tree_simple_assignment&) = delete; + tree_simple_assignment (const tree_simple_assignment&) = delete; - tree_simple_assignment& operator = (const tree_simple_assignment&) = delete; + tree_simple_assignment& operator = (const tree_simple_assignment&) = delete; - ~tree_simple_assignment (void); + ~tree_simple_assignment (void); - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - bool is_assignment_expression (void) const { return true; } + bool is_assignment_expression (void) const { return true; } - std::string oper (void) const; + std::string oper (void) const; - tree_expression * left_hand_side (void) { return m_lhs; } + tree_expression * left_hand_side (void) { return m_lhs; } - tree_expression * right_hand_side (void) { return m_rhs; } + tree_expression * right_hand_side (void) { return m_rhs; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator& tw, int nargout = 1); + octave_value evaluate (tree_evaluator& tw, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) - { - tw.visit_simple_assignment (*this); - } + void accept (tree_walker& tw) + { + tw.visit_simple_assignment (*this); + } - octave_value::assign_op op_type (void) const { return m_etype; } + octave_value::assign_op op_type (void) const { return m_etype; } - private: +private: - void do_assign (octave_lvalue& ult, const octave_value_list& args, - const octave_value& rhs_val); + void do_assign (octave_lvalue& ult, const octave_value_list& args, + const octave_value& rhs_val); - void do_assign (octave_lvalue& ult, const octave_value& rhs_val); + void do_assign (octave_lvalue& ult, const octave_value& rhs_val); - // The left hand side of the assignment. - tree_expression *m_lhs; + // The left hand side of the assignment. + tree_expression *m_lhs; - // The right hand side of the assignment. - tree_expression *m_rhs; + // The right hand side of the assignment. + tree_expression *m_rhs; - // True if we should not delete the lhs. - bool m_preserve; + // True if we should not delete the lhs. + bool m_preserve; - // True if this is an assignment to the automatic variable ans. - bool m_ans_assign; + // True if this is an assignment to the automatic variable ans. + bool m_ans_assign; - // The type of the expression. - octave_value::assign_op m_etype; - }; + // The type of the expression. + octave_value::assign_op m_etype; +}; - // Multi-valued assignment expressions. +// Multi-valued assignment expressions. - class tree_multi_assignment : public tree_expression - { - public: +class tree_multi_assignment : public tree_expression +{ +public: - tree_multi_assignment (bool plhs = false, int l = -1, int c = -1) - : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), - m_preserve (plhs) - { } + tree_multi_assignment (bool plhs = false, int l = -1, int c = -1) + : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), + m_preserve (plhs) + { } - tree_multi_assignment (tree_argument_list *lst, tree_expression *r, - bool plhs = false, int l = -1, int c = -1); + tree_multi_assignment (tree_argument_list *lst, tree_expression *r, + bool plhs = false, int l = -1, int c = -1); - // No copying! + // No copying! - tree_multi_assignment (const tree_multi_assignment&) = delete; + tree_multi_assignment (const tree_multi_assignment&) = delete; - tree_multi_assignment& operator = (const tree_multi_assignment&) = delete; + tree_multi_assignment& operator = (const tree_multi_assignment&) = delete; - ~tree_multi_assignment (void); + ~tree_multi_assignment (void); - bool is_assignment_expression (void) const { return true; } + bool is_assignment_expression (void) const { return true; } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - std::string oper (void) const; + std::string oper (void) const; - tree_argument_list * left_hand_side (void) { return m_lhs; } + tree_argument_list * left_hand_side (void) { return m_lhs; } - tree_expression * right_hand_side (void) { return m_rhs; } + tree_expression * right_hand_side (void) { return m_rhs; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator& tw, int nargout = 1) - { - octave_value_list retval = evaluate_n (tw, nargout); + octave_value evaluate (tree_evaluator& tw, int nargout = 1) + { + octave_value_list retval = evaluate_n (tw, nargout); - return retval.length () > 0 ? retval(0) : octave_value (); - } + return retval.length () > 0 ? retval(0) : octave_value (); + } - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); - void accept (tree_walker& tw) - { - tw.visit_multi_assignment (*this); - } + void accept (tree_walker& tw) + { + tw.visit_multi_assignment (*this); + } - octave_value::assign_op op_type (void) const - { - return octave_value::op_asn_eq; - } + octave_value::assign_op op_type (void) const + { + return octave_value::op_asn_eq; + } - private: +private: - // The left hand side of the assignment. - tree_argument_list *m_lhs; + // The left hand side of the assignment. + tree_argument_list *m_lhs; - // The right hand side of the assignment. - tree_expression *m_rhs; + // The right hand side of the assignment. + tree_expression *m_rhs; - // True if we should not delete the lhs. - bool m_preserve; - }; + // True if we should not delete the lhs. + bool m_preserve; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-binop.cc --- a/libinterp/parse-tree/pt-binop.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-binop.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,207 +37,207 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Binary expressions. +// Binary expressions. - void - tree_binary_expression::matlab_style_short_circuit_warning (const char *op) - { - warning_with_id ("Octave:possible-matlab-short-circuit-operator", - "Matlab-style short-circuit operation performed for operator %s", - op); - } +void +tree_binary_expression::matlab_style_short_circuit_warning (const char *op) +{ + warning_with_id ("Octave:possible-matlab-short-circuit-operator", + "Matlab-style short-circuit operation performed for operator %s", + op); +} - std::string - tree_binary_expression::oper (void) const - { - return octave_value::binary_op_as_string (m_etype); - } +std::string +tree_binary_expression::oper (void) const +{ + return octave_value::binary_op_as_string (m_etype); +} - tree_expression * - tree_binary_expression::dup (symbol_scope& scope) const - { - tree_binary_expression *new_be - = new tree_binary_expression (m_lhs ? m_lhs->dup (scope) : nullptr, - m_rhs ? m_rhs->dup (scope) : nullptr, - line (), column (), m_etype); +tree_expression * +tree_binary_expression::dup (symbol_scope& scope) const +{ + tree_binary_expression *new_be + = new tree_binary_expression (m_lhs ? m_lhs->dup (scope) : nullptr, + m_rhs ? m_rhs->dup (scope) : nullptr, + line (), column (), m_etype); - new_be->copy_base (*this); + new_be->copy_base (*this); - return new_be; - } + return new_be; +} - octave_value - tree_binary_expression::evaluate (tree_evaluator& tw, int) - { - if (m_lhs) - { - octave_value a = m_lhs->evaluate (tw); +octave_value +tree_binary_expression::evaluate (tree_evaluator& tw, int) +{ + if (m_lhs) + { + octave_value a = m_lhs->evaluate (tw); - if (a.is_defined () && m_rhs) - { - octave_value b = m_rhs->evaluate (tw); + if (a.is_defined () && m_rhs) + { + octave_value b = m_rhs->evaluate (tw); - if (b.is_defined ()) - { - profiler::enter - block (tw.get_profiler (), *this); + if (b.is_defined ()) + { + profiler::enter + block (tw.get_profiler (), *this); - // Note: The profiler does not catch the braindead - // short-circuit evaluation code above, but that should be - // ok. The evaluation of operands and the operator itself - // is entangled and it's not clear where to start/stop - // timing the operator to make it reasonable. + // Note: The profiler does not catch the braindead + // short-circuit evaluation code above, but that should be + // ok. The evaluation of operands and the operator itself + // is entangled and it's not clear where to start/stop + // timing the operator to make it reasonable. - interpreter& interp = tw.get_interpreter (); + interpreter& interp = tw.get_interpreter (); - type_info& ti = interp.get_type_info (); + type_info& ti = interp.get_type_info (); - return binary_op (ti, m_etype, a, b); - } - } - } + return binary_op (ti, m_etype, a, b); + } + } + } - return octave_value (); - } + return octave_value (); +} - tree_expression * - tree_braindead_shortcircuit_binary_expression::dup (symbol_scope& scope) const - { - tree_braindead_shortcircuit_binary_expression *new_be - = new tree_braindead_shortcircuit_binary_expression - (m_lhs ? m_lhs->dup (scope) : nullptr, - m_rhs ? m_rhs->dup (scope) : nullptr, - line (), column (), op_type ()); +tree_expression * +tree_braindead_shortcircuit_binary_expression::dup (symbol_scope& scope) const +{ + tree_braindead_shortcircuit_binary_expression *new_be + = new tree_braindead_shortcircuit_binary_expression + (m_lhs ? m_lhs->dup (scope) : nullptr, + m_rhs ? m_rhs->dup (scope) : nullptr, + line (), column (), op_type ()); - new_be->copy_base (*this); + new_be->copy_base (*this); - return new_be; - } + return new_be; +} - octave_value - tree_braindead_shortcircuit_binary_expression::evaluate (tree_evaluator& tw, - int) - { - if (m_lhs) - { - octave_value a = m_lhs->evaluate (tw); +octave_value +tree_braindead_shortcircuit_binary_expression::evaluate (tree_evaluator& tw, + int) +{ + if (m_lhs) + { + octave_value a = m_lhs->evaluate (tw); - if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1) - { - bool result = false; + if (a.ndims () == 2 && a.rows () == 1 && a.columns () == 1) + { + bool result = false; - bool a_true = a.is_true (); + bool a_true = a.is_true (); - octave_value::binary_op oper_type = op_type (); + octave_value::binary_op oper_type = op_type (); - if (a_true) - { - if (oper_type == octave_value::op_el_or) - { - matlab_style_short_circuit_warning ("|"); - return octave_value (true); - } - } - else - { - if (oper_type == octave_value::op_el_and) - { - matlab_style_short_circuit_warning ("&"); - return octave_value (false); - } - } + if (a_true) + { + if (oper_type == octave_value::op_el_or) + { + matlab_style_short_circuit_warning ("|"); + return octave_value (true); + } + } + else + { + if (oper_type == octave_value::op_el_and) + { + matlab_style_short_circuit_warning ("&"); + return octave_value (false); + } + } - if (m_rhs) - { - octave_value b = m_rhs->evaluate (tw); + if (m_rhs) + { + octave_value b = m_rhs->evaluate (tw); - result = b.is_true (); - } + result = b.is_true (); + } - return octave_value (result); - } - } + return octave_value (result); + } + } - return octave_value (); - } + return octave_value (); +} - // Boolean expressions. +// Boolean expressions. - std::string - tree_boolean_expression::oper (void) const - { - std::string retval = ""; +std::string +tree_boolean_expression::oper (void) const +{ + std::string retval = ""; - switch (m_etype) - { - case bool_and: - retval = "&&"; - break; + switch (m_etype) + { + case bool_and: + retval = "&&"; + break; - case bool_or: - retval = "||"; - break; + case bool_or: + retval = "||"; + break; - default: - break; - } + default: + break; + } - return retval; - } + return retval; +} - tree_expression * - tree_boolean_expression::dup (symbol_scope& scope) const - { - tree_boolean_expression *new_be - = new tree_boolean_expression (m_lhs ? m_lhs->dup (scope) : nullptr, - m_rhs ? m_rhs->dup (scope) : nullptr, - line (), column (), m_etype); +tree_expression * +tree_boolean_expression::dup (symbol_scope& scope) const +{ + tree_boolean_expression *new_be + = new tree_boolean_expression (m_lhs ? m_lhs->dup (scope) : nullptr, + m_rhs ? m_rhs->dup (scope) : nullptr, + line (), column (), m_etype); - new_be->copy_base (*this); + new_be->copy_base (*this); - return new_be; - } + return new_be; +} - octave_value - tree_boolean_expression::evaluate (tree_evaluator& tw, int) - { - octave_value val; +octave_value +tree_boolean_expression::evaluate (tree_evaluator& tw, int) +{ + octave_value val; - bool result = false; + bool result = false; - // This evaluation is not caught by the profiler, since we can't find - // a reasonable place where to time. Note that we don't want to - // include evaluation of LHS or RHS into the timing, but this is - // entangled together with short-circuit evaluation here. + // This evaluation is not caught by the profiler, since we can't find + // a reasonable place where to time. Note that we don't want to + // include evaluation of LHS or RHS into the timing, but this is + // entangled together with short-circuit evaluation here. - if (m_lhs) - { - octave_value a = m_lhs->evaluate (tw); + if (m_lhs) + { + octave_value a = m_lhs->evaluate (tw); - bool a_true = a.is_true (); + bool a_true = a.is_true (); - if (a_true) - { - if (m_etype == tree_boolean_expression::bool_or) - return octave_value (true); - } - else - { - if (m_etype == tree_boolean_expression::bool_and) - return octave_value (false); - } + if (a_true) + { + if (m_etype == tree_boolean_expression::bool_or) + return octave_value (true); + } + else + { + if (m_etype == tree_boolean_expression::bool_and) + return octave_value (false); + } - if (m_rhs) - { - octave_value b = m_rhs->evaluate (tw); + if (m_rhs) + { + octave_value b = m_rhs->evaluate (tw); - result = b.is_true (); - } + result = b.is_true (); + } - val = octave_value (result); - } + val = octave_value (result); + } - return val; - } + return val; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-binop.h --- a/libinterp/parse-tree/pt-binop.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-binop.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,174 +39,174 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; +class symbol_scope; + +// Binary expressions. - // Binary expressions. +class tree_binary_expression : public tree_expression +{ +public: - class tree_binary_expression : public tree_expression - { - public: + tree_binary_expression (int l = -1, int c = -1, + octave_value::binary_op t + = octave_value::unknown_binary_op) + : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), m_etype (t), + m_preserve_operands (false) + { } - tree_binary_expression (int l = -1, int c = -1, - octave_value::binary_op t - = octave_value::unknown_binary_op) - : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), m_etype (t), - m_preserve_operands (false) - { } + tree_binary_expression (tree_expression *a, tree_expression *b, + int l = -1, int c = -1, + octave_value::binary_op t + = octave_value::unknown_binary_op) + : tree_expression (l, c), m_lhs (a), m_rhs (b), m_etype (t), + m_preserve_operands (false) + { } + + // No copying! + + tree_binary_expression (const tree_binary_expression&) = delete; + + tree_binary_expression& operator = (const tree_binary_expression&) = delete; - tree_binary_expression (tree_expression *a, tree_expression *b, - int l = -1, int c = -1, - octave_value::binary_op t - = octave_value::unknown_binary_op) - : tree_expression (l, c), m_lhs (a), m_rhs (b), m_etype (t), - m_preserve_operands (false) - { } + ~tree_binary_expression (void) + { + if (! m_preserve_operands) + { + delete m_lhs; + delete m_rhs; + } + } - // No copying! + void preserve_operands (void) { m_preserve_operands = true; } - tree_binary_expression (const tree_binary_expression&) = delete; + bool is_binary_expression (void) const { return true; } + + bool rvalue_ok (void) const { return true; } - tree_binary_expression& operator = (const tree_binary_expression&) = delete; + std::string oper (void) const; + + octave_value::binary_op op_type (void) const { return m_etype; } + + tree_expression * lhs (void) { return m_lhs; } + tree_expression * rhs (void) { return m_rhs; } - ~tree_binary_expression (void) - { - if (! m_preserve_operands) - { - delete m_lhs; - delete m_rhs; - } - } + tree_expression * dup (symbol_scope& scope) const; + + octave_value evaluate (tree_evaluator&, int nargout = 1); - void preserve_operands (void) { m_preserve_operands = true; } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - bool is_binary_expression (void) const { return true; } - - bool rvalue_ok (void) const { return true; } + void accept (tree_walker& tw) + { + tw.visit_binary_expression (*this); + } - std::string oper (void) const; + std::string profiler_name (void) const { return "binary " + oper (); } - octave_value::binary_op op_type (void) const { return m_etype; } + void matlab_style_short_circuit_warning (const char *op); + +protected: - tree_expression * lhs (void) { return m_lhs; } - tree_expression * rhs (void) { return m_rhs; } + // The operands for the expression. + tree_expression *m_lhs; + tree_expression *m_rhs; - tree_expression * dup (symbol_scope& scope) const; +private: + + // The type of the expression. + octave_value::binary_op m_etype; - octave_value evaluate (tree_evaluator&, int nargout = 1); + // If TRUE, don't delete m_lhs and m_rhs in destructor; + bool m_preserve_operands; +}; - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } +class tree_braindead_shortcircuit_binary_expression + : public tree_binary_expression +{ +public: - void accept (tree_walker& tw) - { - tw.visit_binary_expression (*this); - } + tree_braindead_shortcircuit_binary_expression (tree_expression *a, + tree_expression *b, + int l, int c, + octave_value::binary_op t) + : tree_binary_expression (a, b, l, c, t) + { } - std::string profiler_name (void) const { return "binary " + oper (); } + // No copying! + + tree_braindead_shortcircuit_binary_expression + (const tree_braindead_shortcircuit_binary_expression&) = delete; - void matlab_style_short_circuit_warning (const char *op); + tree_braindead_shortcircuit_binary_expression& + operator = (const tree_braindead_shortcircuit_binary_expression&) = delete; - protected: + ~tree_braindead_shortcircuit_binary_expression (void) = default; - // The operands for the expression. - tree_expression *m_lhs; - tree_expression *m_rhs; + tree_expression * dup (symbol_scope& scope) const; + + octave_value evaluate (tree_evaluator&, int nargout = 1); - private: + using tree_binary_expression::evaluate_n; +}; + +// Boolean expressions. - // The type of the expression. - octave_value::binary_op m_etype; +class tree_boolean_expression : public tree_binary_expression +{ +public: - // If TRUE, don't delete m_lhs and m_rhs in destructor; - bool m_preserve_operands; + enum type + { + unknown, + bool_and, + bool_or }; - class tree_braindead_shortcircuit_binary_expression - : public tree_binary_expression - { - public: + tree_boolean_expression (int l = -1, int c = -1, type t = unknown) + : tree_binary_expression (l, c), m_etype (t) { } - tree_braindead_shortcircuit_binary_expression (tree_expression *a, - tree_expression *b, - int l, int c, - octave_value::binary_op t) - : tree_binary_expression (a, b, l, c, t) - { } + tree_boolean_expression (tree_expression *a, tree_expression *b, + int l = -1, int c = -1, type t = unknown) + : tree_binary_expression (a, b, l, c), m_etype (t) { } - // No copying! - - tree_braindead_shortcircuit_binary_expression - (const tree_braindead_shortcircuit_binary_expression&) = delete; - - tree_braindead_shortcircuit_binary_expression& - operator = (const tree_braindead_shortcircuit_binary_expression&) = delete; + // No copying! - ~tree_braindead_shortcircuit_binary_expression (void) = default; - - tree_expression * dup (symbol_scope& scope) const; + tree_boolean_expression (const tree_boolean_expression&) = delete; - octave_value evaluate (tree_evaluator&, int nargout = 1); + tree_boolean_expression& operator = (const tree_boolean_expression&) = delete; - using tree_binary_expression::evaluate_n; - }; - - // Boolean expressions. + ~tree_boolean_expression (void) = default; - class tree_boolean_expression : public tree_binary_expression - { - public: + bool is_boolean_expression (void) const { return true; } - enum type - { - unknown, - bool_and, - bool_or - }; + bool rvalue_ok (void) const { return true; } + + std::string oper (void) const; - tree_boolean_expression (int l = -1, int c = -1, type t = unknown) - : tree_binary_expression (l, c), m_etype (t) { } + type op_type (void) const { return m_etype; } - tree_boolean_expression (tree_expression *a, tree_expression *b, - int l = -1, int c = -1, type t = unknown) - : tree_binary_expression (a, b, l, c), m_etype (t) { } - - // No copying! + tree_expression * dup (symbol_scope& scope) const; - tree_boolean_expression (const tree_boolean_expression&) = delete; - - tree_boolean_expression& operator = (const tree_boolean_expression&) = delete; - - ~tree_boolean_expression (void) = default; + octave_value evaluate (tree_evaluator&, int nargout = 1); - bool is_boolean_expression (void) const { return true; } - - bool rvalue_ok (void) const { return true; } - - std::string oper (void) const; + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - type op_type (void) const { return m_etype; } - - tree_expression * dup (symbol_scope& scope) const; - - octave_value evaluate (tree_evaluator&, int nargout = 1); - - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + void accept (tree_walker& tw) + { + tw.visit_boolean_expression (*this); + } - void accept (tree_walker& tw) - { - tw.visit_boolean_expression (*this); - } +private: - private: - - // The type of the expression. - type m_etype; - }; + // The type of the expression. + type m_etype; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-bp.cc --- a/libinterp/parse-tree/pt-bp.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-bp.cc Thu Dec 01 20:05:44 2022 -0800 @@ -33,449 +33,449 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - tree_breakpoint::visit_while_command (tree_while_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); +void +tree_breakpoint::visit_while_command (tree_while_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); - if (! m_found) - { - tree_statement_list *lst = cmd.body (); + if (! m_found) + { + tree_statement_list *lst = cmd.body (); - if (lst) - lst->accept (*this); - } - } + if (lst) + lst->accept (*this); + } +} - void - tree_breakpoint::visit_do_until_command (tree_do_until_command& cmd) - { - if (! m_found) - { - tree_statement_list *lst = cmd.body (); +void +tree_breakpoint::visit_do_until_command (tree_do_until_command& cmd) +{ + if (! m_found) + { + tree_statement_list *lst = cmd.body (); - if (lst) - lst->accept (*this); + if (lst) + lst->accept (*this); - if (! m_found) - { - if (cmd.line () >= m_line) - take_action (cmd); - } - } - } + if (! m_found) + { + if (cmd.line () >= m_line) + take_action (cmd); + } + } +} - void - tree_breakpoint::visit_argument_list (tree_argument_list&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_argument_list (tree_argument_list&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_arguments_block (tree_arguments_block&) - { - // FIXME - } +void +tree_breakpoint::visit_arguments_block (tree_arguments_block&) +{ + // FIXME +} - void - tree_breakpoint::visit_args_block_attribute_list (tree_args_block_attribute_list&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_args_block_attribute_list (tree_args_block_attribute_list&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_args_block_validation_list (tree_args_block_validation_list&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_args_block_validation_list (tree_args_block_validation_list&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_arg_validation (tree_arg_validation&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_arg_validation (tree_arg_validation&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_arg_size_spec (tree_arg_size_spec&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_arg_size_spec (tree_arg_size_spec&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_arg_validation_fcns (tree_arg_validation_fcns&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_arg_validation_fcns (tree_arg_validation_fcns&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_binary_expression (tree_binary_expression&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_binary_expression (tree_binary_expression&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_break_command (tree_break_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); - } +void +tree_breakpoint::visit_break_command (tree_break_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); +} - void - tree_breakpoint::visit_colon_expression (tree_colon_expression&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_colon_expression (tree_colon_expression&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_continue_command (tree_continue_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); - } +void +tree_breakpoint::visit_continue_command (tree_continue_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); +} - void - tree_breakpoint::visit_decl_command (tree_decl_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); - } +void +tree_breakpoint::visit_decl_command (tree_decl_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); +} - void - tree_breakpoint::visit_decl_init_list (tree_decl_init_list&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_decl_init_list (tree_decl_init_list&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_decl_elt (tree_decl_elt&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_decl_elt (tree_decl_elt&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_simple_for_command (tree_simple_for_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); +void +tree_breakpoint::visit_simple_for_command (tree_simple_for_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); - if (! m_found) - { - tree_statement_list *lst = cmd.body (); + if (! m_found) + { + tree_statement_list *lst = cmd.body (); - if (lst) - lst->accept (*this); - } - } + if (lst) + lst->accept (*this); + } +} - void - tree_breakpoint::visit_complex_for_command (tree_complex_for_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); +void +tree_breakpoint::visit_complex_for_command (tree_complex_for_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); - if (! m_found) - { - tree_statement_list *lst = cmd.body (); + if (! m_found) + { + tree_statement_list *lst = cmd.body (); - if (lst) - lst->accept (*this); - } - } + if (lst) + lst->accept (*this); + } +} - void - tree_breakpoint::visit_octave_user_function_header (octave_user_function&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_octave_user_function_header (octave_user_function&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_octave_user_function_trailer (octave_user_function&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_octave_user_function_trailer (octave_user_function&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_identifier (tree_identifier&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_identifier (tree_identifier&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_if_clause (tree_if_clause&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_if_clause (tree_if_clause&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_if_command_list (tree_if_command_list& lst) - { - for (tree_if_clause *t : lst) - { - if (t->line () >= m_line) - take_action (*t); +void +tree_breakpoint::visit_if_command_list (tree_if_command_list& lst) +{ + for (tree_if_clause *t : lst) + { + if (t->line () >= m_line) + take_action (*t); - if (! m_found) - { - tree_statement_list *stmt_lst = t->commands (); + if (! m_found) + { + tree_statement_list *stmt_lst = t->commands (); - if (stmt_lst) - stmt_lst->accept (*this); - } + if (stmt_lst) + stmt_lst->accept (*this); + } - if (m_found) - break; - } - } + if (m_found) + break; + } +} - void - tree_breakpoint::visit_index_expression (tree_index_expression&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_index_expression (tree_index_expression&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_matrix (tree_matrix&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_matrix (tree_matrix&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_cell (tree_cell&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_cell (tree_cell&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_multi_assignment (tree_multi_assignment&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_multi_assignment (tree_multi_assignment&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_no_op_command (tree_no_op_command& cmd) - { - if (cmd.is_end_of_fcn_or_script () && cmd.line () >= m_line) - take_action (cmd); - } +void +tree_breakpoint::visit_no_op_command (tree_no_op_command& cmd) +{ + if (cmd.is_end_of_fcn_or_script () && cmd.line () >= m_line) + take_action (cmd); +} - void - tree_breakpoint::visit_anon_fcn_handle (tree_anon_fcn_handle&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_anon_fcn_handle (tree_anon_fcn_handle&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_constant (tree_constant&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_constant (tree_constant&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_fcn_handle (tree_fcn_handle&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_fcn_handle (tree_fcn_handle&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_parameter_list (tree_parameter_list&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_parameter_list (tree_parameter_list&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_postfix_expression (tree_postfix_expression&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_postfix_expression (tree_postfix_expression&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_prefix_expression (tree_prefix_expression&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_prefix_expression (tree_prefix_expression&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_return_command (tree_return_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); - } +void +tree_breakpoint::visit_return_command (tree_return_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); +} - void - tree_breakpoint::visit_simple_assignment (tree_simple_assignment&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_simple_assignment (tree_simple_assignment&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_statement (tree_statement& stmt) - { - if (stmt.is_command ()) - { - tree_command *cmd = stmt.command (); +void +tree_breakpoint::visit_statement (tree_statement& stmt) +{ + if (stmt.is_command ()) + { + tree_command *cmd = stmt.command (); - cmd->accept (*this); - } - else - { - if (stmt.line () >= m_line) - take_action (stmt); - } - } + cmd->accept (*this); + } + else + { + if (stmt.line () >= m_line) + take_action (stmt); + } +} - // Called by - // tree_statement_list::set_breakpoint (int line, std::string& condition) - // with consisting of a user function in which to set a breakpoint. - void - tree_breakpoint::visit_statement_list (tree_statement_list& lst) - { - for (tree_statement *elt : lst) - { - if (elt) - { - elt->accept (*this); +// Called by +// tree_statement_list::set_breakpoint (int line, std::string& condition) +// with consisting of a user function in which to set a breakpoint. +void +tree_breakpoint::visit_statement_list (tree_statement_list& lst) +{ + for (tree_statement *elt : lst) + { + if (elt) + { + elt->accept (*this); - if (m_found) - break; - } - } - } + if (m_found) + break; + } + } +} - void - tree_breakpoint::visit_switch_case (tree_switch_case&) - { - panic_impossible (); - } +void +tree_breakpoint::visit_switch_case (tree_switch_case&) +{ + panic_impossible (); +} - void - tree_breakpoint::visit_switch_case_list (tree_switch_case_list& lst) - { - for (tree_switch_case *t : lst) - { - if (t->line () >= m_line) - take_action (*t); +void +tree_breakpoint::visit_switch_case_list (tree_switch_case_list& lst) +{ + for (tree_switch_case *t : lst) + { + if (t->line () >= m_line) + take_action (*t); - if (! m_found) - { - tree_statement_list *stmt_lst = t->commands (); + if (! m_found) + { + tree_statement_list *stmt_lst = t->commands (); - if (stmt_lst) - stmt_lst->accept (*this); - } + if (stmt_lst) + stmt_lst->accept (*this); + } - if (m_found) - break; - } - } + if (m_found) + break; + } +} - void - tree_breakpoint::visit_switch_command (tree_switch_command& cmd) - { - if (cmd.line () >= m_line) - take_action (cmd); +void +tree_breakpoint::visit_switch_command (tree_switch_command& cmd) +{ + if (cmd.line () >= m_line) + take_action (cmd); - if (! m_found) - { - tree_switch_case_list *lst = cmd.case_list (); + if (! m_found) + { + tree_switch_case_list *lst = cmd.case_list (); - if (lst) - lst->accept (*this); - } - } + if (lst) + lst->accept (*this); + } +} - void - tree_breakpoint::visit_try_catch_command (tree_try_catch_command& cmd) - { - tree_statement_list *try_code = cmd.body (); +void +tree_breakpoint::visit_try_catch_command (tree_try_catch_command& cmd) +{ + tree_statement_list *try_code = cmd.body (); - if (try_code) - try_code->accept (*this); + if (try_code) + try_code->accept (*this); - if (! m_found) - { - tree_statement_list *catch_code = cmd.cleanup (); + if (! m_found) + { + tree_statement_list *catch_code = cmd.cleanup (); - if (catch_code) - catch_code->accept (*this); - } - } + if (catch_code) + catch_code->accept (*this); + } +} - void - tree_breakpoint::visit_unwind_protect_command (tree_unwind_protect_command& cmd) - { - tree_statement_list *body = cmd.body (); +void +tree_breakpoint::visit_unwind_protect_command (tree_unwind_protect_command& cmd) +{ + tree_statement_list *body = cmd.body (); - if (body) - body->accept (*this); + if (body) + body->accept (*this); - if (! m_found) - { - tree_statement_list *cleanup = cmd.cleanup (); + if (! m_found) + { + tree_statement_list *cleanup = cmd.cleanup (); - if (cleanup) - cleanup->accept (*this); - } - } + if (cleanup) + cleanup->accept (*this); + } +} - void - tree_breakpoint::take_action (tree& tr) - { - if (m_action == set) - { - tr.set_breakpoint (m_condition); - m_line = tr.line (); - m_found = true; - } - else if (m_action == clear) - { - if (tr.is_breakpoint ()) - { - tr.delete_breakpoint (); - m_found = true; - } - } - else if (m_action == list) - { - if (tr.is_breakpoint ()) - { - m_bp_list.append (octave_value (tr.line ())); - m_bp_cond_list.append (octave_value (tr.bp_cond ())); - } - } - else - panic_impossible (); - } +void +tree_breakpoint::take_action (tree& tr) +{ + if (m_action == set) + { + tr.set_breakpoint (m_condition); + m_line = tr.line (); + m_found = true; + } + else if (m_action == clear) + { + if (tr.is_breakpoint ()) + { + tr.delete_breakpoint (); + m_found = true; + } + } + else if (m_action == list) + { + if (tr.is_breakpoint ()) + { + m_bp_list.append (octave_value (tr.line ())); + m_bp_cond_list.append (octave_value (tr.bp_cond ())); + } + } + else + panic_impossible (); +} - void - tree_breakpoint::take_action (tree_statement& stmt) - { - int lineno = stmt.line (); +void +tree_breakpoint::take_action (tree_statement& stmt) +{ + int lineno = stmt.line (); - if (m_action == set) - { - stmt.set_breakpoint (m_condition); - m_line = lineno; - m_found = true; - } - else if (m_action == clear) - { - if (stmt.is_breakpoint ()) - { - stmt.delete_breakpoint (); - m_found = true; - } - } - else if (m_action == list) - { - if (stmt.is_breakpoint ()) - { - m_bp_list.append (octave_value (lineno)); - m_bp_cond_list.append (octave_value (stmt.bp_cond ())); - } - } - else - panic_impossible (); - } + if (m_action == set) + { + stmt.set_breakpoint (m_condition); + m_line = lineno; + m_found = true; + } + else if (m_action == clear) + { + if (stmt.is_breakpoint ()) + { + stmt.delete_breakpoint (); + m_found = true; + } + } + else if (m_action == list) + { + if (stmt.is_breakpoint ()) + { + m_bp_list.append (octave_value (lineno)); + m_bp_cond_list.append (octave_value (stmt.bp_cond ())); + } + } + else + panic_impossible (); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-bp.h --- a/libinterp/parse-tree/pt-bp.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-bp.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,147 +36,147 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree; - class tree_decl_command; +class tree; +class tree_decl_command; - class tree_breakpoint : public tree_walker - { - public: +class tree_breakpoint : public tree_walker +{ +public: - enum action { set = 1, clear = 2, list = 3 }; + enum action { set = 1, clear = 2, list = 3 }; - tree_breakpoint (int l, action a, const std::string& c = "") - : m_line (l), m_action (a), m_condition (c), m_found (false), - m_bp_list (), m_bp_cond_list () - { } + tree_breakpoint (int l, action a, const std::string& c = "") + : m_line (l), m_action (a), m_condition (c), m_found (false), + m_bp_list (), m_bp_cond_list () + { } - // No copying! + // No copying! - tree_breakpoint (const tree_breakpoint&) = delete; + tree_breakpoint (const tree_breakpoint&) = delete; - tree_breakpoint& operator = (const tree_breakpoint&) = delete; + tree_breakpoint& operator = (const tree_breakpoint&) = delete; - ~tree_breakpoint (void) = default; + ~tree_breakpoint (void) = default; - bool success (void) const { return m_found; } + bool success (void) const { return m_found; } - void visit_argument_list (tree_argument_list&); + void visit_argument_list (tree_argument_list&); - void visit_arguments_block (tree_arguments_block&); + void visit_arguments_block (tree_arguments_block&); - void visit_args_block_attribute_list (tree_args_block_attribute_list&); + void visit_args_block_attribute_list (tree_args_block_attribute_list&); - void visit_args_block_validation_list (tree_args_block_validation_list&); + void visit_args_block_validation_list (tree_args_block_validation_list&); - void visit_arg_validation (tree_arg_validation&); + void visit_arg_validation (tree_arg_validation&); - void visit_arg_size_spec (tree_arg_size_spec&); + void visit_arg_size_spec (tree_arg_size_spec&); - void visit_arg_validation_fcns (tree_arg_validation_fcns&); + void visit_arg_validation_fcns (tree_arg_validation_fcns&); - void visit_binary_expression (tree_binary_expression&); + void visit_binary_expression (tree_binary_expression&); - void visit_break_command (tree_break_command&); + void visit_break_command (tree_break_command&); - void visit_colon_expression (tree_colon_expression&); + void visit_colon_expression (tree_colon_expression&); - void visit_continue_command (tree_continue_command&); + void visit_continue_command (tree_continue_command&); - void visit_decl_command (tree_decl_command&); + void visit_decl_command (tree_decl_command&); - void visit_decl_init_list (tree_decl_init_list&); + void visit_decl_init_list (tree_decl_init_list&); - void visit_decl_elt (tree_decl_elt&); + void visit_decl_elt (tree_decl_elt&); - void visit_while_command (tree_while_command&); + void visit_while_command (tree_while_command&); - void visit_do_until_command (tree_do_until_command&); + void visit_do_until_command (tree_do_until_command&); - void visit_simple_for_command (tree_simple_for_command&); + void visit_simple_for_command (tree_simple_for_command&); - void visit_complex_for_command (tree_complex_for_command&); + void visit_complex_for_command (tree_complex_for_command&); - void visit_octave_user_function_header (octave_user_function&); + void visit_octave_user_function_header (octave_user_function&); - void visit_octave_user_function_trailer (octave_user_function&); + void visit_octave_user_function_trailer (octave_user_function&); - void visit_identifier (tree_identifier&); + void visit_identifier (tree_identifier&); - void visit_if_clause (tree_if_clause&); + void visit_if_clause (tree_if_clause&); - void visit_if_command_list (tree_if_command_list&); + void visit_if_command_list (tree_if_command_list&); - void visit_index_expression (tree_index_expression&); + void visit_index_expression (tree_index_expression&); - void visit_matrix (tree_matrix&); + void visit_matrix (tree_matrix&); - void visit_cell (tree_cell&); + void visit_cell (tree_cell&); - void visit_multi_assignment (tree_multi_assignment&); + void visit_multi_assignment (tree_multi_assignment&); - void visit_no_op_command (tree_no_op_command&); + void visit_no_op_command (tree_no_op_command&); - void visit_anon_fcn_handle (tree_anon_fcn_handle&); + void visit_anon_fcn_handle (tree_anon_fcn_handle&); - void visit_constant (tree_constant&); + void visit_constant (tree_constant&); - void visit_fcn_handle (tree_fcn_handle&); + void visit_fcn_handle (tree_fcn_handle&); - void visit_parameter_list (tree_parameter_list&); + void visit_parameter_list (tree_parameter_list&); - void visit_postfix_expression (tree_postfix_expression&); + void visit_postfix_expression (tree_postfix_expression&); - void visit_prefix_expression (tree_prefix_expression&); + void visit_prefix_expression (tree_prefix_expression&); - void visit_return_command (tree_return_command&); + void visit_return_command (tree_return_command&); - void visit_simple_assignment (tree_simple_assignment&); + void visit_simple_assignment (tree_simple_assignment&); - void visit_statement (tree_statement&); + void visit_statement (tree_statement&); - void visit_statement_list (tree_statement_list&); + void visit_statement_list (tree_statement_list&); - void visit_switch_case (tree_switch_case&); + void visit_switch_case (tree_switch_case&); - void visit_switch_case_list (tree_switch_case_list&); + void visit_switch_case_list (tree_switch_case_list&); - void visit_switch_command (tree_switch_command&); + void visit_switch_command (tree_switch_command&); - void visit_try_catch_command (tree_try_catch_command&); + void visit_try_catch_command (tree_try_catch_command&); - void visit_unwind_protect_command (tree_unwind_protect_command&); + void visit_unwind_protect_command (tree_unwind_protect_command&); - octave_value_list get_list (void) { return m_bp_list; } + octave_value_list get_list (void) { return m_bp_list; } - octave_value_list get_cond_list (void) { return m_bp_cond_list; } + octave_value_list get_cond_list (void) { return m_bp_cond_list; } - int get_line (void) { return m_found ? m_line : 0; } + int get_line (void) { return m_found ? m_line : 0; } - private: +private: - void take_action (tree& tr); + void take_action (tree& tr); - void take_action (tree_statement& stmt); + void take_action (tree_statement& stmt); - // Statement line number we are looking for. - int m_line; + // Statement line number we are looking for. + int m_line; - // What to do. - action m_action; + // What to do. + action m_action; - // Expression which must be true to break - std::string m_condition; + // Expression which must be true to break + std::string m_condition; - // Have we already found the line? - bool m_found; + // Have we already found the line? + bool m_found; - // List of breakpoint line numbers. - octave_value_list m_bp_list; + // List of breakpoint line numbers. + octave_value_list m_bp_list; - // List of breakpoint conditions. - octave_value_list m_bp_cond_list; - }; + // List of breakpoint conditions. + octave_value_list m_bp_cond_list; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-cbinop.cc --- a/libinterp/parse-tree/pt-cbinop.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-cbinop.cc Thu Dec 01 20:05:44 2022 -0800 @@ -35,208 +35,208 @@ OCTAVE_BEGIN_NAMESPACE(octave) - octave_value - tree_compound_binary_expression::evaluate (tree_evaluator& tw, int) - { - octave_value val; +octave_value +tree_compound_binary_expression::evaluate (tree_evaluator& tw, int) +{ + octave_value val; - if (m_lhs) - { - octave_value a = m_lhs->evaluate (tw); + if (m_lhs) + { + octave_value a = m_lhs->evaluate (tw); - if (a.is_defined () && m_rhs) - { - octave_value b = m_rhs->evaluate (tw); + if (a.is_defined () && m_rhs) + { + octave_value b = m_rhs->evaluate (tw); - if (b.is_defined ()) - { - interpreter& interp = tw.get_interpreter (); + if (b.is_defined ()) + { + interpreter& interp = tw.get_interpreter (); - type_info& ti = interp.get_type_info (); + type_info& ti = interp.get_type_info (); - val = binary_op (ti, m_etype, a, b); - } - } - } + val = binary_op (ti, m_etype, a, b); + } + } + } - return val; - } + return val; +} - typedef tree_expression* tree_expression_ptr_t; +typedef tree_expression *tree_expression_ptr_t; - // If a tree expression is a transpose or hermitian transpose, return - // the argument and corresponding operator. +// If a tree expression is a transpose or hermitian transpose, return +// the argument and corresponding operator. - static octave_value::unary_op - strip_trans_herm (tree_expression_ptr_t& exp) - { - if (exp->is_unary_expression ()) - { - tree_unary_expression *uexp - = dynamic_cast (exp); +static octave_value::unary_op +strip_trans_herm (tree_expression_ptr_t& exp) +{ + if (exp->is_unary_expression ()) + { + tree_unary_expression *uexp + = dynamic_cast (exp); - octave_value::unary_op op = uexp->op_type (); + octave_value::unary_op op = uexp->op_type (); - if (op == octave_value::op_transpose - || op == octave_value::op_hermitian) - exp = uexp->operand (); - else - op = octave_value::unknown_unary_op; + if (op == octave_value::op_transpose + || op == octave_value::op_hermitian) + exp = uexp->operand (); + else + op = octave_value::unknown_unary_op; - return op; - } - else - return octave_value::unknown_unary_op; - } + return op; + } + else + return octave_value::unknown_unary_op; +} #if 0 - // Restore this code if short-circuit behavior can be preserved when needed. - // See bug #54465. +// Restore this code if short-circuit behavior can be preserved when needed. +// See bug #54465. - static octave_value::unary_op - strip_not (tree_expression_ptr_t& exp) - { - if (exp->is_unary_expression ()) - { - tree_unary_expression *uexp - = dynamic_cast (exp); +static octave_value::unary_op +strip_not (tree_expression_ptr_t& exp) +{ + if (exp->is_unary_expression ()) + { + tree_unary_expression *uexp + = dynamic_cast (exp); - octave_value::unary_op op = uexp->op_type (); + octave_value::unary_op op = uexp->op_type (); - if (op == octave_value::op_not) - exp = uexp->operand (); - else - op = octave_value::unknown_unary_op; + if (op == octave_value::op_not) + exp = uexp->operand (); + else + op = octave_value::unknown_unary_op; - return op; - } - else - return octave_value::unknown_unary_op; - } + return op; + } + else + return octave_value::unknown_unary_op; +} #endif - // Possibly convert multiplication to trans_mul, mul_trans, herm_mul, - // or mul_herm. +// Possibly convert multiplication to trans_mul, mul_trans, herm_mul, +// or mul_herm. - static octave_value::compound_binary_op - simplify_mul_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b) - { - octave_value::compound_binary_op retop - = octave_value::unknown_compound_binary_op; +static octave_value::compound_binary_op +simplify_mul_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b) +{ + octave_value::compound_binary_op retop + = octave_value::unknown_compound_binary_op; - octave_value::unary_op opa = strip_trans_herm (a); + octave_value::unary_op opa = strip_trans_herm (a); - if (opa == octave_value::op_hermitian) - retop = octave_value::op_herm_mul; - else if (opa == octave_value::op_transpose) - retop = octave_value::op_trans_mul; - else - { - octave_value::unary_op opb = strip_trans_herm (b); + if (opa == octave_value::op_hermitian) + retop = octave_value::op_herm_mul; + else if (opa == octave_value::op_transpose) + retop = octave_value::op_trans_mul; + else + { + octave_value::unary_op opb = strip_trans_herm (b); - if (opb == octave_value::op_hermitian) - retop = octave_value::op_mul_herm; - else if (opb == octave_value::op_transpose) - retop = octave_value::op_mul_trans; - } + if (opb == octave_value::op_hermitian) + retop = octave_value::op_mul_herm; + else if (opb == octave_value::op_transpose) + retop = octave_value::op_mul_trans; + } - return retop; - } + return retop; +} - // Possibly convert left division to trans_ldiv or herm_ldiv. +// Possibly convert left division to trans_ldiv or herm_ldiv. - static octave_value::compound_binary_op - simplify_ldiv_op (tree_expression_ptr_t& a, tree_expression_ptr_t&) - { - octave_value::compound_binary_op retop - = octave_value::unknown_compound_binary_op; +static octave_value::compound_binary_op +simplify_ldiv_op (tree_expression_ptr_t& a, tree_expression_ptr_t&) +{ + octave_value::compound_binary_op retop + = octave_value::unknown_compound_binary_op; - octave_value::unary_op opa = strip_trans_herm (a); + octave_value::unary_op opa = strip_trans_herm (a); - if (opa == octave_value::op_hermitian) - retop = octave_value::op_herm_ldiv; - else if (opa == octave_value::op_transpose) - retop = octave_value::op_trans_ldiv; + if (opa == octave_value::op_hermitian) + retop = octave_value::op_herm_ldiv; + else if (opa == octave_value::op_transpose) + retop = octave_value::op_trans_ldiv; - return retop; - } + return retop; +} - // Possibly contract and/or with negation. +// Possibly contract and/or with negation. #if 0 - // Restore this code if short-circuit behavior can be preserved when needed. - // See bug #54465. - static octave_value::compound_binary_op - simplify_and_or_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b, - octave_value::binary_op op) - { - octave_value::compound_binary_op retop - = octave_value::unknown_compound_binary_op; +// Restore this code if short-circuit behavior can be preserved when needed. +// See bug #54465. +static octave_value::compound_binary_op +simplify_and_or_op (tree_expression_ptr_t& a, tree_expression_ptr_t& b, + octave_value::binary_op op) +{ + octave_value::compound_binary_op retop + = octave_value::unknown_compound_binary_op; - octave_value::unary_op opa = strip_not (a); + octave_value::unary_op opa = strip_not (a); - if (opa == octave_value::op_not) - { - if (op == octave_value::op_el_and) - retop = octave_value::op_el_not_and; - else if (op == octave_value::op_el_or) - retop = octave_value::op_el_not_or; - } - else - { - octave_value::unary_op opb = strip_not (b); + if (opa == octave_value::op_not) + { + if (op == octave_value::op_el_and) + retop = octave_value::op_el_not_and; + else if (op == octave_value::op_el_or) + retop = octave_value::op_el_not_or; + } + else + { + octave_value::unary_op opb = strip_not (b); - if (opb == octave_value::op_not) - { - if (op == octave_value::op_el_and) - retop = octave_value::op_el_and_not; - else if (op == octave_value::op_el_or) - retop = octave_value::op_el_or_not; - } - } + if (opb == octave_value::op_not) + { + if (op == octave_value::op_el_and) + retop = octave_value::op_el_and_not; + else if (op == octave_value::op_el_or) + retop = octave_value::op_el_or_not; + } + } - return retop; - } + return retop; +} #endif - tree_binary_expression * - maybe_compound_binary_expression (tree_expression *a, tree_expression *b, - int l, int c, octave_value::binary_op t) - { - tree_expression *ca = a; - tree_expression *cb = b; - octave_value::compound_binary_op ct; +tree_binary_expression * +maybe_compound_binary_expression (tree_expression *a, tree_expression *b, + int l, int c, octave_value::binary_op t) +{ + tree_expression *ca = a; + tree_expression *cb = b; + octave_value::compound_binary_op ct; - switch (t) - { - case octave_value::op_mul: - ct = simplify_mul_op (ca, cb); - break; + switch (t) + { + case octave_value::op_mul: + ct = simplify_mul_op (ca, cb); + break; - case octave_value::op_ldiv: - ct = simplify_ldiv_op (ca, cb); - break; + case octave_value::op_ldiv: + ct = simplify_ldiv_op (ca, cb); + break; #if 0 - // Restore this case if short-circuit behavior can be preserved - // when needed. See bug #54465. - case octave_value::op_el_and: - case octave_value::op_el_or: - ct = simplify_and_or_op (ca, cb, t); - break; + // Restore this case if short-circuit behavior can be preserved + // when needed. See bug #54465. + case octave_value::op_el_and: + case octave_value::op_el_or: + ct = simplify_and_or_op (ca, cb, t); + break; #endif - default: - ct = octave_value::unknown_compound_binary_op; - break; - } + default: + ct = octave_value::unknown_compound_binary_op; + break; + } - tree_binary_expression *ret - = (ct == octave_value::unknown_compound_binary_op - ? new tree_binary_expression (a, b, l, c, t) - : new tree_compound_binary_expression (a, b, l, c, t, ca, cb, ct)); + tree_binary_expression *ret + = (ct == octave_value::unknown_compound_binary_op + ? new tree_binary_expression (a, b, l, c, t) + : new tree_compound_binary_expression (a, b, l, c, t, ca, cb, ct)); - return ret; - } + return ret; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-cbinop.h --- a/libinterp/parse-tree/pt-cbinop.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-cbinop.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,62 +39,62 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Binary expressions that can be reduced to compound operations +// Binary expressions that can be reduced to compound operations - class tree_compound_binary_expression : public tree_binary_expression - { - public: +class tree_compound_binary_expression : public tree_binary_expression +{ +public: - tree_compound_binary_expression (tree_expression *a, tree_expression *b, - int l, int c, - octave_value::binary_op t, - tree_expression *ca, tree_expression *cb, - octave_value::compound_binary_op ct) - : tree_binary_expression (a, b, l, c, t), m_lhs (ca), m_rhs (cb), - m_etype (ct) - { } + tree_compound_binary_expression (tree_expression *a, tree_expression *b, + int l, int c, + octave_value::binary_op t, + tree_expression *ca, tree_expression *cb, + octave_value::compound_binary_op ct) + : tree_binary_expression (a, b, l, c, t), m_lhs (ca), m_rhs (cb), + m_etype (ct) + { } - octave_value::compound_binary_op cop_type (void) const { return m_etype; } + octave_value::compound_binary_op cop_type (void) const { return m_etype; } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - tree_expression * clhs (void) { return m_lhs; } - tree_expression * crhs (void) { return m_rhs; } + tree_expression * clhs (void) { return m_lhs; } + tree_expression * crhs (void) { return m_rhs; } - octave_value evaluate (tree_evaluator&, int nargout = 1); + octave_value evaluate (tree_evaluator&, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) - { - tw.visit_compound_binary_expression (*this); - } + void accept (tree_walker& tw) + { + tw.visit_compound_binary_expression (*this); + } - private: +private: - tree_expression *m_lhs; - tree_expression *m_rhs; + tree_expression *m_lhs; + tree_expression *m_rhs; - octave_value::compound_binary_op m_etype; + octave_value::compound_binary_op m_etype; - // No copying! + // No copying! - tree_compound_binary_expression (const tree_compound_binary_expression&) = delete; + tree_compound_binary_expression (const tree_compound_binary_expression&) = delete; - tree_compound_binary_expression& - operator = (const tree_compound_binary_expression&) = delete; - }; + tree_compound_binary_expression& + operator = (const tree_compound_binary_expression&) = delete; +}; - // a "virtual constructor" +// a "virtual constructor" - tree_binary_expression * - maybe_compound_binary_expression (tree_expression *a, tree_expression *b, - int l = -1, int c = -1, - octave_value::binary_op t - = octave_value::unknown_binary_op); +tree_binary_expression * +maybe_compound_binary_expression (tree_expression *a, tree_expression *b, + int l = -1, int c = -1, + octave_value::binary_op t + = octave_value::unknown_binary_op); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-cell.cc --- a/libinterp/parse-tree/pt-cell.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-cell.cc Thu Dec 01 20:05:44 2022 -0800 @@ -38,68 +38,68 @@ OCTAVE_BEGIN_NAMESPACE(octave) - tree_expression * - tree_cell::dup (symbol_scope& scope) const - { - tree_cell *new_cell = new tree_cell (nullptr, line (), column ()); +tree_expression * +tree_cell::dup (symbol_scope& scope) const +{ + tree_cell *new_cell = new tree_cell (nullptr, line (), column ()); + + new_cell->copy_base (*this, scope); - new_cell->copy_base (*this, scope); + return new_cell; +} - return new_cell; - } - - octave_value - tree_cell::evaluate (tree_evaluator& tw, int) +octave_value +tree_cell::evaluate (tree_evaluator& tw, int) +{ + unwind_action act ([&tw] (const std::list *lvl) { - unwind_action act ([&tw] (const std::list *lvl) - { - tw.set_lvalue_list (lvl); - }, tw.lvalue_list ()); - tw.set_lvalue_list (nullptr); + tw.set_lvalue_list (lvl); + }, tw.lvalue_list ()); + tw.set_lvalue_list (nullptr); + + octave_idx_type nr = length (); + octave_idx_type nc = -1; - octave_idx_type nr = length (); - octave_idx_type nc = -1; + Cell val; - Cell val; + octave_idx_type i = 0; - octave_idx_type i = 0; - - for (tree_argument_list *elt : *this) - { - octave_value_list row = tw.convert_to_const_vector (elt); + for (tree_argument_list *elt : *this) + { + octave_value_list row = tw.convert_to_const_vector (elt); - if (nr == 1) - // Optimize the single row case. - val = row.cell_value (); - else if (nc < 0) - { - nc = row.length (); + if (nr == 1) + // Optimize the single row case. + val = row.cell_value (); + else if (nc < 0) + { + nc = row.length (); - val = Cell (nr, nc); - } - else - { - octave_idx_type this_nc = row.length (); + val = Cell (nr, nc); + } + else + { + octave_idx_type this_nc = row.length (); - if (this_nc != nc) - { - if (this_nc == 0) - continue; // blank line - else - error ("number of columns must match"); - } - } + if (this_nc != nc) + { + if (this_nc == 0) + continue; // blank line + else + error ("number of columns must match"); + } + } - for (octave_idx_type j = 0; j < nc; j++) - val(i, j) = row(j); + for (octave_idx_type j = 0; j < nc; j++) + val(i, j) = row(j); - i++; - } + i++; + } - if (i < nr) - val.resize (dim_vector (i, nc)); // there were blank rows + if (i < nr) + val.resize (dim_vector (i, nc)); // there were blank rows - return octave_value (val); - } + return octave_value (val); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-cell.h --- a/libinterp/parse-tree/pt-cell.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-cell.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,45 +38,45 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_argument_list; +class symbol_scope; +class tree_argument_list; - // General cells. +// General cells. - class tree_cell : public tree_array_list - { - public: +class tree_cell : public tree_array_list +{ +public: - tree_cell (tree_argument_list *row = nullptr, int l = -1, int c = -1) - : tree_array_list (row, l, c) - { } + tree_cell (tree_argument_list *row = nullptr, int l = -1, int c = -1) + : tree_array_list (row, l, c) + { } - // No copying! + // No copying! - tree_cell (const tree_cell&) = delete; + tree_cell (const tree_cell&) = delete; - tree_cell& operator = (const tree_cell&) = delete; + tree_cell& operator = (const tree_cell&) = delete; - ~tree_cell (void) = default; + ~tree_cell (void) = default; - bool iscell (void) const { return true; } + bool iscell (void) const { return true; } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator&, int nargout = 1); + octave_value evaluate (tree_evaluator&, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) - { - tw.visit_cell (*this); - } - }; + void accept (tree_walker& tw) + { + tw.visit_cell (*this); + } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-check.cc --- a/libinterp/parse-tree/pt-check.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-check.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,148 +34,148 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - tree_checker::visit_argument_list (tree_argument_list& lst) - { - auto p = lst.begin (); +void +tree_checker::visit_argument_list (tree_argument_list& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_expression *elt = *p++; + while (p != lst.end ()) + { + tree_expression *elt = *p++; - if (elt) - { - if (m_do_lvalue_check && ! elt->lvalue_ok ()) - errmsg ("invalid lvalue in multiple assignment", elt->line ()); - } - } - } + if (elt) + { + if (m_do_lvalue_check && ! elt->lvalue_ok ()) + errmsg ("invalid lvalue in multiple assignment", elt->line ()); + } + } +} - void - tree_checker::visit_simple_for_command (tree_simple_for_command& cmd) - { - tree_expression *lhs = cmd.left_hand_side (); +void +tree_checker::visit_simple_for_command (tree_simple_for_command& cmd) +{ + tree_expression *lhs = cmd.left_hand_side (); - if (lhs) - { - if (! lhs->lvalue_ok ()) - errmsg ("invalid lvalue in for command", cmd.line ()); - } + if (lhs) + { + if (! lhs->lvalue_ok ()) + errmsg ("invalid lvalue in for command", cmd.line ()); + } - tree_expression *expr = cmd.control_expr (); + tree_expression *expr = cmd.control_expr (); - if (expr) - expr->accept (*this); + if (expr) + expr->accept (*this); - tree_expression *maxproc = cmd.maxproc_expr (); + tree_expression *maxproc = cmd.maxproc_expr (); - if (maxproc) - maxproc->accept (*this); + if (maxproc) + maxproc->accept (*this); - tree_statement_list *list = cmd.body (); + tree_statement_list *list = cmd.body (); - if (list) - list->accept (*this); - } + if (list) + list->accept (*this); +} - void - tree_checker::visit_complex_for_command (tree_complex_for_command& cmd) - { - tree_argument_list *lhs = cmd.left_hand_side (); +void +tree_checker::visit_complex_for_command (tree_complex_for_command& cmd) +{ + tree_argument_list *lhs = cmd.left_hand_side (); - if (lhs) - { - int len = lhs->length (); + if (lhs) + { + int len = lhs->length (); - if (len == 0 || len > 2) - errmsg ("invalid number of output arguments in for command", - cmd.line ()); + if (len == 0 || len > 2) + errmsg ("invalid number of output arguments in for command", + cmd.line ()); - m_do_lvalue_check = true; + m_do_lvalue_check = true; - lhs->accept (*this); + lhs->accept (*this); - m_do_lvalue_check = false; - } + m_do_lvalue_check = false; + } - tree_expression *expr = cmd.control_expr (); + tree_expression *expr = cmd.control_expr (); - if (expr) - expr->accept (*this); + if (expr) + expr->accept (*this); - tree_statement_list *list = cmd.body (); + tree_statement_list *list = cmd.body (); - if (list) - list->accept (*this); - } + if (list) + list->accept (*this); +} - void - tree_checker::visit_multi_assignment (tree_multi_assignment& expr) - { - tree_argument_list *lhs = expr.left_hand_side (); +void +tree_checker::visit_multi_assignment (tree_multi_assignment& expr) +{ + tree_argument_list *lhs = expr.left_hand_side (); - if (lhs) - { - m_do_lvalue_check = true; + if (lhs) + { + m_do_lvalue_check = true; - lhs->accept (*this); + lhs->accept (*this); - m_do_lvalue_check = false; - } + m_do_lvalue_check = false; + } - tree_expression *rhs = expr.right_hand_side (); + tree_expression *rhs = expr.right_hand_side (); - if (rhs) - rhs->accept (*this); - } + if (rhs) + rhs->accept (*this); +} - void - tree_checker::visit_simple_assignment (tree_simple_assignment& expr) - { - tree_expression *lhs = expr.left_hand_side (); +void +tree_checker::visit_simple_assignment (tree_simple_assignment& expr) +{ + tree_expression *lhs = expr.left_hand_side (); - if (lhs) - { - if (! lhs->lvalue_ok ()) - errmsg ("invalid lvalue in assignment", expr.line ()); - } + if (lhs) + { + if (! lhs->lvalue_ok ()) + errmsg ("invalid lvalue in assignment", expr.line ()); + } - tree_expression *rhs = expr.right_hand_side (); + tree_expression *rhs = expr.right_hand_side (); - if (rhs) - rhs->accept (*this); - } + if (rhs) + rhs->accept (*this); +} - void - tree_checker::visit_try_catch_command (tree_try_catch_command& cmd) - { - tree_statement_list *try_code = cmd.body (); +void +tree_checker::visit_try_catch_command (tree_try_catch_command& cmd) +{ + tree_statement_list *try_code = cmd.body (); - tree_identifier *expr_id = cmd.identifier (); + tree_identifier *expr_id = cmd.identifier (); - if (expr_id) - { - if (! expr_id->lvalue_ok ()) - errmsg ("invalid lvalue used for identifier in try-catch command", - cmd.line ()); - } + if (expr_id) + { + if (! expr_id->lvalue_ok ()) + errmsg ("invalid lvalue used for identifier in try-catch command", + cmd.line ()); + } - if (try_code) - try_code->accept (*this); + if (try_code) + try_code->accept (*this); - tree_statement_list *catch_code = cmd.cleanup (); + tree_statement_list *catch_code = cmd.cleanup (); - if (catch_code) - catch_code->accept (*this); - } + if (catch_code) + catch_code->accept (*this); +} - void - tree_checker::errmsg (const std::string& msg, int line) - { - if (m_file_name.empty ()) - error ("%s", msg.c_str ()); - else - error ("%s: %d: %s", m_file_name.c_str (), line, msg.c_str ()); - } +void +tree_checker::errmsg (const std::string& msg, int line) +{ + if (m_file_name.empty ()) + error ("%s", msg.c_str ()); + else + error ("%s: %d: %s", m_file_name.c_str (), line, msg.c_str ()); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-check.h --- a/libinterp/parse-tree/pt-check.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-check.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,45 +34,45 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_decl_command; +class tree_decl_command; - // How to check the semantics of the code that the parse trees represent. +// How to check the semantics of the code that the parse trees represent. - class tree_checker : public tree_walker - { - public: +class tree_checker : public tree_walker +{ +public: - tree_checker (void) - : m_do_lvalue_check (false), m_file_name () { } + tree_checker (void) + : m_do_lvalue_check (false), m_file_name () { } - // No copying! + // No copying! - tree_checker (const tree_checker&) = delete; + tree_checker (const tree_checker&) = delete; - tree_checker& operator = (const tree_checker&) = delete; + tree_checker& operator = (const tree_checker&) = delete; - ~tree_checker (void) = default; + ~tree_checker (void) = default; - void visit_argument_list (tree_argument_list&); + void visit_argument_list (tree_argument_list&); - void visit_simple_for_command (tree_simple_for_command&); + void visit_simple_for_command (tree_simple_for_command&); - void visit_complex_for_command (tree_complex_for_command&); + void visit_complex_for_command (tree_complex_for_command&); - void visit_multi_assignment (tree_multi_assignment&); + void visit_multi_assignment (tree_multi_assignment&); - void visit_simple_assignment (tree_simple_assignment&); + void visit_simple_assignment (tree_simple_assignment&); - void visit_try_catch_command (tree_try_catch_command&); + void visit_try_catch_command (tree_try_catch_command&); - private: +private: - bool m_do_lvalue_check; + bool m_do_lvalue_check; - std::string m_file_name; + std::string m_file_name; - OCTAVE_NORETURN void errmsg (const std::string& msg, int line); - }; + OCTAVE_NORETURN void errmsg (const std::string& msg, int line); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-classdef.cc --- a/libinterp/parse-tree/pt-classdef.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-classdef.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,284 +37,284 @@ OCTAVE_BEGIN_NAMESPACE(octave) - tree_superclass_ref * - tree_superclass_ref::dup (symbol_scope&) const - { - tree_superclass_ref *new_scr - = new tree_superclass_ref (m_method_name, m_class_name, - line (), column ()); +tree_superclass_ref * +tree_superclass_ref::dup (symbol_scope&) const +{ + tree_superclass_ref *new_scr + = new tree_superclass_ref (m_method_name, m_class_name, + line (), column ()); - new_scr->copy_base (*this); + new_scr->copy_base (*this); - return new_scr; - } + return new_scr; +} - octave_value_list - tree_superclass_ref::evaluate_n (tree_evaluator& tw, int nargout) - { - octave_value tmp - = octave_classdef::superclass_ref (m_method_name, m_class_name); +octave_value_list +tree_superclass_ref::evaluate_n (tree_evaluator& tw, int nargout) +{ + octave_value tmp + = octave_classdef::superclass_ref (m_method_name, m_class_name); - if (! is_postfix_indexed ()) - { - // There was no index, so this superclass_ref object is not - // part of an index expression. It is also not an identifier in - // the syntax tree but we need to handle it as if it were. So - // call the function here. - octave_function *f = tmp.function_value (true); + if (! is_postfix_indexed ()) + { + // There was no index, so this superclass_ref object is not + // part of an index expression. It is also not an identifier in + // the syntax tree but we need to handle it as if it were. So + // call the function here. + octave_function *f = tmp.function_value (true); - panic_unless (f); + panic_unless (f); - return f->call (tw, nargout); - } + return f->call (tw, nargout); + } - // The superclass_ref function object will be indexed as part of the - // enclosing index expression. + // The superclass_ref function object will be indexed as part of the + // enclosing index expression. - return ovl (tmp); - } + return ovl (tmp); +} - tree_metaclass_query * - tree_metaclass_query::dup (symbol_scope&) const - { - tree_metaclass_query *new_mcq - = new tree_metaclass_query (m_class_name, line (), column ()); +tree_metaclass_query * +tree_metaclass_query::dup (symbol_scope&) const +{ + tree_metaclass_query *new_mcq + = new tree_metaclass_query (m_class_name, line (), column ()); - new_mcq->copy_base (*this); + new_mcq->copy_base (*this); - return new_mcq; - } + return new_mcq; +} - octave_value - tree_metaclass_query::evaluate (tree_evaluator&, int) - { - return octave_classdef::metaclass_query (m_class_name); - } +octave_value +tree_metaclass_query::evaluate (tree_evaluator&, int) +{ + return octave_classdef::metaclass_query (m_class_name); +} - // Classdef attribute +// Classdef attribute - // Classdef attribute_list +// Classdef attribute_list - tree_classdef_attribute_list::~tree_classdef_attribute_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_classdef_attribute_list::~tree_classdef_attribute_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - // Classdef superclass +// Classdef superclass - // Classdef superclass_list +// Classdef superclass_list - tree_classdef_superclass_list::~tree_classdef_superclass_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_classdef_superclass_list::~tree_classdef_superclass_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - // Classdef property +// Classdef property - std::string check_for_doc_string (comment_list *comments) - { - // If the comment list ends in a block comment or full-line comment, - // then it is the doc string for this property. +std::string check_for_doc_string (comment_list *comments) +{ + // If the comment list ends in a block comment or full-line comment, + // then it is the doc string for this property. - if (comments) - { - comment_elt last_elt = comments->back (); + if (comments) + { + comment_elt last_elt = comments->back (); - if (last_elt.is_block () || last_elt.is_full_line ()) - return last_elt.text (); - } + if (last_elt.is_block () || last_elt.is_full_line ()) + return last_elt.text (); + } - return ""; - } + return ""; +} - tree_classdef_property::tree_classdef_property (tree_arg_validation *av, - comment_list *comments) - : m_av (av), m_comments (comments), - m_doc_string (check_for_doc_string (m_comments)) - { } +tree_classdef_property::tree_classdef_property (tree_arg_validation *av, + comment_list *comments) + : m_av (av), m_comments (comments), + m_doc_string (check_for_doc_string (m_comments)) +{ } - tree_classdef_property::~tree_classdef_property (void) - { - delete m_av; - } +tree_classdef_property::~tree_classdef_property (void) +{ + delete m_av; +} - tree_identifier * tree_classdef_property::ident (void) - { - tree_expression *id_expr = m_av->identifier_expression (); +tree_identifier *tree_classdef_property::ident (void) +{ + tree_expression *id_expr = m_av->identifier_expression (); - return dynamic_cast (id_expr); - } + return dynamic_cast (id_expr); +} - tree_expression * tree_classdef_property::expression (void) - { - return m_av->initializer_expression (); - } +tree_expression *tree_classdef_property::expression (void) +{ + return m_av->initializer_expression (); +} - // Classdef property_list +// Classdef property_list - tree_classdef_property_list::~tree_classdef_property_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_classdef_property_list::~tree_classdef_property_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - // Classdef properties_block +// Classdef properties_block - // Classdef methods_list +// Classdef methods_list - // Classdef methods_block +// Classdef methods_block - // Classdef event +// Classdef event - tree_classdef_event::tree_classdef_event (tree_identifier *i, - comment_list *comments) - : m_id (i), m_comments (comments), - m_doc_string (check_for_doc_string (m_comments)) - { } +tree_classdef_event::tree_classdef_event (tree_identifier *i, + comment_list *comments) + : m_id (i), m_comments (comments), + m_doc_string (check_for_doc_string (m_comments)) +{ } - // Classdef events_list +// Classdef events_list - tree_classdef_events_list::~tree_classdef_events_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_classdef_events_list::~tree_classdef_events_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - // Classdef events_block +// Classdef events_block - // Classdef enum +// Classdef enum - tree_classdef_enum::tree_classdef_enum (tree_identifier *i, - tree_expression *e, - comment_list *comments) - : m_id (i), m_expr (e), m_comments (comments), - m_doc_string (check_for_doc_string (m_comments)) - { } +tree_classdef_enum::tree_classdef_enum (tree_identifier *i, + tree_expression *e, + comment_list *comments) + : m_id (i), m_expr (e), m_comments (comments), + m_doc_string (check_for_doc_string (m_comments)) +{ } - // Classdef enum_list +// Classdef enum_list - tree_classdef_enum_list::~tree_classdef_enum_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_classdef_enum_list::~tree_classdef_enum_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - // Classdef enum_block +// Classdef enum_block - // Classdef body +// Classdef body - tree_classdef_body::tree_classdef_body (void) - : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst () - { } +tree_classdef_body::tree_classdef_body (void) + : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst () +{ } - tree_classdef_body::tree_classdef_body (tree_classdef_properties_block *pb) - : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), - m_doc_string (pb ? get_doc_string (pb->leading_comment ()) : "") - { - append (pb); - } +tree_classdef_body::tree_classdef_body (tree_classdef_properties_block *pb) + : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), + m_doc_string (pb ? get_doc_string (pb->leading_comment ()) : "") +{ + append (pb); +} - tree_classdef_body::tree_classdef_body (tree_classdef_methods_block *mb) - : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), - m_doc_string (mb ? get_doc_string (mb->leading_comment ()) : "") - { - append (mb); - } +tree_classdef_body::tree_classdef_body (tree_classdef_methods_block *mb) + : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), + m_doc_string (mb ? get_doc_string (mb->leading_comment ()) : "") +{ + append (mb); +} - tree_classdef_body::tree_classdef_body (tree_classdef_events_block *evb) - : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), - m_doc_string (evb ? get_doc_string (evb->leading_comment ()) : "") - { - append (evb); - } +tree_classdef_body::tree_classdef_body (tree_classdef_events_block *evb) + : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), + m_doc_string (evb ? get_doc_string (evb->leading_comment ()) : "") +{ + append (evb); +} - tree_classdef_body::tree_classdef_body (tree_classdef_enum_block *enb) - : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), - m_doc_string (enb ? get_doc_string (enb->leading_comment ()) : "") - { - append (enb); - } +tree_classdef_body::tree_classdef_body (tree_classdef_enum_block *enb) + : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (), + m_doc_string (enb ? get_doc_string (enb->leading_comment ()) : "") +{ + append (enb); +} - tree_classdef_body::~tree_classdef_body (void) - { - while (! m_properties_lst.empty ()) - { - auto p = m_properties_lst.begin (); - delete *p; - m_properties_lst.erase (p); - } +tree_classdef_body::~tree_classdef_body (void) +{ + while (! m_properties_lst.empty ()) + { + auto p = m_properties_lst.begin (); + delete *p; + m_properties_lst.erase (p); + } - while (! m_methods_lst.empty ()) - { - auto p = m_methods_lst.begin (); - delete *p; - m_methods_lst.erase (p); - } + while (! m_methods_lst.empty ()) + { + auto p = m_methods_lst.begin (); + delete *p; + m_methods_lst.erase (p); + } - while (! m_events_lst.empty ()) - { - auto p = m_events_lst.begin (); - delete *p; - m_events_lst.erase (p); - } + while (! m_events_lst.empty ()) + { + auto p = m_events_lst.begin (); + delete *p; + m_events_lst.erase (p); + } - while (! m_enum_lst.empty ()) - { - auto p = m_enum_lst.begin (); - delete *p; - m_enum_lst.erase (p); - } - } + while (! m_enum_lst.empty ()) + { + auto p = m_enum_lst.begin (); + delete *p; + m_enum_lst.erase (p); + } +} - std::string - tree_classdef_body::get_doc_string (comment_list *comments) const - { - // Grab the first comment from the list and use it as the doc string - // for this classdef body. +std::string +tree_classdef_body::get_doc_string (comment_list *comments) const +{ + // Grab the first comment from the list and use it as the doc string + // for this classdef body. - if (comments) - { - comment_elt first_elt = comments->front (); + if (comments) + { + comment_elt first_elt = comments->front (); - return first_elt.text (); - } + return first_elt.text (); + } - return ""; - } + return ""; +} - // Classdef +// Classdef - octave_value - tree_classdef::make_meta_class (interpreter& interp, bool is_at_folder) - { - cdef_class cls = cdef_class::make_meta_class (interp, this, is_at_folder); +octave_value +tree_classdef::make_meta_class (interpreter& interp, bool is_at_folder) +{ + cdef_class cls = cdef_class::make_meta_class (interp, this, is_at_folder); - if (cls.ok ()) - return cls.get_constructor_function (); + if (cls.ok ()) + return cls.get_constructor_function (); - return octave_value (); - } + return octave_value (); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-classdef.h --- a/libinterp/parse-tree/pt-classdef.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-classdef.h Thu Dec 01 20:05:44 2022 -0800 @@ -42,808 +42,808 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class interpreter; - - class tree_arg_validation; +class interpreter; - class tree_superclass_ref : public tree_expression - { - public: +class tree_arg_validation; - tree_superclass_ref (void) = delete; +class tree_superclass_ref : public tree_expression +{ +public: - tree_superclass_ref (const std::string& meth, const std::string& cls, - int l = -1, int c = -1) - : tree_expression (l, c), m_method_name (meth), m_class_name (cls) - { } - - // No copying! + tree_superclass_ref (void) = delete; - tree_superclass_ref (const tree_superclass_ref&) = delete; + tree_superclass_ref (const std::string& meth, const std::string& cls, + int l = -1, int c = -1) + : tree_expression (l, c), m_method_name (meth), m_class_name (cls) + { } - tree_superclass_ref& operator = (const tree_superclass_ref&) = delete; + // No copying! + + tree_superclass_ref (const tree_superclass_ref&) = delete; - std::string method_name (void) const - { - return m_method_name; - } + tree_superclass_ref& operator = (const tree_superclass_ref&) = delete; - std::string class_name (void) const { return m_class_name; } - - tree_superclass_ref * dup (symbol_scope& scope) const; + std::string method_name (void) const + { + return m_method_name; + } - octave_value evaluate (tree_evaluator& tw, int nargout = 1) - { - octave_value_list retval = evaluate_n (tw, nargout); + std::string class_name (void) const { return m_class_name; } - return retval.length () > 0 ? retval(0) : octave_value (); - } - - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); + tree_superclass_ref * dup (symbol_scope& scope) const; - void accept (tree_walker& tw) - { - tw.visit_superclass_ref (*this); - } + octave_value evaluate (tree_evaluator& tw, int nargout = 1) + { + octave_value_list retval = evaluate_n (tw, nargout); - private: + return retval.length () > 0 ? retval(0) : octave_value (); + } - // The name of the method to call. This is the text before the - // "@" and may be of the form "object.method". - std::string m_method_name; + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); - // The name of the superclass. This is the text after the "@" - // and may be of the form "object.method". - std::string m_class_name; - }; + void accept (tree_walker& tw) + { + tw.visit_superclass_ref (*this); + } - class tree_metaclass_query : public tree_expression - { - public: - - tree_metaclass_query (void) = delete; +private: - tree_metaclass_query (const std::string& cls, int l = -1, int c = -1) - : tree_expression (l, c), m_class_name (cls) - { } - - // No copying! + // The name of the method to call. This is the text before the + // "@" and may be of the form "object.method". + std::string m_method_name; - tree_metaclass_query (const tree_metaclass_query&) = delete; + // The name of the superclass. This is the text after the "@" + // and may be of the form "object.method". + std::string m_class_name; +}; - tree_metaclass_query& operator = (const tree_metaclass_query&) = delete; - - std::string class_name (void) const { return m_class_name; } +class tree_metaclass_query : public tree_expression +{ +public: - tree_metaclass_query * dup (symbol_scope& scope) const; + tree_metaclass_query (void) = delete; - octave_value evaluate (tree_evaluator&, int nargout = 1); + tree_metaclass_query (const std::string& cls, int l = -1, int c = -1) + : tree_expression (l, c), m_class_name (cls) + { } - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + // No copying! + + tree_metaclass_query (const tree_metaclass_query&) = delete; - void accept (tree_walker& tw) - { - tw.visit_metaclass_query (*this); - } + tree_metaclass_query& operator = (const tree_metaclass_query&) = delete; - private: + std::string class_name (void) const { return m_class_name; } - std::string m_class_name; - }; + tree_metaclass_query * dup (symbol_scope& scope) const; - class tree_classdef_attribute - { - public: + octave_value evaluate (tree_evaluator&, int nargout = 1); - tree_classdef_attribute (tree_identifier *i = nullptr, - tree_expression *e = nullptr) - : m_id (i), m_expr (e), m_neg (false) - { } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - tree_classdef_attribute (tree_identifier *i, bool b) - : m_id (i), m_expr (nullptr), m_neg (b) - { } + void accept (tree_walker& tw) + { + tw.visit_metaclass_query (*this); + } - // No copying! - - tree_classdef_attribute (const tree_classdef_attribute&) = delete; +private: - tree_classdef_attribute& operator = (const tree_classdef_attribute&) = delete; - - ~tree_classdef_attribute (void) - { - delete m_id; - delete m_expr; - } + std::string m_class_name; +}; - tree_identifier * ident (void) { return m_id; } - - tree_expression * expression (void) { return m_expr; } +class tree_classdef_attribute +{ +public: - bool negate (void) { return m_neg; } - - void accept (tree_walker& tw) - { - tw.visit_classdef_attribute (*this); - } + tree_classdef_attribute (tree_identifier *i = nullptr, + tree_expression *e = nullptr) + : m_id (i), m_expr (e), m_neg (false) + { } - private: + tree_classdef_attribute (tree_identifier *i, bool b) + : m_id (i), m_expr (nullptr), m_neg (b) + { } + + // No copying! - tree_identifier *m_id; - tree_expression *m_expr; - bool m_neg; - }; + tree_classdef_attribute (const tree_classdef_attribute&) = delete; - class tree_classdef_attribute_list : public base_list + tree_classdef_attribute& operator = (const tree_classdef_attribute&) = delete; + + ~tree_classdef_attribute (void) { - public: - - tree_classdef_attribute_list (void) { } + delete m_id; + delete m_expr; + } - tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); } - - tree_classdef_attribute_list (const base_list& a) - : base_list (a) - { } + tree_identifier * ident (void) { return m_id; } - // No copying! - - tree_classdef_attribute_list (const tree_classdef_attribute_list&) = delete; - - tree_classdef_attribute_list& - operator = (const tree_classdef_attribute_list&) = delete; + tree_expression * expression (void) { return m_expr; } - ~tree_classdef_attribute_list (void); + bool negate (void) { return m_neg; } - void accept (tree_walker& tw) - { - tw.visit_classdef_attribute_list (*this); - } - }; - - class tree_classdef_superclass + void accept (tree_walker& tw) { - public: + tw.visit_classdef_attribute (*this); + } + +private: - tree_classdef_superclass (const std::string& cname) - : m_cls_name (cname) - { } - - // No copying! + tree_identifier *m_id; + tree_expression *m_expr; + bool m_neg; +}; - tree_classdef_superclass (const tree_classdef_superclass&) = delete; +class tree_classdef_attribute_list : public base_list +{ +public: + + tree_classdef_attribute_list (void) { } - tree_classdef_superclass& - operator = (const tree_classdef_superclass&) = delete; + tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); } - ~tree_classdef_superclass (void) = default; + tree_classdef_attribute_list (const base_list& a) + : base_list (a) + { } - std::string class_name (void) { return m_cls_name; } + // No copying! - void accept (tree_walker& tw) - { - tw.visit_classdef_superclass (*this); - } + tree_classdef_attribute_list (const tree_classdef_attribute_list&) = delete; - private: + tree_classdef_attribute_list& + operator = (const tree_classdef_attribute_list&) = delete; - std::string m_cls_name; - }; + ~tree_classdef_attribute_list (void); - class tree_classdef_superclass_list - : public base_list + void accept (tree_walker& tw) { - public: - - tree_classdef_superclass_list (void) { } + tw.visit_classdef_attribute_list (*this); + } +}; - tree_classdef_superclass_list (tree_classdef_superclass *sc) - { - append (sc); - } +class tree_classdef_superclass +{ +public: - tree_classdef_superclass_list (const base_list& a) - : base_list (a) - { } + tree_classdef_superclass (const std::string& cname) + : m_cls_name (cname) + { } - // No copying! + // No copying! - tree_classdef_superclass_list (const tree_classdef_superclass_list&) = delete; + tree_classdef_superclass (const tree_classdef_superclass&) = delete; - tree_classdef_superclass_list& - operator = (const tree_classdef_superclass_list&) = delete; + tree_classdef_superclass& + operator = (const tree_classdef_superclass&) = delete; - ~tree_classdef_superclass_list (void); + ~tree_classdef_superclass (void) = default; - void accept (tree_walker& tw) - { - tw.visit_classdef_superclass_list (*this); - } - }; + std::string class_name (void) { return m_cls_name; } - template - class tree_classdef_element : public tree + void accept (tree_walker& tw) { - public: + tw.visit_classdef_superclass (*this); + } - tree_classdef_element (tree_classdef_attribute_list *a, T *elt_list, - comment_list *lc, comment_list *tc, - int l = -1, int c = -1) - : tree (l, c), m_attr_list (a), m_elt_list (elt_list), - m_lead_comm (lc), m_trail_comm (tc) - { } +private: + + std::string m_cls_name; +}; - // No copying! +class tree_classdef_superclass_list + : public base_list +{ +public: - tree_classdef_element (const tree_classdef_element&) = delete; - - tree_classdef_element& operator = (const tree_classdef_element&) = delete; + tree_classdef_superclass_list (void) { } - ~tree_classdef_element (void) - { - delete m_attr_list; - delete m_elt_list; - delete m_lead_comm; - delete m_trail_comm; - } + tree_classdef_superclass_list (tree_classdef_superclass *sc) + { + append (sc); + } - tree_classdef_attribute_list * attribute_list (void) { return m_attr_list; } + tree_classdef_superclass_list (const base_list& a) + : base_list (a) + { } - T * element_list (void) { return m_elt_list; } - - comment_list * leading_comment (void) { return m_lead_comm; } + // No copying! - comment_list * trailing_comment (void) { return m_trail_comm; } - - void accept (tree_walker&) { } + tree_classdef_superclass_list (const tree_classdef_superclass_list&) = delete; - private: - - // List of attributes that apply to this class. - tree_classdef_attribute_list *m_attr_list; + tree_classdef_superclass_list& + operator = (const tree_classdef_superclass_list&) = delete; - // The list of objects contained in this block. - T *m_elt_list; + ~tree_classdef_superclass_list (void); - // Comments preceding the token marking the beginning of the block. - comment_list *m_lead_comm; - - // Comments preceding the END token marking the end of the block. - comment_list *m_trail_comm; - }; + void accept (tree_walker& tw) + { + tw.visit_classdef_superclass_list (*this); + } +}; - class tree_classdef_property - { - public: - - tree_classdef_property (tree_arg_validation *av, - comment_list *comments = nullptr); - - // No copying! +template +class tree_classdef_element : public tree +{ +public: - tree_classdef_property (const tree_classdef_property&) = delete; - - tree_classdef_property& operator = (const tree_classdef_property&) = delete; - - ~tree_classdef_property (void); + tree_classdef_element (tree_classdef_attribute_list *a, T *elt_list, + comment_list *lc, comment_list *tc, + int l = -1, int c = -1) + : tree (l, c), m_attr_list (a), m_elt_list (elt_list), + m_lead_comm (lc), m_trail_comm (tc) + { } - tree_identifier * ident (void); + // No copying! - tree_expression * expression (void); + tree_classdef_element (const tree_classdef_element&) = delete; - comment_list * comments (void) const { return m_comments; } + tree_classdef_element& operator = (const tree_classdef_element&) = delete; - void doc_string (const std::string& txt) { m_doc_string = txt; } - - std::string doc_string (void) const { return m_doc_string; } - - bool have_doc_string (void) const { return ! m_doc_string.empty (); } + ~tree_classdef_element (void) + { + delete m_attr_list; + delete m_elt_list; + delete m_lead_comm; + delete m_trail_comm; + } - void accept (tree_walker& tw) - { - tw.visit_classdef_property (*this); - } + tree_classdef_attribute_list * attribute_list (void) { return m_attr_list; } - private: + T * element_list (void) { return m_elt_list; } - tree_arg_validation *m_av; - comment_list *m_comments; - std::string m_doc_string; - }; + comment_list * leading_comment (void) { return m_lead_comm; } - class tree_classdef_property_list : public base_list - { - public: + comment_list * trailing_comment (void) { return m_trail_comm; } - tree_classdef_property_list (void) { } + void accept (tree_walker&) { } - tree_classdef_property_list (tree_classdef_property *p) { append (p); } +private: - tree_classdef_property_list (const base_list& a) - : base_list (a) { } - - // No copying! + // List of attributes that apply to this class. + tree_classdef_attribute_list *m_attr_list; - tree_classdef_property_list (const tree_classdef_property_list&) = delete; + // The list of objects contained in this block. + T *m_elt_list; - tree_classdef_property_list& - operator = (const tree_classdef_property_list&) = delete; + // Comments preceding the token marking the beginning of the block. + comment_list *m_lead_comm; - ~tree_classdef_property_list (void); + // Comments preceding the END token marking the end of the block. + comment_list *m_trail_comm; +}; - void accept (tree_walker& tw) - { - tw.visit_classdef_property_list (*this); - } - }; +class tree_classdef_property +{ +public: - class tree_classdef_properties_block - : public tree_classdef_element - { - public: + tree_classdef_property (tree_arg_validation *av, + comment_list *comments = nullptr); + + // No copying! + + tree_classdef_property (const tree_classdef_property&) = delete; - tree_classdef_properties_block (tree_classdef_attribute_list *a, - tree_classdef_property_list *plist, - comment_list *lc, comment_list *tc, - int l = -1, int c = -1) - : tree_classdef_element (a, plist, lc, tc, l, c) - { } + tree_classdef_property& operator = (const tree_classdef_property&) = delete; + + ~tree_classdef_property (void); - // No copying! + tree_identifier * ident (void); - tree_classdef_properties_block (const tree_classdef_properties_block&) = delete; + tree_expression * expression (void); - tree_classdef_properties_block& - operator = (const tree_classdef_properties_block&) = delete; + comment_list * comments (void) const { return m_comments; } - ~tree_classdef_properties_block (void) = default; + void doc_string (const std::string& txt) { m_doc_string = txt; } - void accept (tree_walker& tw) - { - tw.visit_classdef_properties_block (*this); - } - }; + std::string doc_string (void) const { return m_doc_string; } - class tree_classdef_methods_list : public base_list + bool have_doc_string (void) const { return ! m_doc_string.empty (); } + + void accept (tree_walker& tw) { - public: - - tree_classdef_methods_list (void) { } + tw.visit_classdef_property (*this); + } - tree_classdef_methods_list (const octave_value& f) { append (f); } - - tree_classdef_methods_list (const base_list& a) - : base_list (a) { } +private: - // No copying! - - tree_classdef_methods_list (const tree_classdef_methods_list&) = delete; + tree_arg_validation *m_av; + comment_list *m_comments; + std::string m_doc_string; +}; - tree_classdef_methods_list& - operator = (const tree_classdef_methods_list&) = delete; - - ~tree_classdef_methods_list (void) = default; +class tree_classdef_property_list : public base_list +{ +public: - void accept (tree_walker& tw) - { - tw.visit_classdef_methods_list (*this); - } - }; + tree_classdef_property_list (void) { } + + tree_classdef_property_list (tree_classdef_property *p) { append (p); } + + tree_classdef_property_list (const base_list& a) + : base_list (a) { } - class tree_classdef_methods_block - : public tree_classdef_element - { - public: + // No copying! + + tree_classdef_property_list (const tree_classdef_property_list&) = delete; - tree_classdef_methods_block (tree_classdef_attribute_list *a, - tree_classdef_methods_list *mlist, - comment_list *lc, comment_list *tc, - int l = -1, int c = -1) - : tree_classdef_element (a, mlist, lc, tc, l, c) - { } + tree_classdef_property_list& + operator = (const tree_classdef_property_list&) = delete; + + ~tree_classdef_property_list (void); - // No copying! - - tree_classdef_methods_block (const tree_classdef_methods_block&) = delete; - - tree_classdef_methods_block& - operator = (const tree_classdef_methods_block&) = delete; - - ~tree_classdef_methods_block (void) = default; + void accept (tree_walker& tw) + { + tw.visit_classdef_property_list (*this); + } +}; - void accept (tree_walker& tw) - { - tw.visit_classdef_methods_block (*this); - } - }; - - class tree_classdef_event - { - public: +class tree_classdef_properties_block + : public tree_classdef_element +{ +public: - tree_classdef_event (tree_identifier *i = nullptr, - comment_list *comments = nullptr); + tree_classdef_properties_block (tree_classdef_attribute_list *a, + tree_classdef_property_list *plist, + comment_list *lc, comment_list *tc, + int l = -1, int c = -1) + : tree_classdef_element (a, plist, lc, tc, l, c) + { } - // No copying! + // No copying! - tree_classdef_event (const tree_classdef_event&) = delete; - - tree_classdef_event& operator = (const tree_classdef_event&) = delete; + tree_classdef_properties_block (const tree_classdef_properties_block&) = delete; - ~tree_classdef_event (void) - { - delete m_id; - } + tree_classdef_properties_block& + operator = (const tree_classdef_properties_block&) = delete; + + ~tree_classdef_properties_block (void) = default; - tree_identifier * ident (void) { return m_id; } - - comment_list * comments (void) const { return m_comments; } - - void doc_string (const std::string& txt) { m_doc_string = txt; } + void accept (tree_walker& tw) + { + tw.visit_classdef_properties_block (*this); + } +}; - std::string doc_string (void) const { return m_doc_string; } - - bool have_doc_string (void) const { return ! m_doc_string.empty (); } +class tree_classdef_methods_list : public base_list +{ +public: - void accept (tree_walker& tw) - { - tw.visit_classdef_event (*this); - } + tree_classdef_methods_list (void) { } + + tree_classdef_methods_list (const octave_value& f) { append (f); } + + tree_classdef_methods_list (const base_list& a) + : base_list (a) { } - private: + // No copying! + + tree_classdef_methods_list (const tree_classdef_methods_list&) = delete; - tree_identifier *m_id; - comment_list *m_comments; - std::string m_doc_string; - }; + tree_classdef_methods_list& + operator = (const tree_classdef_methods_list&) = delete; - class tree_classdef_events_list : public base_list + ~tree_classdef_methods_list (void) = default; + + void accept (tree_walker& tw) { - public: - - tree_classdef_events_list (void) { } - - tree_classdef_events_list (tree_classdef_event *e) { append (e); } + tw.visit_classdef_methods_list (*this); + } +}; - tree_classdef_events_list (const base_list& a) - : base_list (a) - { } - - // No copying! - - tree_classdef_events_list (const tree_classdef_events_list&) = delete; - - tree_classdef_events_list& - operator = (const tree_classdef_events_list&) = delete; - - ~tree_classdef_events_list (void); +class tree_classdef_methods_block + : public tree_classdef_element +{ +public: - void accept (tree_walker& tw) - { - tw.visit_classdef_events_list (*this); - } - }; + tree_classdef_methods_block (tree_classdef_attribute_list *a, + tree_classdef_methods_list *mlist, + comment_list *lc, comment_list *tc, + int l = -1, int c = -1) + : tree_classdef_element (a, mlist, lc, tc, l, c) + { } - class tree_classdef_events_block - : public tree_classdef_element - { - public: + // No copying! + + tree_classdef_methods_block (const tree_classdef_methods_block&) = delete; - tree_classdef_events_block (tree_classdef_attribute_list *a, - tree_classdef_events_list *elist, - comment_list *lc, comment_list *tc, - int l = -1, int c = -1) - : tree_classdef_element (a, elist, lc, tc, l, c) - { } + tree_classdef_methods_block& + operator = (const tree_classdef_methods_block&) = delete; + + ~tree_classdef_methods_block (void) = default; - // No copying! - - tree_classdef_events_block (const tree_classdef_events_block&) = delete; - - tree_classdef_events_block& - operator = (const tree_classdef_events_block&) = delete; - - ~tree_classdef_events_block (void) = default; + void accept (tree_walker& tw) + { + tw.visit_classdef_methods_block (*this); + } +}; - void accept (tree_walker& tw) - { - tw.visit_classdef_events_block (*this); - } - }; +class tree_classdef_event +{ +public: - class tree_classdef_enum - { - public: + tree_classdef_event (tree_identifier *i = nullptr, + comment_list *comments = nullptr); + + // No copying! + + tree_classdef_event (const tree_classdef_event&) = delete; - tree_classdef_enum (tree_identifier *i, tree_expression *e, - comment_list *comments); - - // No copying! - - tree_classdef_enum (const tree_classdef_enum&) = delete; + tree_classdef_event& operator = (const tree_classdef_event&) = delete; - tree_classdef_enum& operator = (const tree_classdef_enum&) = delete; + ~tree_classdef_event (void) + { + delete m_id; + } - ~tree_classdef_enum (void) - { - delete m_id; - delete m_expr; - } + tree_identifier * ident (void) { return m_id; } - tree_identifier * ident (void) { return m_id; } + comment_list * comments (void) const { return m_comments; } + + void doc_string (const std::string& txt) { m_doc_string = txt; } - tree_expression * expression (void) { return m_expr; } - - comment_list * comments (void) const { return m_comments; } + std::string doc_string (void) const { return m_doc_string; } - void doc_string (const std::string& txt) { m_doc_string = txt; } - - std::string doc_string (void) const { return m_doc_string; } + bool have_doc_string (void) const { return ! m_doc_string.empty (); } - bool have_doc_string (void) const { return ! m_doc_string.empty (); } + void accept (tree_walker& tw) + { + tw.visit_classdef_event (*this); + } - void accept (tree_walker& tw) - { - tw.visit_classdef_enum (*this); - } +private: - private: + tree_identifier *m_id; + comment_list *m_comments; + std::string m_doc_string; +}; - tree_identifier *m_id; - tree_expression *m_expr; - comment_list *m_comments; - std::string m_doc_string; - }; +class tree_classdef_events_list : public base_list +{ +public: - class tree_classdef_enum_list : public base_list - { - public: + tree_classdef_events_list (void) { } + + tree_classdef_events_list (tree_classdef_event *e) { append (e); } - tree_classdef_enum_list (void) { } - - tree_classdef_enum_list (tree_classdef_enum *e) { append (e); } + tree_classdef_events_list (const base_list& a) + : base_list (a) + { } - tree_classdef_enum_list (const base_list& a) - : base_list (a) - { } + // No copying! - // No copying! + tree_classdef_events_list (const tree_classdef_events_list&) = delete; - tree_classdef_enum_list (const tree_classdef_enum_list&) = delete; + tree_classdef_events_list& + operator = (const tree_classdef_events_list&) = delete; - tree_classdef_enum_list& operator = (const tree_classdef_enum_list&) = delete; - - ~tree_classdef_enum_list (void); + ~tree_classdef_events_list (void); - void accept (tree_walker& tw) - { - tw.visit_classdef_enum_list (*this); - } - }; + void accept (tree_walker& tw) + { + tw.visit_classdef_events_list (*this); + } +}; - class tree_classdef_enum_block - : public tree_classdef_element - { - public: +class tree_classdef_events_block + : public tree_classdef_element +{ +public: - tree_classdef_enum_block (tree_classdef_attribute_list *a, - tree_classdef_enum_list *elist, + tree_classdef_events_block (tree_classdef_attribute_list *a, + tree_classdef_events_list *elist, comment_list *lc, comment_list *tc, int l = -1, int c = -1) - : tree_classdef_element (a, elist, lc, tc, l, c) - { } + : tree_classdef_element (a, elist, lc, tc, l, c) + { } - // No copying! + // No copying! + + tree_classdef_events_block (const tree_classdef_events_block&) = delete; - tree_classdef_enum_block (const tree_classdef_enum_block&) = delete; + tree_classdef_events_block& + operator = (const tree_classdef_events_block&) = delete; + + ~tree_classdef_events_block (void) = default; - tree_classdef_enum_block& - operator = (const tree_classdef_enum_block&) = delete; + void accept (tree_walker& tw) + { + tw.visit_classdef_events_block (*this); + } +}; - ~tree_classdef_enum_block (void) = default; +class tree_classdef_enum +{ +public: + + tree_classdef_enum (tree_identifier *i, tree_expression *e, + comment_list *comments); + + // No copying! - void accept (tree_walker& tw) - { - tw.visit_classdef_enum_block (*this); - } - }; + tree_classdef_enum (const tree_classdef_enum&) = delete; + + tree_classdef_enum& operator = (const tree_classdef_enum&) = delete; - class tree_classdef_body + ~tree_classdef_enum (void) { - public: + delete m_id; + delete m_expr; + } - typedef std::list::iterator - properties_list_iterator; - typedef std::list::const_iterator - properties_list_const_iterator; + tree_identifier * ident (void) { return m_id; } + + tree_expression * expression (void) { return m_expr; } + + comment_list * comments (void) const { return m_comments; } + + void doc_string (const std::string& txt) { m_doc_string = txt; } - typedef std::list::iterator - methods_list_iterator; - typedef std::list::const_iterator - methods_list_const_iterator; + std::string doc_string (void) const { return m_doc_string; } + + bool have_doc_string (void) const { return ! m_doc_string.empty (); } - typedef std::list::iterator events_list_iterator; - typedef std::list::const_iterator - events_list_const_iterator; + void accept (tree_walker& tw) + { + tw.visit_classdef_enum (*this); + } + +private: - typedef std::list::iterator enum_list_iterator; - typedef std::list::const_iterator - enum_list_const_iterator; + tree_identifier *m_id; + tree_expression *m_expr; + comment_list *m_comments; + std::string m_doc_string; +}; - tree_classdef_body (void); - - tree_classdef_body (tree_classdef_properties_block *pb); +class tree_classdef_enum_list : public base_list +{ +public: - tree_classdef_body (tree_classdef_methods_block *mb); + tree_classdef_enum_list (void) { } - tree_classdef_body (tree_classdef_events_block *evb); + tree_classdef_enum_list (tree_classdef_enum *e) { append (e); } - tree_classdef_body (tree_classdef_enum_block *enb); + tree_classdef_enum_list (const base_list& a) + : base_list (a) + { } - // No copying! + // No copying! - tree_classdef_body (const tree_classdef_body&) = delete; + tree_classdef_enum_list (const tree_classdef_enum_list&) = delete; - tree_classdef_body& operator = (const tree_classdef_body&) = delete; + tree_classdef_enum_list& operator = (const tree_classdef_enum_list&) = delete; + + ~tree_classdef_enum_list (void); - ~tree_classdef_body (void); - - void append (tree_classdef_properties_block *pb) - { - m_properties_lst.push_back (pb); - } + void accept (tree_walker& tw) + { + tw.visit_classdef_enum_list (*this); + } +}; - void append (tree_classdef_methods_block *mb) - { - m_methods_lst.push_back (mb); - } +class tree_classdef_enum_block + : public tree_classdef_element +{ +public: - void append (tree_classdef_events_block *evb) - { - m_events_lst.push_back (evb); - } + tree_classdef_enum_block (tree_classdef_attribute_list *a, + tree_classdef_enum_list *elist, + comment_list *lc, comment_list *tc, + int l = -1, int c = -1) + : tree_classdef_element (a, elist, lc, tc, l, c) + { } - void append (tree_classdef_enum_block *enb) - { - m_enum_lst.push_back (enb); - } + // No copying! + + tree_classdef_enum_block (const tree_classdef_enum_block&) = delete; + + tree_classdef_enum_block& + operator = (const tree_classdef_enum_block&) = delete; + + ~tree_classdef_enum_block (void) = default; - std::list properties_list (void) - { - return m_properties_lst; - } + void accept (tree_walker& tw) + { + tw.visit_classdef_enum_block (*this); + } +}; + +class tree_classdef_body +{ +public: - std::list methods_list (void) - { - return m_methods_lst; - } + typedef std::list::iterator + properties_list_iterator; + typedef std::list::const_iterator + properties_list_const_iterator; + + typedef std::list::iterator + methods_list_iterator; + typedef std::list::const_iterator + methods_list_const_iterator; - std::list events_list (void) - { - return m_events_lst; - } + typedef std::list::iterator events_list_iterator; + typedef std::list::const_iterator + events_list_const_iterator; + + typedef std::list::iterator enum_list_iterator; + typedef std::list::const_iterator + enum_list_const_iterator; + + tree_classdef_body (void); + + tree_classdef_body (tree_classdef_properties_block *pb); - std::list enum_list (void) - { - return m_enum_lst; - } + tree_classdef_body (tree_classdef_methods_block *mb); + + tree_classdef_body (tree_classdef_events_block *evb); + + tree_classdef_body (tree_classdef_enum_block *enb); - void doc_string (const std::string& txt) { m_doc_string = txt; } + // No copying! - std::string doc_string (void) const { return m_doc_string; } + tree_classdef_body (const tree_classdef_body&) = delete; - bool have_doc_string (void) const { return ! m_doc_string.empty (); } + tree_classdef_body& operator = (const tree_classdef_body&) = delete; - void accept (tree_walker& tw) - { - tw.visit_classdef_body (*this); - } + ~tree_classdef_body (void); + + void append (tree_classdef_properties_block *pb) + { + m_properties_lst.push_back (pb); + } - private: - - std::string get_doc_string (comment_list *comment) const; + void append (tree_classdef_methods_block *mb) + { + m_methods_lst.push_back (mb); + } - std::list m_properties_lst; - - std::list m_methods_lst; + void append (tree_classdef_events_block *evb) + { + m_events_lst.push_back (evb); + } - std::list m_events_lst; + void append (tree_classdef_enum_block *enb) + { + m_enum_lst.push_back (enb); + } - std::list m_enum_lst; + std::list properties_list (void) + { + return m_properties_lst; + } - std::string m_doc_string; - }; + std::list methods_list (void) + { + return m_methods_lst; + } - // Classdef definition. - - class tree_classdef : public tree_command + std::list events_list (void) { - public: + return m_events_lst; + } - tree_classdef (const symbol_scope& scope, - tree_classdef_attribute_list *a, tree_identifier *i, - tree_classdef_superclass_list *sc, - tree_classdef_body *b, comment_list *lc, - comment_list *tc, const std::string& pn = "", - const std::string& fn = "", int l = -1, int c = -1) - : tree_command (l, c), m_scope (scope), m_attr_list (a), m_id (i), - m_supclass_list (sc), m_element_list (b), m_lead_comm (lc), - m_trail_comm (tc), m_pack_name (pn), m_file_name (fn) - { } + std::list enum_list (void) + { + return m_enum_lst; + } + + void doc_string (const std::string& txt) { m_doc_string = txt; } + + std::string doc_string (void) const { return m_doc_string; } - // No copying! + bool have_doc_string (void) const { return ! m_doc_string.empty (); } + + void accept (tree_walker& tw) + { + tw.visit_classdef_body (*this); + } + +private: - tree_classdef (const tree_classdef&) = delete; + std::string get_doc_string (comment_list *comment) const; + + std::list m_properties_lst; - tree_classdef& operator = (const tree_classdef&) = delete; + std::list m_methods_lst; + + std::list m_events_lst; - ~tree_classdef (void) - { - delete m_attr_list; - delete m_id; - delete m_supclass_list; - delete m_element_list; - delete m_lead_comm; - delete m_trail_comm; - } + std::list m_enum_lst; + + std::string m_doc_string; +}; + +// Classdef definition. + +class tree_classdef : public tree_command +{ +public: - symbol_scope scope (void) { return m_scope; } - - tree_classdef_attribute_list * - attribute_list (void) { return m_attr_list; } + tree_classdef (const symbol_scope& scope, + tree_classdef_attribute_list *a, tree_identifier *i, + tree_classdef_superclass_list *sc, + tree_classdef_body *b, comment_list *lc, + comment_list *tc, const std::string& pn = "", + const std::string& fn = "", int l = -1, int c = -1) + : tree_command (l, c), m_scope (scope), m_attr_list (a), m_id (i), + m_supclass_list (sc), m_element_list (b), m_lead_comm (lc), + m_trail_comm (tc), m_pack_name (pn), m_file_name (fn) + { } - tree_identifier * ident (void) { return m_id; } + // No copying! - tree_classdef_superclass_list * - superclass_list (void) { return m_supclass_list; } + tree_classdef (const tree_classdef&) = delete; - tree_classdef_body * body (void) { return m_element_list; } + tree_classdef& operator = (const tree_classdef&) = delete; - comment_list * leading_comment (void) { return m_lead_comm; } - comment_list * trailing_comment (void) { return m_trail_comm; } - - std::string package_name (void) const { return m_pack_name; } - - std::string file_name (void) const { return m_file_name; } + ~tree_classdef (void) + { + delete m_attr_list; + delete m_id; + delete m_supclass_list; + delete m_element_list; + delete m_lead_comm; + delete m_trail_comm; + } - octave_value make_meta_class (interpreter& interp, - bool is_at_folder = false); + symbol_scope scope (void) { return m_scope; } + + tree_classdef_attribute_list * + attribute_list (void) { return m_attr_list; } - std::string doc_string (void) const - { - return m_element_list ? m_element_list->doc_string () : ""; - } + tree_identifier * ident (void) { return m_id; } + + tree_classdef_superclass_list * + superclass_list (void) { return m_supclass_list; } + + tree_classdef_body * body (void) { return m_element_list; } - void accept (tree_walker& tw) - { - tw.visit_classdef (*this); - } + comment_list * leading_comment (void) { return m_lead_comm; } + comment_list * trailing_comment (void) { return m_trail_comm; } + + std::string package_name (void) const { return m_pack_name; } + + std::string file_name (void) const { return m_file_name; } + + octave_value make_meta_class (interpreter& interp, + bool is_at_folder = false); - private: + std::string doc_string (void) const + { + return m_element_list ? m_element_list->doc_string () : ""; + } - // The scope that was used when parsing the classdef object and that - // corresponds to any identifiers that were found in attribute lists - // (for example). Used again when computing the meta class object. - - symbol_scope m_scope; + void accept (tree_walker& tw) + { + tw.visit_classdef (*this); + } - tree_classdef_attribute_list *m_attr_list; +private: - tree_identifier *m_id; + // The scope that was used when parsing the classdef object and that + // corresponds to any identifiers that were found in attribute lists + // (for example). Used again when computing the meta class object. - tree_classdef_superclass_list *m_supclass_list; + symbol_scope m_scope; + + tree_classdef_attribute_list *m_attr_list; - tree_classdef_body *m_element_list; + tree_identifier *m_id; + + tree_classdef_superclass_list *m_supclass_list; + + tree_classdef_body *m_element_list; - comment_list *m_lead_comm; - comment_list *m_trail_comm; + comment_list *m_lead_comm; + comment_list *m_trail_comm; - std::string m_pack_name; - std::string m_file_name; - }; + std::string m_pack_name; + std::string m_file_name; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-cmd.h --- a/libinterp/parse-tree/pt-cmd.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-cmd.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,94 +37,94 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // A base class for commands. +// A base class for commands. - class tree_command : public tree - { - public: +class tree_command : public tree +{ +public: - tree_command (int l = -1, int c = -1) - : tree (l, c) { } + tree_command (int l = -1, int c = -1) + : tree (l, c) { } - // No copying! + // No copying! - tree_command (const tree_command&) = delete; + tree_command (const tree_command&) = delete; - tree_command& operator = (const tree_command&) = delete; + tree_command& operator = (const tree_command&) = delete; - virtual ~tree_command (void) = default; - }; + virtual ~tree_command (void) = default; +}; - // No-op. +// No-op. - class tree_no_op_command : public tree_command - { - public: +class tree_no_op_command : public tree_command +{ +public: - tree_no_op_command (const std::string& cmd = "no_op", bool e = false, - int l = -1, int c = -1) - : tree_command (l, c), m_eof (e), m_orig_cmd (cmd) { } + tree_no_op_command (const std::string& cmd = "no_op", bool e = false, + int l = -1, int c = -1) + : tree_command (l, c), m_eof (e), m_orig_cmd (cmd) { } - // No copying! + // No copying! - tree_no_op_command (const tree_no_op_command&) = delete; + tree_no_op_command (const tree_no_op_command&) = delete; - tree_no_op_command& operator = (const tree_no_op_command&) = delete; + tree_no_op_command& operator = (const tree_no_op_command&) = delete; - ~tree_no_op_command (void) = default; + ~tree_no_op_command (void) = default; - void accept (tree_walker& tw) - { - tw.visit_no_op_command (*this); - } + void accept (tree_walker& tw) + { + tw.visit_no_op_command (*this); + } - bool is_end_of_fcn_or_script (void) const - { - return (m_orig_cmd == "endfunction" || m_orig_cmd == "endscript"); - } + bool is_end_of_fcn_or_script (void) const + { + return (m_orig_cmd == "endfunction" || m_orig_cmd == "endscript"); + } - bool is_end_of_file (void) const { return m_eof; } + bool is_end_of_file (void) const { return m_eof; } - std::string original_command (void) { return m_orig_cmd; } + std::string original_command (void) { return m_orig_cmd; } - private: +private: - bool m_eof; + bool m_eof; - std::string m_orig_cmd; - }; + std::string m_orig_cmd; +}; - // Function definition. +// Function definition. - class tree_function_def : public tree_command - { - public: +class tree_function_def : public tree_command +{ +public: - tree_function_def (octave_function *f, int l = -1, int c = -1) - : tree_command (l, c), m_fcn (f) { } + tree_function_def (octave_function *f, int l = -1, int c = -1) + : tree_command (l, c), m_fcn (f) { } - // No copying! + // No copying! - tree_function_def (const tree_function_def&) = delete; + tree_function_def (const tree_function_def&) = delete; - tree_function_def& operator = (const tree_function_def&) = delete; + tree_function_def& operator = (const tree_function_def&) = delete; - ~tree_function_def (void) = default; + ~tree_function_def (void) = default; - void accept (tree_walker& tw) - { - tw.visit_function_def (*this); - } + void accept (tree_walker& tw) + { + tw.visit_function_def (*this); + } - octave_value function (void) { return m_fcn; } + octave_value function (void) { return m_fcn; } - private: +private: - octave_value m_fcn; + octave_value m_fcn; - tree_function_def (const octave_value& v, int l = -1, int c = -1) - : tree_command (l, c), m_fcn (v) { } - }; + tree_function_def (const octave_value& v, int l = -1, int c = -1) + : tree_command (l, c), m_fcn (v) { } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-colon.cc --- a/libinterp/parse-tree/pt-colon.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-colon.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,47 +34,47 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Colon expressions. +// Colon expressions. - tree_expression * - tree_colon_expression::dup (symbol_scope& scope) const - { - tree_colon_expression *new_ce - = new tree_colon_expression (m_base ? m_base->dup (scope) : nullptr, - m_limit ? m_limit->dup (scope) : nullptr, - m_increment ? m_increment->dup (scope) - : nullptr, - line (), column ()); +tree_expression * +tree_colon_expression::dup (symbol_scope& scope) const +{ + tree_colon_expression *new_ce + = new tree_colon_expression (m_base ? m_base->dup (scope) : nullptr, + m_limit ? m_limit->dup (scope) : nullptr, + m_increment ? m_increment->dup (scope) + : nullptr, + line (), column ()); - new_ce->copy_base (*this); + new_ce->copy_base (*this); - return new_ce; - } + return new_ce; +} - octave_value tree_colon_expression::evaluate (tree_evaluator& tw, int) - { - octave_value val; +octave_value tree_colon_expression::evaluate (tree_evaluator& tw, int) +{ + octave_value val; - if (! m_base || ! m_limit) - return val; + if (! m_base || ! m_limit) + return val; - octave_value ov_base; - octave_value ov_increment; - octave_value ov_limit; + octave_value ov_base; + octave_value ov_increment; + octave_value ov_limit; - if (m_increment) - { - ov_base = m_base->evaluate (tw); - ov_increment = m_increment->evaluate (tw); - ov_limit = m_limit->evaluate (tw); - } - else - { - ov_base = m_base->evaluate (tw); - ov_limit = m_limit->evaluate (tw); - } + if (m_increment) + { + ov_base = m_base->evaluate (tw); + ov_increment = m_increment->evaluate (tw); + ov_limit = m_limit->evaluate (tw); + } + else + { + ov_base = m_base->evaluate (tw); + ov_limit = m_limit->evaluate (tw); + } - return colon_op (ov_base, ov_increment, ov_limit, is_for_cmd_expr ()); - } + return colon_op (ov_base, ov_increment, ov_limit, is_for_cmd_expr ()); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-colon.h --- a/libinterp/parse-tree/pt-colon.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-colon.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,80 +38,80 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; +class symbol_scope; - // Colon expressions. +// Colon expressions. - class tree_colon_expression : public tree_expression - { - public: +class tree_colon_expression : public tree_expression +{ +public: - tree_colon_expression (int l = -1, int c = -1) - : tree_expression (l, c), m_base (nullptr), m_limit (nullptr), - m_increment (nullptr), m_save_base (false) { } + tree_colon_expression (int l = -1, int c = -1) + : tree_expression (l, c), m_base (nullptr), m_limit (nullptr), + m_increment (nullptr), m_save_base (false) { } - tree_colon_expression (tree_expression *bas, tree_expression *lim, - int l = -1, int c = -1) - : tree_expression (l, c), m_base (bas), m_limit (lim), - m_increment (nullptr), m_save_base (false) { } + tree_colon_expression (tree_expression *bas, tree_expression *lim, + int l = -1, int c = -1) + : tree_expression (l, c), m_base (bas), m_limit (lim), + m_increment (nullptr), m_save_base (false) { } - tree_colon_expression (tree_expression *bas, tree_expression *lim, - tree_expression *inc, int l = -1, int c = -1) - : tree_expression (l, c), m_base (bas), m_limit (lim), - m_increment (inc), m_save_base (false) { } + tree_colon_expression (tree_expression *bas, tree_expression *lim, + tree_expression *inc, int l = -1, int c = -1) + : tree_expression (l, c), m_base (bas), m_limit (lim), + m_increment (inc), m_save_base (false) { } - // No copying! + // No copying! - tree_colon_expression (const tree_colon_expression&) = delete; + tree_colon_expression (const tree_colon_expression&) = delete; - tree_colon_expression& operator = (const tree_colon_expression&) = delete; + tree_colon_expression& operator = (const tree_colon_expression&) = delete; - ~tree_colon_expression (void) - { - if (! m_save_base) - delete m_base; + ~tree_colon_expression (void) + { + if (! m_save_base) + delete m_base; - delete m_limit; - delete m_increment; - } + delete m_limit; + delete m_increment; + } - void preserve_base (void) { m_save_base = true; } + void preserve_base (void) { m_save_base = true; } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - void eval_error (const std::string& s) const; + void eval_error (const std::string& s) const; - tree_expression * base (void) { return m_base; } + tree_expression * base (void) { return m_base; } - tree_expression * limit (void) { return m_limit; } + tree_expression * limit (void) { return m_limit; } - tree_expression * increment (void) { return m_increment; } + tree_expression * increment (void) { return m_increment; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - bool is_colon_expression (void) const { return true; } + bool is_colon_expression (void) const { return true; } - octave_value evaluate (tree_evaluator&, int nargout = 1); + octave_value evaluate (tree_evaluator&, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) - { - tw.visit_colon_expression (*this); - } + void accept (tree_walker& tw) + { + tw.visit_colon_expression (*this); + } - private: +private: - // The components of the expression. - tree_expression *m_base; - tree_expression *m_limit; - tree_expression *m_increment; + // The components of the expression. + tree_expression *m_base; + tree_expression *m_limit; + tree_expression *m_increment; - bool m_save_base; - }; + bool m_save_base; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-const.cc --- a/libinterp/parse-tree/pt-const.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-const.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,38 +37,38 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // We are likely to have a lot of tree_constant objects to allocate, - // so make the grow_size large. +// We are likely to have a lot of tree_constant objects to allocate, +// so make the grow_size large. - void - tree_constant::print (std::ostream& os, bool pr_as_read_syntax, - bool pr_orig_text) - { - if (pr_orig_text && ! m_orig_text.empty ()) - os << m_orig_text; - else - m_value.print (os, pr_as_read_syntax); - } +void +tree_constant::print (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + if (pr_orig_text && ! m_orig_text.empty ()) + os << m_orig_text; + else + m_value.print (os, pr_as_read_syntax); +} - void - tree_constant::print_raw (std::ostream& os, bool pr_as_read_syntax, - bool pr_orig_text) - { - if (pr_orig_text && ! m_orig_text.empty ()) - os << m_orig_text; - else - m_value.print_raw (os, pr_as_read_syntax); - } +void +tree_constant::print_raw (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + if (pr_orig_text && ! m_orig_text.empty ()) + os << m_orig_text; + else + m_value.print_raw (os, pr_as_read_syntax); +} - tree_expression * - tree_constant::dup (symbol_scope&) const - { - tree_constant *new_tc - = new tree_constant (m_value, m_orig_text, line (), column ()); +tree_expression * +tree_constant::dup (symbol_scope&) const +{ + tree_constant *new_tc + = new tree_constant (m_value, m_orig_text, line (), column ()); - new_tc->copy_base (*this); + new_tc->copy_base (*this); - return new_tc; - } + return new_tc; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-const.h --- a/libinterp/parse-tree/pt-const.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-const.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,85 +41,85 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_evaluator; +class symbol_scope; +class tree_evaluator; - class tree_constant : public tree_expression - { - public: +class tree_constant : public tree_expression +{ +public: - tree_constant (int l = -1, int c = -1) - : tree_expression (l, c), m_value (), m_orig_text () - { } + tree_constant (int l = -1, int c = -1) + : tree_expression (l, c), m_value (), m_orig_text () + { } - tree_constant (const octave_value& v, int l = -1, int c = -1) - : tree_expression (l, c), m_value (v), m_orig_text () - { } + tree_constant (const octave_value& v, int l = -1, int c = -1) + : tree_expression (l, c), m_value (v), m_orig_text () + { } - tree_constant (const octave_value& v, const std::string& ot, - int l = -1, int c = -1) - : tree_expression (l, c), m_value (v), m_orig_text (ot) - { } + tree_constant (const octave_value& v, const std::string& ot, + int l = -1, int c = -1) + : tree_expression (l, c), m_value (v), m_orig_text (ot) + { } - // No copying! + // No copying! - tree_constant (const tree_constant&) = delete; + tree_constant (const tree_constant&) = delete; - tree_constant& operator = (const tree_constant&) = delete; + tree_constant& operator = (const tree_constant&) = delete; - ~tree_constant (void) = default; + ~tree_constant (void) = default; - // Type. It would be nice to eliminate the need for this. + // Type. It would be nice to eliminate the need for this. - bool is_constant (void) const { return true; } + bool is_constant (void) const { return true; } - void maybe_mutate (void) { m_value.maybe_mutate (); } + void maybe_mutate (void) { m_value.maybe_mutate (); } - void print (std::ostream& os, bool pr_as_read_syntax = false, - bool pr_orig_txt = true); + void print (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); - void print_raw (std::ostream& os, bool pr_as_read_syntax = false, - bool pr_orig_txt = true); + void print_raw (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - octave_value value (void) { return m_value; } + octave_value value (void) { return m_value; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - void accept (tree_walker& tw) - { - tw.visit_constant (*this); - } + void accept (tree_walker& tw) + { + tw.visit_constant (*this); + } - // Store the original text corresponding to this constant for later - // pretty printing. + // Store the original text corresponding to this constant for later + // pretty printing. - void stash_original_text (const std::string& s) { m_orig_text = s; } + void stash_original_text (const std::string& s) { m_orig_text = s; } - std::string original_text (void) const { return m_orig_text; } + std::string original_text (void) const { return m_orig_text; } - octave_value evaluate (tree_evaluator&, int nargout = 1) - { - if (nargout > 1) - error ("invalid number of output arguments for constant expression"); + octave_value evaluate (tree_evaluator&, int nargout = 1) + { + if (nargout > 1) + error ("invalid number of output arguments for constant expression"); - return value (); - } + return value (); + } - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - private: +private: - // The actual value that this constant refers to. - octave_value m_value; + // The actual value that this constant refers to. + octave_value m_value; - // The original text form of this constant. - std::string m_orig_text; - }; + // The original text form of this constant. + std::string m_orig_text; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-decl.cc --- a/libinterp/parse-tree/pt-decl.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-decl.cc Thu Dec 01 20:05:44 2022 -0800 @@ -42,51 +42,51 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Declarations (global, static, etc.). +// Declarations (global, static, etc.). - tree_decl_elt::tree_decl_elt (tree_identifier *i, tree_expression *e) - : type (unknown), m_id (i), m_expr (e) - { - if (! m_id) - error ("tree_decl_elt: invalid ID"); - } +tree_decl_elt::tree_decl_elt (tree_identifier *i, tree_expression *e) + : type (unknown), m_id (i), m_expr (e) +{ + if (! m_id) + error ("tree_decl_elt: invalid ID"); +} - tree_decl_elt::~tree_decl_elt (void) - { - delete m_id; - delete m_expr; - } +tree_decl_elt::~tree_decl_elt (void) +{ + delete m_id; + delete m_expr; +} - tree_decl_elt * - tree_decl_elt::dup (symbol_scope& scope) const - { - return new tree_decl_elt (m_id->dup (scope), - m_expr ? m_expr->dup (scope) : nullptr); - } +tree_decl_elt * +tree_decl_elt::dup (symbol_scope& scope) const +{ + return new tree_decl_elt (m_id->dup (scope), + m_expr ? m_expr->dup (scope) : nullptr); +} - // Initializer lists for declaration statements. +// Initializer lists for declaration statements. - // Declaration commands (global, static). +// Declaration commands (global, static). - tree_decl_command::tree_decl_command (const std::string& n, - tree_decl_init_list *t, int l, int c) - : tree_command (l, c), m_cmd_name (n), m_init_list (t) - { - if (t) - { - if (m_cmd_name == "global") - mark_global (); - else if (m_cmd_name == "persistent") - mark_persistent (); - else - error ("tree_decl_command: unknown decl type: %s", - m_cmd_name.c_str ()); - } - } +tree_decl_command::tree_decl_command (const std::string& n, + tree_decl_init_list *t, int l, int c) + : tree_command (l, c), m_cmd_name (n), m_init_list (t) +{ + if (t) + { + if (m_cmd_name == "global") + mark_global (); + else if (m_cmd_name == "persistent") + mark_persistent (); + else + error ("tree_decl_command: unknown decl type: %s", + m_cmd_name.c_str ()); + } +} - tree_decl_command::~tree_decl_command (void) - { - delete m_init_list; - } +tree_decl_command::~tree_decl_command (void) +{ + delete m_init_list; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-decl.h --- a/libinterp/parse-tree/pt-decl.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-decl.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,182 +39,182 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_evaluator; - class tree_expression; - class tree_identifier; - - // List of expressions that make up a declaration statement. - - class tree_decl_elt - { - public: +class symbol_scope; +class tree_evaluator; +class tree_expression; +class tree_identifier; - enum decl_type - { - unknown, - global, - persistent - }; - - tree_decl_elt (tree_identifier *i, tree_expression *e = nullptr); - - // No copying! - - tree_decl_elt (const tree_decl_elt&) = delete; - - tree_decl_elt& operator = (const tree_decl_elt&) = delete; - - ~tree_decl_elt (void); - - void mark_as_formal_parameter (void) - { - m_id->mark_as_formal_parameter (); - } +// List of expressions that make up a declaration statement. - bool lvalue_ok (void) { return m_id->lvalue_ok (); } - - octave_lvalue lvalue (tree_evaluator& tw) - { - return m_id->lvalue (tw); - } - - void mark_global (void) { type = global; } - bool is_global (void) const { return type == global; } - - void mark_persistent (void) { type = persistent; } - bool is_persistent (void) const { return type == persistent; } - - tree_identifier * ident (void) { return m_id; } - - std::string name (void) const { return m_id->name (); } +class tree_decl_elt +{ +public: - tree_expression * expression (void) { return m_expr; } - - tree_decl_elt * dup (symbol_scope& scope) const; - - void accept (tree_walker& tw) - { - tw.visit_decl_elt (*this); - } - - private: - - decl_type type; - - // An identifier to tag with the declared property. - tree_identifier *m_id; - - // An initializer expression (may be zero); - tree_expression *m_expr; + enum decl_type + { + unknown, + global, + persistent }; - class tree_decl_init_list : public base_list - { - public: + tree_decl_elt (tree_identifier *i, tree_expression *e = nullptr); + + // No copying! - tree_decl_init_list (void) { } + tree_decl_elt (const tree_decl_elt&) = delete; + + tree_decl_elt& operator = (const tree_decl_elt&) = delete; - tree_decl_init_list (tree_decl_elt *t) { append (t); } + ~tree_decl_elt (void); - // No copying! + void mark_as_formal_parameter (void) + { + m_id->mark_as_formal_parameter (); + } - tree_decl_init_list (const tree_decl_init_list&) = delete; + bool lvalue_ok (void) { return m_id->lvalue_ok (); } - tree_decl_init_list& operator = (const tree_decl_init_list&) = delete; + octave_lvalue lvalue (tree_evaluator& tw) + { + return m_id->lvalue (tw); + } + + void mark_global (void) { type = global; } + bool is_global (void) const { return type == global; } - ~tree_decl_init_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } + void mark_persistent (void) { type = persistent; } + bool is_persistent (void) const { return type == persistent; } + + tree_identifier * ident (void) { return m_id; } + + std::string name (void) const { return m_id->name (); } + + tree_expression * expression (void) { return m_expr; } + + tree_decl_elt * dup (symbol_scope& scope) const; - void mark_global (void) - { - for (tree_decl_elt *elt : *this) - elt->mark_global (); - } + void accept (tree_walker& tw) + { + tw.visit_decl_elt (*this); + } + +private: + + decl_type type; - void mark_persistent (void) - { - for (tree_decl_elt *elt : *this) - elt->mark_persistent (); - } + // An identifier to tag with the declared property. + tree_identifier *m_id; + + // An initializer expression (may be zero); + tree_expression *m_expr; +}; + +class tree_decl_init_list : public base_list +{ +public: - std::list variable_names (void) const - { - std::list retval; + tree_decl_init_list (void) { } + + tree_decl_init_list (tree_decl_elt *t) { append (t); } + + // No copying! + + tree_decl_init_list (const tree_decl_init_list&) = delete; + + tree_decl_init_list& operator = (const tree_decl_init_list&) = delete; - for (const tree_decl_elt *elt : *this) - { - std::string nm = elt->name (); - - if (! nm.empty ()) - retval.push_back (nm); - } - - return retval; - } + ~tree_decl_init_list (void) + { + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } + } - void accept (tree_walker& tw) - { - tw.visit_decl_init_list (*this); - } - }; + void mark_global (void) + { + for (tree_decl_elt *elt : *this) + elt->mark_global (); + } - // Base class for declaration commands -- global, static, etc. + void mark_persistent (void) + { + for (tree_decl_elt *elt : *this) + elt->mark_persistent (); + } - class tree_decl_command : public tree_command + std::list variable_names (void) const { - public: + std::list retval; - tree_decl_command (const std::string& n, int l = -1, int c = -1) - : tree_command (l, c), m_cmd_name (n), m_init_list (nullptr) { } + for (const tree_decl_elt *elt : *this) + { + std::string nm = elt->name (); - tree_decl_command (const std::string& n, tree_decl_init_list *t, - int l = -1, int c = -1); + if (! nm.empty ()) + retval.push_back (nm); + } + + return retval; + } - // No copying! - - tree_decl_command (const tree_decl_command&) = delete; + void accept (tree_walker& tw) + { + tw.visit_decl_init_list (*this); + } +}; - tree_decl_command& operator = (const tree_decl_command&) = delete; +// Base class for declaration commands -- global, static, etc. - ~tree_decl_command (void); +class tree_decl_command : public tree_command +{ +public: - void mark_global (void) - { - if (m_init_list) - m_init_list->mark_global (); - } + tree_decl_command (const std::string& n, int l = -1, int c = -1) + : tree_command (l, c), m_cmd_name (n), m_init_list (nullptr) { } + + tree_decl_command (const std::string& n, tree_decl_init_list *t, + int l = -1, int c = -1); + + // No copying! + + tree_decl_command (const tree_decl_command&) = delete; - void mark_persistent (void) - { - if (m_init_list) - m_init_list->mark_persistent (); - } + tree_decl_command& operator = (const tree_decl_command&) = delete; + + ~tree_decl_command (void); - tree_decl_init_list * initializer_list (void) { return m_init_list; } + void mark_global (void) + { + if (m_init_list) + m_init_list->mark_global (); + } - std::string name (void) const { return m_cmd_name; } + void mark_persistent (void) + { + if (m_init_list) + m_init_list->mark_persistent (); + } - void accept (tree_walker& tw) - { - tw.visit_decl_command (*this); - } + tree_decl_init_list * initializer_list (void) { return m_init_list; } + + std::string name (void) const { return m_cmd_name; } - private: + void accept (tree_walker& tw) + { + tw.visit_decl_command (*this); + } + +private: - // The name of this command -- global, static, etc. - std::string m_cmd_name; + // The name of this command -- global, static, etc. + std::string m_cmd_name; - // The list of variables or initializers in this declaration command. - tree_decl_init_list *m_init_list; - }; + // The list of variables or initializers in this declaration command. + tree_decl_init_list *m_init_list; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-eval.cc diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-eval.h --- a/libinterp/parse-tree/pt-eval.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-eval.h Thu Dec 01 20:05:44 2022 -0800 @@ -52,955 +52,955 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_info_list; - class symbol_scope; - class tree_decl_elt; - class tree_expression; +class symbol_info_list; +class symbol_scope; +class tree_decl_elt; +class tree_expression; + +class debugger; +class interpreter; +class push_parser; +class unwind_protect; + +// How to evaluate the code that the parse trees represent. - class debugger; - class interpreter; - class push_parser; - class unwind_protect; +class OCTINTERP_API tree_evaluator : public tree_walker +{ +public: - // How to evaluate the code that the parse trees represent. + enum echo_state + { + ECHO_OFF = 0, + ECHO_SCRIPTS = 1, + ECHO_FUNCTIONS = 2, + ECHO_ALL = 4 + }; - class OCTINTERP_API tree_evaluator : public tree_walker + template + class value_stack { public: - enum echo_state - { - ECHO_OFF = 0, - ECHO_SCRIPTS = 1, - ECHO_FUNCTIONS = 2, - ECHO_ALL = 4 - }; - - template - class value_stack - { - public: - - value_stack (void) = default; - - value_stack (const value_stack&) = default; - - value_stack& operator = (const value_stack&) = default; - - ~value_stack (void) = default; - - void push (const T& val) { m_stack.push (val); } - - void pop (void) - { - m_stack.pop (); - } - - T val_pop (void) - { - T retval = m_stack.top (); - m_stack.pop (); - return retval; - } - - T top (void) const - { - return m_stack.top (); - } - - std::size_t size (void) const - { - return m_stack.size (); - } - - bool empty (void) const - { - return m_stack.empty (); - } - - void clear (void) - { - while (! m_stack.empty ()) - m_stack.pop (); - } - - private: - - std::stack m_stack; - }; - - typedef void (*decl_elt_init_fcn) (tree_decl_elt&); - - tree_evaluator (interpreter& interp) - : m_interpreter (interp), m_parser (), m_statement_context (SC_OTHER), - m_lvalue_list (nullptr), m_autoload_map (), m_bp_table (*this), - m_call_stack (*this), m_profiler (), m_debug_frame (0), - m_debug_mode (false), m_quiet_breakpoint_flag (false), - m_debugger_stack (), m_exit_status (0), m_max_recursion_depth (256), - m_whos_line_format (" %la:5; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;\n"), - m_silent_functions (false), m_string_fill_char (' '), m_PS4 ("+ "), - m_dbstep_flag (0), m_break_on_next_stmt (false), m_echo (ECHO_OFF), - m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1), - m_echo_files (), m_in_top_level_repl (false), - m_server_mode (false), m_in_loop_command (false), - m_breaking (0), m_continuing (0), m_returning (0), - m_indexed_object (), m_index_list (), m_index_type (), - m_index_position (0), m_num_indices (0) - { } - - // No copying! - - tree_evaluator (const tree_evaluator&) = delete; - - tree_evaluator& operator = (const tree_evaluator&) = delete; - - ~tree_evaluator (void) = default; - - std::shared_ptr get_parser (void) - { - return m_parser; - } + value_stack (void) = default; - void set_parser (const std::shared_ptr& parser) - { - m_parser = parser; - } - - bool at_top_level (void) const; - - std::string mfilename (const std::string& opt = "") const; - - // Parse a line of input. If input ends at a complete statement - // boundary, execute the resulting parse tree. Useful to handle - // parsing user input when running in server mode. - - void parse_and_execute (const std::string& input, bool& incomplete_parse); - - void get_line_and_eval (void); - - int repl (void); - - bool in_top_level_repl (void) const { return m_in_top_level_repl; } - - int server_loop (void); - - bool server_mode (void) const { return m_server_mode; } - - void server_mode (bool arg) { m_server_mode = arg; } - - void eval (std::shared_ptr& stmt_list, - bool interactive); - - octave_value_list eval_string (const std::string& eval_str, bool silent, - int& parse_status, int nargout); - - octave_value eval_string (const std::string& eval_str, bool silent, - int& parse_status); - - octave_value_list eval_string (const octave_value& arg, bool silent, - int& parse_status, int nargout); - - octave_value_list eval (const std::string& try_code, int nargout); - - octave_value_list eval (const std::string& try_code, - const std::string& catch_code, int nargout); - - octave_value_list evalin (const std::string& context, - const std::string& try_code, int nargout); + value_stack (const value_stack&) = default; - octave_value_list evalin (const std::string& context, - const std::string& try_code, - const std::string& catch_code, int nargout); - - void visit_anon_fcn_handle (tree_anon_fcn_handle&); - - void visit_argument_list (tree_argument_list&); - - void visit_arguments_block (tree_arguments_block&); - - void visit_args_block_attribute_list (tree_args_block_attribute_list&); - - void visit_args_block_validation_list (tree_args_block_validation_list&); - - void visit_arg_validation (tree_arg_validation&); - - void visit_arg_size_spec (tree_arg_size_spec&); - - void visit_arg_validation_fcns (tree_arg_validation_fcns&); - - void visit_binary_expression (tree_binary_expression&); - - void visit_boolean_expression (tree_boolean_expression&); - - void visit_compound_binary_expression (tree_compound_binary_expression&); - - void visit_break_command (tree_break_command&); - - void visit_colon_expression (tree_colon_expression&); - - void visit_continue_command (tree_continue_command&); - - void visit_decl_command (tree_decl_command&); - - void visit_decl_elt (tree_decl_elt&); - - void visit_simple_for_command (tree_simple_for_command&); - - void visit_complex_for_command (tree_complex_for_command&); - - void visit_spmd_command (tree_spmd_command&); - - octave_value evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh); - - octave_value_list - execute_builtin_function (octave_builtin& builtin_function, int nargout, - const octave_value_list& args); - octave_value_list - execute_mex_function (octave_mex_function& mex_function, int nargout, - const octave_value_list& args); - - void visit_octave_user_script (octave_user_script&); + value_stack& operator = (const value_stack&) = default; - octave_value_list - execute_user_script (octave_user_script& user_script, int nargout, - const octave_value_list& args); - - void visit_octave_user_function (octave_user_function&); - - octave_value_list - execute_user_function (octave_user_function& user_function, - int nargout, const octave_value_list& args); - - void visit_octave_user_function_header (octave_user_function&); - - void visit_octave_user_function_trailer (octave_user_function&); - - void visit_function_def (tree_function_def&); - - void visit_identifier (tree_identifier&); - - void visit_if_clause (tree_if_clause&); - - void visit_if_command (tree_if_command&); - - void visit_if_command_list (tree_if_command_list&); - - void visit_index_expression (tree_index_expression&); - - void visit_matrix (tree_matrix&); - - void visit_cell (tree_cell&); - - void visit_multi_assignment (tree_multi_assignment&); - - void visit_no_op_command (tree_no_op_command&); - - void visit_constant (tree_constant&); - - void visit_fcn_handle (tree_fcn_handle&); - - void visit_parameter_list (tree_parameter_list&); - - void visit_postfix_expression (tree_postfix_expression&); - - void visit_prefix_expression (tree_prefix_expression&); - - void visit_return_command (tree_return_command&); - - void visit_simple_assignment (tree_simple_assignment&); + ~value_stack (void) = default; - void visit_statement (tree_statement&); - - void visit_statement_list (tree_statement_list&); - - void visit_switch_case (tree_switch_case&); - - void visit_switch_case_list (tree_switch_case_list&); - - void visit_switch_command (tree_switch_command&); - - void visit_try_catch_command (tree_try_catch_command&); - - void do_unwind_protect_cleanup_code (tree_statement_list *list); - - void visit_unwind_protect_command (tree_unwind_protect_command&); - - void visit_while_command (tree_while_command&); - void visit_do_until_command (tree_do_until_command&); - - void visit_superclass_ref (tree_superclass_ref&); - void visit_metaclass_query (tree_metaclass_query&); - - void bind_ans (const octave_value& val, bool print); - - bool statement_printing_enabled (void); - - void reset_debug_state (void); - - void reset_debug_state (bool mode); - - void enter_debugger (const std::string& prompt = "debug> "); - - void keyboard (const std::string& prompt = "keyboard> "); - - void dbupdown (int n, bool verbose = false); - - // Possible types of evaluation contexts. - enum stmt_list_type - { - SC_FUNCTION, // function body - SC_SCRIPT, // script file - SC_OTHER // command-line input or eval string - }; - - Matrix ignored_fcn_outputs (void) const; - - octave_value make_fcn_handle (const std::string& nm); + void push (const T& val) { m_stack.push (val); } - octave_value evaluate (tree_decl_elt *); - - void install_variable (const std::string& name, - const octave_value& value, bool global); - - octave_value global_varval (const std::string& name) const; - - octave_value& global_varref (const std::string& name); - - void global_assign (const std::string& name, - const octave_value& val = octave_value ()); - - octave_value top_level_varval (const std::string& name) const; - - void top_level_assign (const std::string& name, - const octave_value& val = octave_value ()); - - bool is_variable (const std::string& name) const; - - bool is_local_variable (const std::string& name) const; - - bool is_variable (const tree_expression *expr) const; - - bool is_defined (const tree_expression *expr) const; - - bool is_variable (const symbol_record& sym) const; - - bool is_defined (const symbol_record& sym) const; - - bool is_global (const std::string& name) const; - - octave_value varval (const symbol_record& sym) const; - - octave_value varval (const std::string& name) const; - - void assign (const std::string& name, - const octave_value& val = octave_value ()); - - void assignin (const std::string& context, const std::string& name, - const octave_value& val = octave_value ()); - - void source_file (const std::string& file_name, - const std::string& context = "", - bool verbose = false, bool require_file = true); - - void set_auto_fcn_var (stack_frame::auto_var_type avt, - const octave_value& val = octave_value ()); - - octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const; - - void define_parameter_list_from_arg_vector - (tree_parameter_list *param_list, const octave_value_list& args); - - void undefine_parameter_list (tree_parameter_list *param_list); - - octave_value_list convert_to_const_vector (tree_argument_list *arg_list); - - octave_value_list - convert_return_list_to_const_vector - (tree_parameter_list *ret_list, int nargout, - const Matrix& ignored_outputs, const Cell& varargout); - - bool eval_decl_elt (tree_decl_elt *elt); - - bool switch_case_label_matches (tree_switch_case *expr, - const octave_value& val); - - interpreter& get_interpreter (void) { return m_interpreter; } - - bp_table& get_bp_table (void) { return m_bp_table; } - - profiler& get_profiler (void) { return m_profiler; } - - void push_stack_frame (const symbol_scope& scope); - - void push_stack_frame (octave_user_function *fcn, - const std::shared_ptr& closure_frames = std::shared_ptr ()); - - void push_stack_frame (octave_user_function *fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& closure_frames = std::shared_ptr ()); - - void push_stack_frame (octave_user_script *script); - - void push_stack_frame (octave_function *fcn); - - void pop_stack_frame (void); - - std::shared_ptr get_current_stack_frame (void) const + void pop (void) { - return m_call_stack.get_current_stack_frame (); - } - - std::shared_ptr current_user_frame (void) const - { - return m_call_stack.current_user_frame (); + m_stack.pop (); } - // Current line in current function. - int current_line (void) const; - - // Current column in current function. - int current_column (void) const; - - // Line number in current function that we are debugging. - int debug_user_code_line (void) const; - - // Column number in current function that we are debugging. - int debug_user_code_column (void) const; - - void debug_where (std::ostream& os) const; - - octave_user_code * current_user_code (void) const; - - unwind_protect * curr_fcn_unwind_protect_frame (void); - - // Current function that we are debugging. - octave_user_code * debug_user_code (void) const; - - octave_function * current_function (bool skip_first = false) const; - - octave_function * caller_function (void) const; - - bool goto_frame (std::size_t n = 0, bool verbose = false); - - void goto_caller_frame (void); - - void goto_base_frame (void); - - void restore_frame (std::size_t n); - - std::string get_dispatch_class (void) const; - - void set_dispatch_class (const std::string& class_name); - - bool is_class_method_executing (std::string& dispatch_class) const; - - bool is_class_constructor_executing (std::string& dispatch_class) const; - - std::list> - backtrace_frames (octave_idx_type& curr_user_frame) const; - - std::list> backtrace_frames () const; - - std::list backtrace_info (octave_idx_type& curr_user_frame, - bool print_subfn = true) const; - - std::list backtrace_info (void) const; - - octave_map backtrace (octave_idx_type& curr_user_frame, - bool print_subfn = true) const; - - octave_map backtrace (void) const; - - octave_map empty_backtrace (void) const; - - std::string backtrace_message (void) const; - - void push_dummy_scope (const std::string& name); - void pop_scope (void); - - symbol_scope get_top_scope (void) const; - symbol_scope get_current_scope (void) const; - - void mlock (bool skip_first = false) const; - - void munlock (bool skip_first = false) const; - - bool mislocked (bool skip_first = false) const; - - octave_value max_stack_depth (const octave_value_list& args, int nargout); - - // Useful for debugging - void display_call_stack (void) const; - - octave_value find (const std::string& name); - - void clear_objects (void); - - void clear_variable (const std::string& name); - - void clear_variable_pattern (const std::string& pattern); - - void clear_variable_regexp (const std::string& pattern); - - void clear_variables (void); - - void clear_global_variable (const std::string& name); - - void clear_global_variable_pattern (const std::string& pattern); - - void clear_global_variable_regexp (const std::string& pattern); - - void clear_global_variables (void); - - void clear_all (bool force = false); - - void clear_symbol (const std::string& name); - - void clear_symbol_pattern (const std::string& pattern); - - void clear_symbol_regexp (const std::string& pattern); - - std::list global_variable_names (void) const; - - std::list top_level_variable_names (void) const; - - std::list variable_names (void) const; - - octave_user_code * get_user_code (const std::string& fname = "", - const std::string& class_name = ""); - - std::string current_function_name (bool skip_first = false) const; - - bool in_user_code (void) const; - - symbol_info_list glob_symbol_info (const std::string& pattern) const; - - symbol_info_list regexp_symbol_info (const std::string& pattern) const; - - symbol_info_list get_symbol_info (void); - - symbol_info_list top_scope_symbol_info (void) const; - - octave_map get_autoload_map (void) const; - - std::string lookup_autoload (const std::string& nm) const; - - std::list autoloaded_functions (void) const; - - std::list reverse_lookup_autoload (const std::string& nm) const; - - void add_autoload (const std::string& fcn, const std::string& nm); - - void remove_autoload (const std::string& fcn, const std::string& nm); - - int max_recursion_depth (void) const { return m_max_recursion_depth; } - - int max_recursion_depth (int n) + T val_pop (void) { - int val = m_max_recursion_depth; - m_max_recursion_depth = n; - return val; + T retval = m_stack.top (); + m_stack.pop (); + return retval; } - octave_value - max_recursion_depth (const octave_value_list& args, int nargout); - - bool silent_functions (void) const { return m_silent_functions; } - - bool silent_functions (bool b) - { - int val = m_silent_functions; - m_silent_functions = b; - return val; - } - - octave_value whos_line_format (const octave_value_list& args, int nargout); - - std::string whos_line_format (void) const { return m_whos_line_format; } - - std::string whos_line_format (const std::string& s) + T top (void) const { - std::string val = m_whos_line_format; - m_whos_line_format = s; - return val; - } - - octave_value - silent_functions (const octave_value_list& args, int nargout); - - std::size_t debug_frame (void) const { return m_debug_frame; } - - std::size_t debug_frame (std::size_t n) - { - std::size_t val = m_debug_frame; - m_debug_frame = n; - return val; - } - - std::size_t current_call_stack_frame_number (void) const - { - return m_call_stack.current_frame (); - } - - bool quiet_breakpoint_flag (void) const { return m_quiet_breakpoint_flag; } - - bool quiet_breakpoint_flag (bool flag) - { - bool val = m_quiet_breakpoint_flag; - m_quiet_breakpoint_flag = flag; - return val; + return m_stack.top (); } - char string_fill_char (void) const { return m_string_fill_char; } - - char string_fill_char (char c) - { - int val = m_string_fill_char; - m_string_fill_char = c; - return val; - } - - // The following functions are provided for convenience. They - // call the corresponding functions in the debugger class for the - // current debugger (if any). - - bool in_debug_repl (void) const; - - void dbcont (void); - - // Return true if we are in the debug repl and m_execution_mode is - // set to exit the debugger. Otherwise, do nothing. - - void dbquit (bool all = false); - - // Add EXPR to the set of expressions that may be evaluated when the - // debugger stops at a breakpoint. - void add_debug_watch_expression (const std::string& expr) - { - m_debug_watch_expressions.insert (expr); - } - - // Remove EXPR from the set of expressions that may be evaluated - // when the debugger stops at a breakpoint. - void remove_debug_watch_expression (const std::string& expr) - { - m_debug_watch_expressions.erase (expr); - } - - // Clear the set of expressions that may be evaluated when the - // debugger stops at a breakpoint. - void clear_debug_watch_expressions (void) - { - m_debug_watch_expressions.clear (); - } - - // Return the set of expressions that may be evaluated when the - // debugger stops at a breakpoint. - std::set debug_watch_expressions (void) const + std::size_t size (void) const { - return m_debug_watch_expressions; - } - - octave_value PS4 (const octave_value_list& args, int nargout); - - std::string PS4 (void) const { return m_PS4; } - - std::string PS4 (const std::string& s) - { - std::string val = m_PS4; - m_PS4 = s; - return val; - } - - octave_value indexed_object (void) const - { - return m_indexed_object; - } - - void set_indexed_object (const octave_value& obj = octave_value ()) - { - m_indexed_object = obj; - } - - const std::list& index_list (void) const - { - return m_index_list; - } - - void set_index_list (const std::string& index_type, - const std::list& index_list) - { - m_index_type = index_type; - m_index_list = index_list; - } - - void clear_index_list (void) - { - m_index_type = ""; - m_index_list.clear (); - } - - void append_index_list (char type, const octave_value_list& idx) - { - m_index_type += type; - m_index_list.push_back (idx); + return m_stack.size (); } - const std::string& index_type (void) const - { - return m_index_type; - } - - int index_position (void) const { return m_index_position; } - - int num_indices (void) const { return m_num_indices; } - - octave_value_list evaluate_end_expression (const octave_value_list& args); - - const std::list * lvalue_list (void) const - { - return m_lvalue_list; - } - - void set_lvalue_list (const std::list *lst) + bool empty (void) const { - m_lvalue_list = lst; - } - - int breaking (void) const { return m_breaking; } - - int breaking (int n) - { - int val = m_breaking; - m_breaking = n; - return val; - } - - int continuing (void) const { return m_continuing; } - - int continuing (int n) - { - int val = m_continuing; - m_continuing = n; - return val; - } - - int returning (void) const { return m_returning; } - - int returning (int n) - { - int val = m_returning; - m_returning = n; - return val; + return m_stack.empty (); } - int dbstep_flag (void) const { return m_dbstep_flag; } - - int dbstep_flag (int val) - { - int old_val = m_dbstep_flag; - m_dbstep_flag = val; - return old_val; - } - - void set_dbstep_flag (int step) { m_dbstep_flag = step; } - - bool break_on_next_statement (void) const + void clear (void) { - return m_break_on_next_stmt; - } - - bool break_on_next_statement (bool val) - { - bool old_val = m_break_on_next_stmt; - m_break_on_next_stmt = val; - return old_val; - } - - void set_break_on_next_statement (bool val) - { - m_break_on_next_stmt = val; + while (! m_stack.empty ()) + m_stack.pop (); } - octave_value echo (const octave_value_list& args, int nargout); - - int echo (void) const { return m_echo; } - - int echo (int val) - { - int old_val = m_echo; - m_echo = val; - return old_val; - } - - octave_value - string_fill_char (const octave_value_list& args, int nargout); - - void final_index_error (index_exception& ie, const tree_expression *expr); - - octave_value do_who (int argc, const string_vector& argv, - bool return_list, bool verbose = false); - - octave_value_list - make_value_list (tree_argument_list *args, const string_vector& arg_nm); - - std::list make_lvalue_list (tree_argument_list *); - - void push_echo_state (int type, const std::string& file_name, int pos = 1); - private: - template - void execute_range_loop (const range& rng, int line, - octave_lvalue& ult, - tree_statement_list *loop_body); + std::stack m_stack; + }; + + typedef void (*decl_elt_init_fcn) (tree_decl_elt&); + + tree_evaluator (interpreter& interp) + : m_interpreter (interp), m_parser (), m_statement_context (SC_OTHER), + m_lvalue_list (nullptr), m_autoload_map (), m_bp_table (*this), + m_call_stack (*this), m_profiler (), m_debug_frame (0), + m_debug_mode (false), m_quiet_breakpoint_flag (false), + m_debugger_stack (), m_exit_status (0), m_max_recursion_depth (256), + m_whos_line_format (" %la:5; %ln:6; %cs:16:6:1; %rb:12; %lc:-1;\n"), + m_silent_functions (false), m_string_fill_char (' '), m_PS4 ("+ "), + m_dbstep_flag (0), m_break_on_next_stmt (false), m_echo (ECHO_OFF), + m_echo_state (false), m_echo_file_name (), m_echo_file_pos (1), + m_echo_files (), m_in_top_level_repl (false), + m_server_mode (false), m_in_loop_command (false), + m_breaking (0), m_continuing (0), m_returning (0), + m_indexed_object (), m_index_list (), m_index_type (), + m_index_position (0), m_num_indices (0) + { } + + // No copying! + + tree_evaluator (const tree_evaluator&) = delete; - void set_echo_state (int type, const std::string& file_name, int pos); + tree_evaluator& operator = (const tree_evaluator&) = delete; + + ~tree_evaluator (void) = default; + + std::shared_ptr get_parser (void) + { + return m_parser; + } + + void set_parser (const std::shared_ptr& parser) + { + m_parser = parser; + } - void maybe_set_echo_state (void); + bool at_top_level (void) const; + + std::string mfilename (const std::string& opt = "") const; + + // Parse a line of input. If input ends at a complete statement + // boundary, execute the resulting parse tree. Useful to handle + // parsing user input when running in server mode. + + void parse_and_execute (const std::string& input, bool& incomplete_parse); + + void get_line_and_eval (void); + + int repl (void); - void push_echo_state_cleanup (unwind_protect& frame); + bool in_top_level_repl (void) const { return m_in_top_level_repl; } + + int server_loop (void); + + bool server_mode (void) const { return m_server_mode; } + + void server_mode (bool arg) { m_server_mode = arg; } + + void eval (std::shared_ptr& stmt_list, + bool interactive); - bool maybe_push_echo_state_cleanup (void); + octave_value_list eval_string (const std::string& eval_str, bool silent, + int& parse_status, int nargout); + + octave_value eval_string (const std::string& eval_str, bool silent, + int& parse_status); + + octave_value_list eval_string (const octave_value& arg, bool silent, + int& parse_status, int nargout); + + octave_value_list eval (const std::string& try_code, int nargout); + + octave_value_list eval (const std::string& try_code, + const std::string& catch_code, int nargout); - void do_breakpoint (tree_statement& stmt); + octave_value_list evalin (const std::string& context, + const std::string& try_code, int nargout); + + octave_value_list evalin (const std::string& context, + const std::string& try_code, + const std::string& catch_code, int nargout); + + void visit_anon_fcn_handle (tree_anon_fcn_handle&); + + void visit_argument_list (tree_argument_list&); + + void visit_arguments_block (tree_arguments_block&); - void do_breakpoint (bool is_breakpoint, - bool is_end_of_fcn_or_script = false); + void visit_args_block_attribute_list (tree_args_block_attribute_list&); + + void visit_args_block_validation_list (tree_args_block_validation_list&); + + void visit_arg_validation (tree_arg_validation&); + + void visit_arg_size_spec (tree_arg_size_spec&); + + void visit_arg_validation_fcns (tree_arg_validation_fcns&); + + void visit_binary_expression (tree_binary_expression&); + + void visit_boolean_expression (tree_boolean_expression&); + + void visit_compound_binary_expression (tree_compound_binary_expression&); - bool is_logically_true (tree_expression *expr, const char *warn_for); + void visit_break_command (tree_break_command&); + + void visit_colon_expression (tree_colon_expression&); + + void visit_continue_command (tree_continue_command&); + + void visit_decl_command (tree_decl_command&); + + void visit_decl_elt (tree_decl_elt&); + + void visit_simple_for_command (tree_simple_for_command&); + + void visit_complex_for_command (tree_complex_for_command&); + + void visit_spmd_command (tree_spmd_command&); + + octave_value evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh); + + octave_value_list + execute_builtin_function (octave_builtin& builtin_function, int nargout, + const octave_value_list& args); + octave_value_list + execute_mex_function (octave_mex_function& mex_function, int nargout, + const octave_value_list& args); + + void visit_octave_user_script (octave_user_script&); - // For unwind-protect. - void uwp_set_echo_state (bool state, const std::string& file_name, int pos); + octave_value_list + execute_user_script (octave_user_script& user_script, int nargout, + const octave_value_list& args); + + void visit_octave_user_function (octave_user_function&); + + octave_value_list + execute_user_function (octave_user_function& user_function, + int nargout, const octave_value_list& args); + + void visit_octave_user_function_header (octave_user_function&); + + void visit_octave_user_function_trailer (octave_user_function&); - bool echo_this_file (const std::string& file, int type) const; + void visit_function_def (tree_function_def&); + + void visit_identifier (tree_identifier&); + + void visit_if_clause (tree_if_clause&); - void echo_code (int line); + void visit_if_command (tree_if_command&); + + void visit_if_command_list (tree_if_command_list&); + + void visit_index_expression (tree_index_expression&); + + void visit_matrix (tree_matrix&); - bool quit_loop_now (void); + void visit_cell (tree_cell&); + + void visit_multi_assignment (tree_multi_assignment&); + + void visit_no_op_command (tree_no_op_command&); + + void visit_constant (tree_constant&); + + void visit_fcn_handle (tree_fcn_handle&); + + void visit_parameter_list (tree_parameter_list&); + + void visit_postfix_expression (tree_postfix_expression&); + + void visit_prefix_expression (tree_prefix_expression&); + + void visit_return_command (tree_return_command&); + + void visit_simple_assignment (tree_simple_assignment&); + + void visit_statement (tree_statement&); + + void visit_statement_list (tree_statement_list&); + + void visit_switch_case (tree_switch_case&); + + void visit_switch_case_list (tree_switch_case_list&); - void bind_auto_fcn_vars (const string_vector& arg_names, - const Matrix& ignored_outputs, int nargin, - int nargout, bool takes_varargs, - const octave_value_list& va_args); + void visit_switch_command (tree_switch_command&); + + void visit_try_catch_command (tree_try_catch_command&); + + void do_unwind_protect_cleanup_code (tree_statement_list *list); + + void visit_unwind_protect_command (tree_unwind_protect_command&); + + void visit_while_command (tree_while_command&); + void visit_do_until_command (tree_do_until_command&); + + void visit_superclass_ref (tree_superclass_ref&); + void visit_metaclass_query (tree_metaclass_query&); - std::string check_autoload_file (const std::string& nm) const; + void bind_ans (const octave_value& val, bool print); + + bool statement_printing_enabled (void); + + void reset_debug_state (void); - interpreter& m_interpreter; + void reset_debug_state (bool mode); + + void enter_debugger (const std::string& prompt = "debug> "); + + void keyboard (const std::string& prompt = "keyboard> "); + + void dbupdown (int n, bool verbose = false); - std::shared_ptr m_parser; + // Possible types of evaluation contexts. + enum stmt_list_type + { + SC_FUNCTION, // function body + SC_SCRIPT, // script file + SC_OTHER // command-line input or eval string + }; + + Matrix ignored_fcn_outputs (void) const; + + octave_value make_fcn_handle (const std::string& nm); + + octave_value evaluate (tree_decl_elt *); + + void install_variable (const std::string& name, + const octave_value& value, bool global); + + octave_value global_varval (const std::string& name) const; + + octave_value& global_varref (const std::string& name); + + void global_assign (const std::string& name, + const octave_value& val = octave_value ()); - // The context for the current evaluation. - stmt_list_type m_statement_context; + octave_value top_level_varval (const std::string& name) const; + + void top_level_assign (const std::string& name, + const octave_value& val = octave_value ()); + + bool is_variable (const std::string& name) const; + + bool is_local_variable (const std::string& name) const; + + bool is_variable (const tree_expression *expr) const; + + bool is_defined (const tree_expression *expr) const; - const std::list *m_lvalue_list; + bool is_variable (const symbol_record& sym) const; + + bool is_defined (const symbol_record& sym) const; + + bool is_global (const std::string& name) const; + + octave_value varval (const symbol_record& sym) const; + + octave_value varval (const std::string& name) const; + + void assign (const std::string& name, + const octave_value& val = octave_value ()); - // List of autoloads (function -> file mapping). - std::map m_autoload_map; + void assignin (const std::string& context, const std::string& name, + const octave_value& val = octave_value ()); + + void source_file (const std::string& file_name, + const std::string& context = "", + bool verbose = false, bool require_file = true); + + void set_auto_fcn_var (stack_frame::auto_var_type avt, + const octave_value& val = octave_value ()); + + octave_value get_auto_fcn_var (stack_frame::auto_var_type avt) const; - bp_table m_bp_table; + void define_parameter_list_from_arg_vector + (tree_parameter_list *param_list, const octave_value_list& args); + + void undefine_parameter_list (tree_parameter_list *param_list); + + octave_value_list convert_to_const_vector (tree_argument_list *arg_list); + + octave_value_list + convert_return_list_to_const_vector + (tree_parameter_list *ret_list, int nargout, + const Matrix& ignored_outputs, const Cell& varargout); + + bool eval_decl_elt (tree_decl_elt *elt); - call_stack m_call_stack; + bool switch_case_label_matches (tree_switch_case *expr, + const octave_value& val); + + interpreter& get_interpreter (void) { return m_interpreter; } + + bp_table& get_bp_table (void) { return m_bp_table; } + + profiler& get_profiler (void) { return m_profiler; } + + void push_stack_frame (const symbol_scope& scope); + + void push_stack_frame (octave_user_function *fcn, + const std::shared_ptr& closure_frames = std::shared_ptr ()); - profiler m_profiler; + void push_stack_frame (octave_user_function *fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& closure_frames = std::shared_ptr ()); + + void push_stack_frame (octave_user_script *script); - // The number of the stack frame we are currently debugging. - std::size_t m_debug_frame; + void push_stack_frame (octave_function *fcn); + + void pop_stack_frame (void); + + std::shared_ptr get_current_stack_frame (void) const + { + return m_call_stack.get_current_stack_frame (); + } - bool m_debug_mode; + std::shared_ptr current_user_frame (void) const + { + return m_call_stack.current_user_frame (); + } + + // Current line in current function. + int current_line (void) const; + + // Current column in current function. + int current_column (void) const; + + // Line number in current function that we are debugging. + int debug_user_code_line (void) const; + + // Column number in current function that we are debugging. + int debug_user_code_column (void) const; + + void debug_where (std::ostream& os) const; + + octave_user_code * current_user_code (void) const; + + unwind_protect * curr_fcn_unwind_protect_frame (void); + + // Current function that we are debugging. + octave_user_code * debug_user_code (void) const; + + octave_function * current_function (bool skip_first = false) const; - bool m_quiet_breakpoint_flag; + octave_function * caller_function (void) const; + + bool goto_frame (std::size_t n = 0, bool verbose = false); + + void goto_caller_frame (void); + + void goto_base_frame (void); + + void restore_frame (std::size_t n); + + std::string get_dispatch_class (void) const; + + void set_dispatch_class (const std::string& class_name); + + bool is_class_method_executing (std::string& dispatch_class) const; + + bool is_class_constructor_executing (std::string& dispatch_class) const; + + std::list> + backtrace_frames (octave_idx_type& curr_user_frame) const; + + std::list> backtrace_frames () const; + + std::list backtrace_info (octave_idx_type& curr_user_frame, + bool print_subfn = true) const; + + std::list backtrace_info (void) const; - // When entering the debugger we push it on this stack. Managing - // debugger invocations this way allows us to handle recursive - // debugger calls. When we exit a debugger the object is popped - // from the stack and deleted and we resume working with the - // previous debugger (if any) that is now at the top of the stack. - std::stack m_debugger_stack; + octave_map backtrace (octave_idx_type& curr_user_frame, + bool print_subfn = true) const; + + octave_map backtrace (void) const; + + octave_map empty_backtrace (void) const; + + std::string backtrace_message (void) const; + + void push_dummy_scope (const std::string& name); + void pop_scope (void); + + symbol_scope get_top_scope (void) const; + symbol_scope get_current_scope (void) const; + + void mlock (bool skip_first = false) const; + + void munlock (bool skip_first = false) const; + + bool mislocked (bool skip_first = false) const; + + octave_value max_stack_depth (const octave_value_list& args, int nargout); + + // Useful for debugging + void display_call_stack (void) const; + + octave_value find (const std::string& name); - std::set m_debug_watch_expressions; + void clear_objects (void); + + void clear_variable (const std::string& name); + + void clear_variable_pattern (const std::string& pattern); - int m_exit_status; + void clear_variable_regexp (const std::string& pattern); + + void clear_variables (void); + + void clear_global_variable (const std::string& name); + + void clear_global_variable_pattern (const std::string& pattern); - // Maximum nesting level for functions, scripts, or sourced files - // called recursively. - int m_max_recursion_depth; + void clear_global_variable_regexp (const std::string& pattern); + + void clear_global_variables (void); + + void clear_all (bool force = false); + + void clear_symbol (const std::string& name); + + void clear_symbol_pattern (const std::string& pattern); + + void clear_symbol_regexp (const std::string& pattern); + + std::list global_variable_names (void) const; + + std::list top_level_variable_names (void) const; - // Defines layout for the whos/who -long command - std::string m_whos_line_format; + std::list variable_names (void) const; + + octave_user_code * get_user_code (const std::string& fname = "", + const std::string& class_name = ""); + + std::string current_function_name (bool skip_first = false) const; + + bool in_user_code (void) const; + + symbol_info_list glob_symbol_info (const std::string& pattern) const; + + symbol_info_list regexp_symbol_info (const std::string& pattern) const; + + symbol_info_list get_symbol_info (void); + + symbol_info_list top_scope_symbol_info (void) const; + + octave_map get_autoload_map (void) const; + + std::string lookup_autoload (const std::string& nm) const; + + std::list autoloaded_functions (void) const; + + std::list reverse_lookup_autoload (const std::string& nm) const; + + void add_autoload (const std::string& fcn, const std::string& nm); + + void remove_autoload (const std::string& fcn, const std::string& nm); + + int max_recursion_depth (void) const { return m_max_recursion_depth; } + + int max_recursion_depth (int n) + { + int val = m_max_recursion_depth; + m_max_recursion_depth = n; + return val; + } + + octave_value + max_recursion_depth (const octave_value_list& args, int nargout); + + bool silent_functions (void) const { return m_silent_functions; } + + bool silent_functions (bool b) + { + int val = m_silent_functions; + m_silent_functions = b; + return val; + } + + octave_value whos_line_format (const octave_value_list& args, int nargout); - // If TRUE, turn off printing of results in functions (as if a - // semicolon has been appended to each statement). - bool m_silent_functions; + std::string whos_line_format (void) const { return m_whos_line_format; } + + std::string whos_line_format (const std::string& s) + { + std::string val = m_whos_line_format; + m_whos_line_format = s; + return val; + } + + octave_value + silent_functions (const octave_value_list& args, int nargout); + + std::size_t debug_frame (void) const { return m_debug_frame; } + + std::size_t debug_frame (std::size_t n) + { + std::size_t val = m_debug_frame; + m_debug_frame = n; + return val; + } + + std::size_t current_call_stack_frame_number (void) const + { + return m_call_stack.current_frame (); + } - // The character to fill with when creating string arrays. - char m_string_fill_char; + bool quiet_breakpoint_flag (void) const { return m_quiet_breakpoint_flag; } + + bool quiet_breakpoint_flag (bool flag) + { + bool val = m_quiet_breakpoint_flag; + m_quiet_breakpoint_flag = flag; + return val; + } + + char string_fill_char (void) const { return m_string_fill_char; } - // String printed before echoed commands (enabled by --echo-commands). - std::string m_PS4; + char string_fill_char (char c) + { + int val = m_string_fill_char; + m_string_fill_char = c; + return val; + } + + // The following functions are provided for convenience. They + // call the corresponding functions in the debugger class for the + // current debugger (if any). + + bool in_debug_repl (void) const; + + void dbcont (void); + + // Return true if we are in the debug repl and m_execution_mode is + // set to exit the debugger. Otherwise, do nothing. - // If > 0, stop executing at the (N-1)th stopping point, counting - // from the the current execution point in the current frame. - // - // If < 0, stop executing at the next possible stopping point. - int m_dbstep_flag; + void dbquit (bool all = false); + + // Add EXPR to the set of expressions that may be evaluated when the + // debugger stops at a breakpoint. + void add_debug_watch_expression (const std::string& expr) + { + m_debug_watch_expressions.insert (expr); + } + + // Remove EXPR from the set of expressions that may be evaluated + // when the debugger stops at a breakpoint. + void remove_debug_watch_expression (const std::string& expr) + { + m_debug_watch_expressions.erase (expr); + } + + // Clear the set of expressions that may be evaluated when the + // debugger stops at a breakpoint. + void clear_debug_watch_expressions (void) + { + m_debug_watch_expressions.clear (); + } - // If TRUE, and we are not stopping for another reason (dbstep or a - // breakpoint) then stop at next statement and enter the debugger. - bool m_break_on_next_stmt; + // Return the set of expressions that may be evaluated when the + // debugger stops at a breakpoint. + std::set debug_watch_expressions (void) const + { + return m_debug_watch_expressions; + } + + octave_value PS4 (const octave_value_list& args, int nargout); + + std::string PS4 (void) const { return m_PS4; } + + std::string PS4 (const std::string& s) + { + std::string val = m_PS4; + m_PS4 = s; + return val; + } + + octave_value indexed_object (void) const + { + return m_indexed_object; + } + + void set_indexed_object (const octave_value& obj = octave_value ()) + { + m_indexed_object = obj; + } - // Echo commands as they are executed? - // - // 1 ==> echo commands read from script files - // 2 ==> echo commands from functions - // - // more than one state can be active at once. - int m_echo; + const std::list& index_list (void) const + { + return m_index_list; + } + + void set_index_list (const std::string& index_type, + const std::list& index_list) + { + m_index_type = index_type; + m_index_list = index_list; + } + + void clear_index_list (void) + { + m_index_type = ""; + m_index_list.clear (); + } + + void append_index_list (char type, const octave_value_list& idx) + { + m_index_type += type; + m_index_list.push_back (idx); + } - // Are we currently echoing commands? This state is set by the - // functions that execute functions and scripts. - bool m_echo_state; + const std::string& index_type (void) const + { + return m_index_type; + } + + int index_position (void) const { return m_index_position; } + + int num_indices (void) const { return m_num_indices; } + + octave_value_list evaluate_end_expression (const octave_value_list& args); + + const std::list * lvalue_list (void) const + { + return m_lvalue_list; + } - std::string m_echo_file_name; + void set_lvalue_list (const std::list *lst) + { + m_lvalue_list = lst; + } + + int breaking (void) const { return m_breaking; } + + int breaking (int n) + { + int val = m_breaking; + m_breaking = n; + return val; + } + + int continuing (void) const { return m_continuing; } - // Next line to echo, counting from 1. We use int here because the - // parser does. It also initializes line and column numbers to the - // invalid value -1 and that can cause trouble if cast to an - // unsigned value. When updating this value and echoing ranges of - // code, we also check to ensure that the line numbers stored in the - // parse tree are valid. It would be better to ensure that the - // parser always stores valid position info, but that's more - // difficult to always do correctly. - int m_echo_file_pos; + int continuing (int n) + { + int val = m_continuing; + m_continuing = n; + return val; + } + + int returning (void) const { return m_returning; } + + int returning (int n) + { + int val = m_returning; + m_returning = n; + return val; + } + + int dbstep_flag (void) const { return m_dbstep_flag; } + + int dbstep_flag (int val) + { + int old_val = m_dbstep_flag; + m_dbstep_flag = val; + return old_val; + } + + void set_dbstep_flag (int step) { m_dbstep_flag = step; } + + bool break_on_next_statement (void) const + { + return m_break_on_next_stmt; + } + + bool break_on_next_statement (bool val) + { + bool old_val = m_break_on_next_stmt; + m_break_on_next_stmt = val; + return old_val; + } + + void set_break_on_next_statement (bool val) + { + m_break_on_next_stmt = val; + } + + octave_value echo (const octave_value_list& args, int nargout); + + int echo (void) const { return m_echo; } + + int echo (int val) + { + int old_val = m_echo; + m_echo = val; + return old_val; + } - std::map m_echo_files; + octave_value + string_fill_char (const octave_value_list& args, int nargout); + + void final_index_error (index_exception& ie, const tree_expression *expr); + + octave_value do_who (int argc, const string_vector& argv, + bool return_list, bool verbose = false); + + octave_value_list + make_value_list (tree_argument_list *args, const string_vector& arg_nm); + + std::list make_lvalue_list (tree_argument_list *); + + void push_echo_state (int type, const std::string& file_name, int pos = 1); + +private: + + template + void execute_range_loop (const range& rng, int line, + octave_lvalue& ult, + tree_statement_list *loop_body); + + void set_echo_state (int type, const std::string& file_name, int pos); + + void maybe_set_echo_state (void); + + void push_echo_state_cleanup (unwind_protect& frame); - // TRUE if we are in the top level interactive read eval print loop. - bool m_in_top_level_repl; + bool maybe_push_echo_state_cleanup (void); + + void do_breakpoint (tree_statement& stmt); + + void do_breakpoint (bool is_breakpoint, + bool is_end_of_fcn_or_script = false); + + bool is_logically_true (tree_expression *expr, const char *warn_for); + + // For unwind-protect. + void uwp_set_echo_state (bool state, const std::string& file_name, int pos); + + bool echo_this_file (const std::string& file, int type) const; - // TRUE means we are executing in the server_loop function. - bool m_server_mode; + void echo_code (int line); + + bool quit_loop_now (void); + + void bind_auto_fcn_vars (const string_vector& arg_names, + const Matrix& ignored_outputs, int nargin, + int nargout, bool takes_varargs, + const octave_value_list& va_args); + + std::string check_autoload_file (const std::string& nm) const; + + interpreter& m_interpreter; + + std::shared_ptr m_parser; - // TRUE means we are evaluating some kind of looping construct. - bool m_in_loop_command; + // The context for the current evaluation. + stmt_list_type m_statement_context; + + const std::list *m_lvalue_list; + + // List of autoloads (function -> file mapping). + std::map m_autoload_map; + + bp_table m_bp_table; + + call_stack m_call_stack; + + profiler m_profiler; + + // The number of the stack frame we are currently debugging. + std::size_t m_debug_frame; + + bool m_debug_mode; + + bool m_quiet_breakpoint_flag; - // Nonzero means we're breaking out of a loop or function body. - int m_breaking; + // When entering the debugger we push it on this stack. Managing + // debugger invocations this way allows us to handle recursive + // debugger calls. When we exit a debugger the object is popped + // from the stack and deleted and we resume working with the + // previous debugger (if any) that is now at the top of the stack. + std::stack m_debugger_stack; + + std::set m_debug_watch_expressions; + + int m_exit_status; + + // Maximum nesting level for functions, scripts, or sourced files + // called recursively. + int m_max_recursion_depth; - // Nonzero means we're jumping to the end of a loop. - int m_continuing; + // Defines layout for the whos/who -long command + std::string m_whos_line_format; + + // If TRUE, turn off printing of results in functions (as if a + // semicolon has been appended to each statement). + bool m_silent_functions; + + // The character to fill with when creating string arrays. + char m_string_fill_char; + + // String printed before echoed commands (enabled by --echo-commands). + std::string m_PS4; + + // If > 0, stop executing at the (N-1)th stopping point, counting + // from the the current execution point in the current frame. + // + // If < 0, stop executing at the next possible stopping point. + int m_dbstep_flag; - // Nonzero means we're returning from a function. - int m_returning; + // If TRUE, and we are not stopping for another reason (dbstep or a + // breakpoint) then stop at next statement and enter the debugger. + bool m_break_on_next_stmt; + + // Echo commands as they are executed? + // + // 1 ==> echo commands read from script files + // 2 ==> echo commands from functions + // + // more than one state can be active at once. + int m_echo; + + // Are we currently echoing commands? This state is set by the + // functions that execute functions and scripts. + bool m_echo_state; + + std::string m_echo_file_name; + + // Next line to echo, counting from 1. We use int here because the + // parser does. It also initializes line and column numbers to the + // invalid value -1 and that can cause trouble if cast to an + // unsigned value. When updating this value and echoing ranges of + // code, we also check to ensure that the line numbers stored in the + // parse tree are valid. It would be better to ensure that the + // parser always stores valid position info, but that's more + // difficult to always do correctly. + int m_echo_file_pos; - // The following are all used by the END function. Maybe they - // should be kept together in a separate object? - octave_value m_indexed_object; - std::list m_index_list; - std::string m_index_type; - int m_index_position; - int m_num_indices; - }; + std::map m_echo_files; + + // TRUE if we are in the top level interactive read eval print loop. + bool m_in_top_level_repl; + + // TRUE means we are executing in the server_loop function. + bool m_server_mode; + + // TRUE means we are evaluating some kind of looping construct. + bool m_in_loop_command; + + // Nonzero means we're breaking out of a loop or function body. + int m_breaking; + + // Nonzero means we're jumping to the end of a loop. + int m_continuing; + + // Nonzero means we're returning from a function. + int m_returning; + + // The following are all used by the END function. Maybe they + // should be kept together in a separate object? + octave_value m_indexed_object; + std::list m_index_list; + std::string m_index_type; + int m_index_position; + int m_num_indices; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-except.cc --- a/libinterp/parse-tree/pt-except.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-except.cc Thu Dec 01 20:05:44 2022 -0800 @@ -45,27 +45,27 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Simple exception handling. +// Simple exception handling. - tree_try_catch_command::~tree_try_catch_command (void) - { - delete m_expr_id; - delete m_try_code; - delete m_catch_code; - delete m_lead_comm; - delete m_mid_comm; - delete m_trail_comm; - } +tree_try_catch_command::~tree_try_catch_command (void) +{ + delete m_expr_id; + delete m_try_code; + delete m_catch_code; + delete m_lead_comm; + delete m_mid_comm; + delete m_trail_comm; +} - // Simple exception handling. +// Simple exception handling. - tree_unwind_protect_command::~tree_unwind_protect_command (void) - { - delete m_unwind_protect_code; - delete m_cleanup_code; - delete m_lead_comm; - delete m_mid_comm; - delete m_trail_comm; - } +tree_unwind_protect_command::~tree_unwind_protect_command (void) +{ + delete m_unwind_protect_code; + delete m_cleanup_code; + delete m_lead_comm; + delete m_mid_comm; + delete m_trail_comm; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-except.h --- a/libinterp/parse-tree/pt-except.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-except.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,141 +34,141 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class comment_list; - class tree_statement_list; +class comment_list; +class tree_statement_list; - // Simple exception handling. +// Simple exception handling. - class tree_try_catch_command : public tree_command - { - public: +class tree_try_catch_command : public tree_command +{ +public: - tree_try_catch_command (int l = -1, int c = -1) - : tree_command (l, c), m_try_code (nullptr), m_catch_code (nullptr), - m_expr_id (nullptr), m_lead_comm (nullptr), m_mid_comm (nullptr), - m_trail_comm (nullptr) - { } + tree_try_catch_command (int l = -1, int c = -1) + : tree_command (l, c), m_try_code (nullptr), m_catch_code (nullptr), + m_expr_id (nullptr), m_lead_comm (nullptr), m_mid_comm (nullptr), + m_trail_comm (nullptr) + { } - tree_try_catch_command (tree_statement_list *tc, tree_statement_list *cc, - tree_identifier *id, - comment_list *cl = nullptr, - comment_list *cm = nullptr, - comment_list *ct = nullptr, - int l = -1, int c = -1) - : tree_command (l, c), m_try_code (tc), m_catch_code (cc), - m_expr_id (id), m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct) - { } + tree_try_catch_command (tree_statement_list *tc, tree_statement_list *cc, + tree_identifier *id, + comment_list *cl = nullptr, + comment_list *cm = nullptr, + comment_list *ct = nullptr, + int l = -1, int c = -1) + : tree_command (l, c), m_try_code (tc), m_catch_code (cc), + m_expr_id (id), m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct) + { } - // No copying! + // No copying! - tree_try_catch_command (const tree_try_catch_command&) = delete; + tree_try_catch_command (const tree_try_catch_command&) = delete; - tree_try_catch_command& operator = (const tree_try_catch_command&) = delete; + tree_try_catch_command& operator = (const tree_try_catch_command&) = delete; - ~tree_try_catch_command (void); + ~tree_try_catch_command (void); - tree_identifier * identifier (void) { return m_expr_id; } + tree_identifier * identifier (void) { return m_expr_id; } - tree_statement_list * body (void) { return m_try_code; } + tree_statement_list * body (void) { return m_try_code; } - tree_statement_list * cleanup (void) { return m_catch_code; } + tree_statement_list * cleanup (void) { return m_catch_code; } - comment_list * leading_comment (void) { return m_lead_comm; } + comment_list * leading_comment (void) { return m_lead_comm; } - comment_list * middle_comment (void) { return m_mid_comm; } + comment_list * middle_comment (void) { return m_mid_comm; } - comment_list * trailing_comment (void) { return m_trail_comm; } + comment_list * trailing_comment (void) { return m_trail_comm; } - void accept (tree_walker& tw) - { - tw.visit_try_catch_command (*this); - } + void accept (tree_walker& tw) + { + tw.visit_try_catch_command (*this); + } - private: +private: - // The first block of code to attempt to execute. - tree_statement_list *m_try_code; + // The first block of code to attempt to execute. + tree_statement_list *m_try_code; - // The code to execute if an error occurs in the first block. - tree_statement_list *m_catch_code; + // The code to execute if an error occurs in the first block. + tree_statement_list *m_catch_code; - // Identifier to modify. - tree_identifier *m_expr_id; + // Identifier to modify. + tree_identifier *m_expr_id; - // Comment preceding TRY token. - comment_list *m_lead_comm; + // Comment preceding TRY token. + comment_list *m_lead_comm; - // Comment preceding CATCH token. - comment_list *m_mid_comm; + // Comment preceding CATCH token. + comment_list *m_mid_comm; - // Comment preceding END_TRY_CATCH token. - comment_list *m_trail_comm; - }; + // Comment preceding END_TRY_CATCH token. + comment_list *m_trail_comm; +}; - // Simple exception handling. +// Simple exception handling. - class tree_unwind_protect_command : public tree_command - { - public: +class tree_unwind_protect_command : public tree_command +{ +public: - tree_unwind_protect_command (int l = -1, int c = -1) - : tree_command (l, c), - m_unwind_protect_code (nullptr), m_cleanup_code (nullptr), - m_lead_comm (nullptr), m_mid_comm (nullptr), m_trail_comm (nullptr) - { } + tree_unwind_protect_command (int l = -1, int c = -1) + : tree_command (l, c), + m_unwind_protect_code (nullptr), m_cleanup_code (nullptr), + m_lead_comm (nullptr), m_mid_comm (nullptr), m_trail_comm (nullptr) + { } - tree_unwind_protect_command (tree_statement_list *tc, - tree_statement_list *cc, - comment_list *cl = nullptr, - comment_list *cm = nullptr, - comment_list *ct = nullptr, - int l = -1, int c = -1) - : tree_command (l, c), m_unwind_protect_code (tc), m_cleanup_code (cc), - m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct) - { } + tree_unwind_protect_command (tree_statement_list *tc, + tree_statement_list *cc, + comment_list *cl = nullptr, + comment_list *cm = nullptr, + comment_list *ct = nullptr, + int l = -1, int c = -1) + : tree_command (l, c), m_unwind_protect_code (tc), m_cleanup_code (cc), + m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct) + { } - // No copying! + // No copying! - tree_unwind_protect_command (const tree_unwind_protect_command&) = delete; + tree_unwind_protect_command (const tree_unwind_protect_command&) = delete; - tree_unwind_protect_command& - operator = (const tree_unwind_protect_command&) = delete; + tree_unwind_protect_command& + operator = (const tree_unwind_protect_command&) = delete; - ~tree_unwind_protect_command (void); + ~tree_unwind_protect_command (void); - tree_statement_list * body (void) { return m_unwind_protect_code; } + tree_statement_list * body (void) { return m_unwind_protect_code; } - tree_statement_list * cleanup (void) { return m_cleanup_code; } + tree_statement_list * cleanup (void) { return m_cleanup_code; } - comment_list * leading_comment (void) { return m_lead_comm; } + comment_list * leading_comment (void) { return m_lead_comm; } - comment_list * middle_comment (void) { return m_mid_comm; } + comment_list * middle_comment (void) { return m_mid_comm; } - comment_list * trailing_comment (void) { return m_trail_comm; } + comment_list * trailing_comment (void) { return m_trail_comm; } - void accept (tree_walker& tw) - { - tw.visit_unwind_protect_command (*this); - } + void accept (tree_walker& tw) + { + tw.visit_unwind_protect_command (*this); + } - private: +private: - // The first body of code to attempt to execute. - tree_statement_list *m_unwind_protect_code; + // The first body of code to attempt to execute. + tree_statement_list *m_unwind_protect_code; - // The body of code to execute no matter what happens in the first - // body of code. - tree_statement_list *m_cleanup_code; + // The body of code to execute no matter what happens in the first + // body of code. + tree_statement_list *m_cleanup_code; - // Comment preceding UNWIND_PROTECT token. - comment_list *m_lead_comm; + // Comment preceding UNWIND_PROTECT token. + comment_list *m_lead_comm; - // Comment preceding UNWIND_PROTECT_CLEANUP token. - comment_list *m_mid_comm; + // Comment preceding UNWIND_PROTECT_CLEANUP token. + comment_list *m_mid_comm; - // Comment preceding END_UNWIND_PROTECT token. - comment_list *m_trail_comm; - }; + // Comment preceding END_UNWIND_PROTECT token. + comment_list *m_trail_comm; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-exp.cc --- a/libinterp/parse-tree/pt-exp.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-exp.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,18 +37,18 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Expressions. +// Expressions. - octave_lvalue - tree_expression::lvalue (tree_evaluator&) - { - error ("invalid lvalue function called in expression"); - } +octave_lvalue +tree_expression::lvalue (tree_evaluator&) +{ + error ("invalid lvalue function called in expression"); +} - std::string - tree_expression::original_text (void) const - { - return ""; - } +std::string +tree_expression::original_text (void) const +{ + return ""; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-exp.h --- a/libinterp/parse-tree/pt-exp.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-exp.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,131 +38,131 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class octave_lvalue; +class symbol_scope; +class octave_lvalue; - // A base class for expressions. +// A base class for expressions. - class tree_expression : public tree - { - public: +class tree_expression : public tree +{ +public: - tree_expression (int l = -1, int c = -1) - : tree (l, c), m_num_parens (0), m_postfix_index_type ('\0'), - m_for_cmd_expr (false), m_print_flag (false) { } + tree_expression (int l = -1, int c = -1) + : tree (l, c), m_num_parens (0), m_postfix_index_type ('\0'), + m_for_cmd_expr (false), m_print_flag (false) { } - // No copying! + // No copying! - tree_expression (const tree_expression&) = delete; + tree_expression (const tree_expression&) = delete; - tree_expression& operator = (const tree_expression&) = delete; + tree_expression& operator = (const tree_expression&) = delete; - virtual ~tree_expression (void) = default; + virtual ~tree_expression (void) = default; - virtual tree_expression * dup (symbol_scope& scope) const = 0; + virtual tree_expression * dup (symbol_scope& scope) const = 0; - virtual bool is_constant (void) const { return false; } + virtual bool is_constant (void) const { return false; } - virtual bool is_matrix (void) const { return false; } + virtual bool is_matrix (void) const { return false; } - virtual bool iscell (void) const { return false; } + virtual bool iscell (void) const { return false; } - virtual bool is_identifier (void) const { return false; } + virtual bool is_identifier (void) const { return false; } - virtual bool is_index_expression (void) const { return false; } + virtual bool is_index_expression (void) const { return false; } - virtual bool is_assignment_expression (void) const { return false; } + virtual bool is_assignment_expression (void) const { return false; } - virtual bool is_prefix_expression (void) const { return false; } + virtual bool is_prefix_expression (void) const { return false; } - virtual bool is_unary_expression (void) const { return false; } + virtual bool is_unary_expression (void) const { return false; } - virtual bool is_binary_expression (void) const { return false; } + virtual bool is_binary_expression (void) const { return false; } - virtual bool is_boolean_expression (void) const { return false; } + virtual bool is_boolean_expression (void) const { return false; } - virtual bool is_colon_expression (void) const { return false; } + virtual bool is_colon_expression (void) const { return false; } - virtual bool lvalue_ok (void) const { return false; } + virtual bool lvalue_ok (void) const { return false; } - virtual bool rvalue_ok (void) const { return false; } + virtual bool rvalue_ok (void) const { return false; } - virtual octave_lvalue lvalue (tree_evaluator&); + virtual octave_lvalue lvalue (tree_evaluator&); - int paren_count (void) const { return m_num_parens; } + int paren_count (void) const { return m_num_parens; } - bool is_postfix_indexed (void) const - { return (m_postfix_index_type != '\0'); } + bool is_postfix_indexed (void) const + { return (m_postfix_index_type != '\0'); } - char postfix_index (void) const { return m_postfix_index_type; } + char postfix_index (void) const { return m_postfix_index_type; } - // Check if the result of the expression should be printed. - // Should normally be used in conjunction with - // tree_evaluator::statement_printing_enabled. - bool print_result (void) const { return m_print_flag; } + // Check if the result of the expression should be printed. + // Should normally be used in conjunction with + // tree_evaluator::statement_printing_enabled. + bool print_result (void) const { return m_print_flag; } - virtual std::string oper (void) const { return ""; } + virtual std::string oper (void) const { return ""; } - virtual std::string name (void) const { return ""; } + virtual std::string name (void) const { return ""; } - virtual std::string original_text (void) const; + virtual std::string original_text (void) const; - void mark_as_for_cmd_expr (void) { m_for_cmd_expr = true; } + void mark_as_for_cmd_expr (void) { m_for_cmd_expr = true; } - bool is_for_cmd_expr (void) const { return m_for_cmd_expr; } + bool is_for_cmd_expr (void) const { return m_for_cmd_expr; } - tree_expression * mark_in_parens (void) - { - m_num_parens++; - return this; - } + tree_expression * mark_in_parens (void) + { + m_num_parens++; + return this; + } - tree_expression * set_postfix_index (char type) - { - m_postfix_index_type = type; - return this; - } + tree_expression * set_postfix_index (char type) + { + m_postfix_index_type = type; + return this; + } - tree_expression * set_print_flag (bool print) - { - m_print_flag = print; - return this; - } + tree_expression * set_print_flag (bool print) + { + m_print_flag = print; + return this; + } - virtual void copy_base (const tree_expression& e) - { - m_num_parens = e.m_num_parens; - m_postfix_index_type = e.m_postfix_index_type; - m_print_flag = e.m_print_flag; - } + virtual void copy_base (const tree_expression& e) + { + m_num_parens = e.m_num_parens; + m_postfix_index_type = e.m_postfix_index_type; + m_print_flag = e.m_print_flag; + } - virtual octave_value evaluate (tree_evaluator& tw, int nargout = 1) = 0; + virtual octave_value evaluate (tree_evaluator& tw, int nargout = 1) = 0; - virtual octave_value_list - evaluate_n (tree_evaluator& tw, int nargout = 1) = 0; + virtual octave_value_list + evaluate_n (tree_evaluator& tw, int nargout = 1) = 0; - protected: +protected: - // A count of the number of times this expression appears directly - // inside a set of parentheses. - // - // (((e1)) + e2) ==> 2 for expression e1 - // ==> 1 for expression ((e1)) + e2 - // ==> 0 for expression e2 - int m_num_parens; + // A count of the number of times this expression appears directly + // inside a set of parentheses. + // + // (((e1)) + e2) ==> 2 for expression e1 + // ==> 1 for expression ((e1)) + e2 + // ==> 0 for expression e2 + int m_num_parens; - // The first index type associated with this expression. This field - // is 0 (character '\0') if the expression has no associated index. - // See the code in tree_identifier::rvalue for the rationale. - char m_postfix_index_type; + // The first index type associated with this expression. This field + // is 0 (character '\0') if the expression has no associated index. + // See the code in tree_identifier::rvalue for the rationale. + char m_postfix_index_type; - // TRUE if this expression is the EXPR in for loop: - // FOR i = EXPR ... END - bool m_for_cmd_expr; + // TRUE if this expression is the EXPR in for loop: + // FOR i = EXPR ... END + bool m_for_cmd_expr; - // Print result of rvalue for this expression? - bool m_print_flag; - }; + // Print result of rvalue for this expression? + bool m_print_flag; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-fcn-handle.cc --- a/libinterp/parse-tree/pt-fcn-handle.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-fcn-handle.cc Thu Dec 01 20:05:44 2022 -0800 @@ -36,73 +36,73 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - tree_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax, - bool pr_orig_text) - { - print_raw (os, pr_as_read_syntax, pr_orig_text); - } +void +tree_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + print_raw (os, pr_as_read_syntax, pr_orig_text); +} - void - tree_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax, - bool pr_orig_text) - { - os << ((pr_as_read_syntax || pr_orig_text) ? "@" : "") << m_name; - } +void +tree_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax, + bool pr_orig_text) +{ + os << ((pr_as_read_syntax || pr_orig_text) ? "@" : "") << m_name; +} - tree_expression * - tree_fcn_handle::dup (symbol_scope&) const - { - tree_fcn_handle *new_fh = new tree_fcn_handle (m_name, line (), column ()); +tree_expression * +tree_fcn_handle::dup (symbol_scope&) const +{ + tree_fcn_handle *new_fh = new tree_fcn_handle (m_name, line (), column ()); - new_fh->copy_base (*this); + new_fh->copy_base (*this); - return new_fh; - } + return new_fh; +} - octave_value - tree_fcn_handle::evaluate (tree_evaluator& tw, int) - { - return tw.make_fcn_handle (m_name); - } +octave_value +tree_fcn_handle::evaluate (tree_evaluator& tw, int) +{ + return tw.make_fcn_handle (m_name); +} - tree_anon_fcn_handle::~tree_anon_fcn_handle (void) - { - delete m_parameter_list; - delete m_expression; - } +tree_anon_fcn_handle::~tree_anon_fcn_handle (void) +{ + delete m_parameter_list; + delete m_expression; +} - tree_expression * - tree_anon_fcn_handle::dup (symbol_scope&) const - { - tree_parameter_list *param_list = parameter_list (); - tree_expression *expr = expression (); +tree_expression * +tree_anon_fcn_handle::dup (symbol_scope&) const +{ + tree_parameter_list *param_list = parameter_list (); + tree_expression *expr = expression (); - symbol_scope af_scope = m_scope; - symbol_scope af_parent_scope = m_parent_scope; + symbol_scope af_scope = m_scope; + symbol_scope af_parent_scope = m_parent_scope; - symbol_scope new_scope; + symbol_scope new_scope; - if (af_scope) - new_scope = af_scope.dup (); + if (af_scope) + new_scope = af_scope.dup (); - // FIXME: if new scope is nullptr, then we are in big trouble here... + // FIXME: if new scope is nullptr, then we are in big trouble here... - tree_anon_fcn_handle *new_afh = new - tree_anon_fcn_handle (param_list ? param_list->dup (new_scope) : nullptr, - expr ? expr->dup (new_scope) : nullptr, - new_scope, af_parent_scope, line (), column ()); + tree_anon_fcn_handle *new_afh = new + tree_anon_fcn_handle (param_list ? param_list->dup (new_scope) : nullptr, + expr ? expr->dup (new_scope) : nullptr, + new_scope, af_parent_scope, line (), column ()); - new_afh->copy_base (*this); + new_afh->copy_base (*this); - return new_afh; - } + return new_afh; +} - octave_value - tree_anon_fcn_handle::evaluate (tree_evaluator& tw, int) - { - return tw.evaluate_anon_fcn_handle (*this); - } +octave_value +tree_anon_fcn_handle::evaluate (tree_evaluator& tw, int) +{ + return tw.evaluate_anon_fcn_handle (*this); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-fcn-handle.h --- a/libinterp/parse-tree/pt-fcn-handle.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-fcn-handle.h Thu Dec 01 20:05:44 2022 -0800 @@ -45,127 +45,127 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_fcn_handle : public tree_expression - { - public: +class tree_fcn_handle : public tree_expression +{ +public: - tree_fcn_handle (int l = -1, int c = -1) - : tree_expression (l, c), m_name () { } + tree_fcn_handle (int l = -1, int c = -1) + : tree_expression (l, c), m_name () { } - tree_fcn_handle (const std::string& n, int l = -1, int c = -1) - : tree_expression (l, c), m_name (n) { } + tree_fcn_handle (const std::string& n, int l = -1, int c = -1) + : tree_expression (l, c), m_name (n) { } - // No copying! + // No copying! - tree_fcn_handle (const tree_fcn_handle&) = delete; + tree_fcn_handle (const tree_fcn_handle&) = delete; - tree_fcn_handle& operator = (const tree_fcn_handle&) = delete; + tree_fcn_handle& operator = (const tree_fcn_handle&) = delete; - ~tree_fcn_handle (void) = default; + ~tree_fcn_handle (void) = default; - void print (std::ostream& os, bool pr_as_read_syntax = false, - bool pr_orig_txt = true); + void print (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); - void print_raw (std::ostream& os, bool pr_as_read_syntax = false, - bool pr_orig_txt = true); + void print_raw (std::ostream& os, bool pr_as_read_syntax = false, + bool pr_orig_txt = true); - std::string name (void) const { return m_name; } + std::string name (void) const { return m_name; } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator& tw, int nargout = 1); + octave_value evaluate (tree_evaluator& tw, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) - { - tw.visit_fcn_handle (*this); - } + void accept (tree_walker& tw) + { + tw.visit_fcn_handle (*this); + } - private: +private: - // The name of this function handle. - std::string m_name; - }; + // The name of this function handle. + std::string m_name; +}; - class tree_anon_fcn_handle : public tree_expression - { - public: +class tree_anon_fcn_handle : public tree_expression +{ +public: - tree_anon_fcn_handle (int l = -1, int c = -1) - : tree_expression (l, c), m_parameter_list (nullptr), - m_expression (nullptr), m_scope (), m_parent_scope (), - m_file_name () - { } + tree_anon_fcn_handle (int l = -1, int c = -1) + : tree_expression (l, c), m_parameter_list (nullptr), + m_expression (nullptr), m_scope (), m_parent_scope (), + m_file_name () + { } - tree_anon_fcn_handle (tree_parameter_list *pl, tree_expression *ex, - const symbol_scope& scope, - const symbol_scope& parent_scope, - int l = -1, int c = -1) - : tree_expression (l, c), m_parameter_list (pl), m_expression (ex), - m_scope (scope), m_parent_scope (parent_scope), m_file_name () - { } + tree_anon_fcn_handle (tree_parameter_list *pl, tree_expression *ex, + const symbol_scope& scope, + const symbol_scope& parent_scope, + int l = -1, int c = -1) + : tree_expression (l, c), m_parameter_list (pl), m_expression (ex), + m_scope (scope), m_parent_scope (parent_scope), m_file_name () + { } - // No copying! + // No copying! - tree_anon_fcn_handle (const tree_anon_fcn_handle&) = delete; + tree_anon_fcn_handle (const tree_anon_fcn_handle&) = delete; - tree_anon_fcn_handle& operator = (const tree_anon_fcn_handle&) = delete; + tree_anon_fcn_handle& operator = (const tree_anon_fcn_handle&) = delete; - ~tree_anon_fcn_handle (void); + ~tree_anon_fcn_handle (void); - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - tree_parameter_list * parameter_list (void) const - { - return m_parameter_list; - } + tree_parameter_list * parameter_list (void) const + { + return m_parameter_list; + } - tree_expression * expression (void) const { return m_expression; } + tree_expression * expression (void) const { return m_expression; } - symbol_scope scope (void) const { return m_scope; } + symbol_scope scope (void) const { return m_scope; } - symbol_scope parent_scope (void) const { return m_parent_scope; } + symbol_scope parent_scope (void) const { return m_parent_scope; } - bool has_parent_scope (void) const { return m_parent_scope.is_valid (); } + bool has_parent_scope (void) const { return m_parent_scope.is_valid (); } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator& tw, int nargout = 1); + octave_value evaluate (tree_evaluator& tw, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) { tw.visit_anon_fcn_handle (*this); } + void accept (tree_walker& tw) { tw.visit_anon_fcn_handle (*this); } - void stash_file_name (const std::string& file) { m_file_name = file; } + void stash_file_name (const std::string& file) { m_file_name = file; } - std::string file_name (void) const { return m_file_name; } + std::string file_name (void) const { return m_file_name; } - private: +private: - // Inputs parameters. - tree_parameter_list *m_parameter_list; + // Inputs parameters. + tree_parameter_list *m_parameter_list; - // Function body, limited to a single expression. - tree_expression *m_expression; + // Function body, limited to a single expression. + tree_expression *m_expression; - // Function scope. - symbol_scope m_scope; + // Function scope. + symbol_scope m_scope; - // Parent scope, or an invalid scope if none. - symbol_scope m_parent_scope; + // Parent scope, or an invalid scope if none. + symbol_scope m_parent_scope; - // Filename where the handle was defined. - std::string m_file_name; - }; + // Filename where the handle was defined. + std::string m_file_name; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-id.cc --- a/libinterp/parse-tree/pt-id.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-id.cc Thu Dec 01 20:05:44 2022 -0800 @@ -39,125 +39,125 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Symbols from the symbol table. +// Symbols from the symbol table. - void - tree_identifier::eval_undefined_error (void) - { - int l = line (); - int c = column (); +void +tree_identifier::eval_undefined_error (void) +{ + int l = line (); + int c = column (); - std::string msg = "'" + name () + "' undefined"; + std::string msg = "'" + name () + "' undefined"; - if (l > 0) - { - msg += " near line " + std::to_string (l); + if (l > 0) + { + msg += " near line " + std::to_string (l); - if (c > 0) - msg += ", column " + std::to_string (c); - } + if (c > 0) + msg += ", column " + std::to_string (c); + } - std::string missing_msg = maybe_missing_function_hook (name ()); + std::string missing_msg = maybe_missing_function_hook (name ()); - if (! missing_msg.empty ()) - msg += "\n\n" + missing_msg; + if (! missing_msg.empty ()) + msg += "\n\n" + missing_msg; - error_with_id ("Octave:undefined-function", "%s", msg.c_str ()); - } + error_with_id ("Octave:undefined-function", "%s", msg.c_str ()); +} - octave_lvalue - tree_identifier::lvalue (tree_evaluator& tw) - { - if (m_sym.is_added_static ()) - static_workspace_error (); +octave_lvalue +tree_identifier::lvalue (tree_evaluator& tw) +{ + if (m_sym.is_added_static ()) + static_workspace_error (); - return octave_lvalue (m_sym, tw.get_current_stack_frame ()); - } + return octave_lvalue (m_sym, tw.get_current_stack_frame ()); +} - tree_identifier * - tree_identifier::dup (symbol_scope& scope) const - { - // The new tree_identifier object contains a symbol_record - // entry from the duplicated scope. +tree_identifier * +tree_identifier::dup (symbol_scope& scope) const +{ + // The new tree_identifier object contains a symbol_record + // entry from the duplicated scope. - symbol_record new_sym = scope.find_symbol (name ()); + symbol_record new_sym = scope.find_symbol (name ()); - tree_identifier *new_id - = new tree_identifier (new_sym, line (), column ()); + tree_identifier *new_id + = new tree_identifier (new_sym, line (), column ()); - new_id->copy_base (*this); + new_id->copy_base (*this); - return new_id; - } + return new_id; +} - octave_value_list - tree_identifier::evaluate_n (tree_evaluator& tw, int nargout) - { - octave_value_list retval; +octave_value_list +tree_identifier::evaluate_n (tree_evaluator& tw, int nargout) +{ + octave_value_list retval; - octave_value val = tw.varval (m_sym); + octave_value val = tw.varval (m_sym); - if (val.is_undefined ()) - { - interpreter& interp = tw.get_interpreter (); + if (val.is_undefined ()) + { + interpreter& interp = tw.get_interpreter (); - symbol_table& symtab = interp.get_symbol_table (); + symbol_table& symtab = interp.get_symbol_table (); - val = symtab.find_function (m_sym.name ()); - } + val = symtab.find_function (m_sym.name ()); + } - if (val.is_defined ()) - { - // GAGME -- this would be cleaner if we required - // parens to indicate function calls. - // - // If this identifier refers to a function, we need to know - // whether it is indexed so that we can do the same thing - // for 'f' and 'f()'. If the index is present and the function - // object declares it can handle it, return the function object - // and let tree_index_expression::rvalue handle indexing. - // Otherwise, arrange to call the function here, so that we don't - // return the function definition as a value. + if (val.is_defined ()) + { + // GAGME -- this would be cleaner if we required + // parens to indicate function calls. + // + // If this identifier refers to a function, we need to know + // whether it is indexed so that we can do the same thing + // for 'f' and 'f()'. If the index is present and the function + // object declares it can handle it, return the function object + // and let tree_index_expression::rvalue handle indexing. + // Otherwise, arrange to call the function here, so that we don't + // return the function definition as a value. - octave_function *fcn = nullptr; + octave_function *fcn = nullptr; - if (val.is_function ()) - fcn = val.function_value (true); + if (val.is_function ()) + fcn = val.function_value (true); - if (fcn && ! (is_postfix_indexed () - && fcn->accepts_postfix_index (postfix_index ()))) - { - retval = fcn->call (tw, nargout); - } - else - { - if (print_result () && nargout == 0 - && tw.statement_printing_enabled ()) - { - octave_value_list args = ovl (val); - args.stash_name_tags (string_vector (name ())); - feval ("display", args); - } + if (fcn && ! (is_postfix_indexed () + && fcn->accepts_postfix_index (postfix_index ()))) + { + retval = fcn->call (tw, nargout); + } + else + { + if (print_result () && nargout == 0 + && tw.statement_printing_enabled ()) + { + octave_value_list args = ovl (val); + args.stash_name_tags (string_vector (name ())); + feval ("display", args); + } - retval = ovl (val); - } - } - else if (m_sym.is_added_static ()) - static_workspace_error (); - else - eval_undefined_error (); + retval = ovl (val); + } + } + else if (m_sym.is_added_static ()) + static_workspace_error (); + else + eval_undefined_error (); - return retval; - } + return retval; +} - octave_lvalue - tree_black_hole::lvalue (tree_evaluator& tw) - { - octave_lvalue retval (m_sym, tw.get_current_stack_frame ()); +octave_lvalue +tree_black_hole::lvalue (tree_evaluator& tw) +{ + octave_lvalue retval (m_sym, tw.get_current_stack_frame ()); - retval.mark_black_hole (); + retval.mark_black_hole (); - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-id.h --- a/libinterp/parse-tree/pt-id.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-id.h Thu Dec 01 20:05:44 2022 -0800 @@ -43,96 +43,96 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; +class tree_evaluator; - // Symbols from the symbol table. +// Symbols from the symbol table. - class tree_identifier : public tree_expression - { - friend class tree_index_expression; +class tree_identifier : public tree_expression +{ + friend class tree_index_expression; - public: +public: - tree_identifier (int l = -1, int c = -1) - : tree_expression (l, c), m_sym () { } + tree_identifier (int l = -1, int c = -1) + : tree_expression (l, c), m_sym () { } - tree_identifier (const symbol_record& s, - int l = -1, int c = -1) - : tree_expression (l, c), m_sym (s) { } + tree_identifier (const symbol_record& s, + int l = -1, int c = -1) + : tree_expression (l, c), m_sym (s) { } - // No copying! + // No copying! - tree_identifier (const tree_identifier&) = delete; + tree_identifier (const tree_identifier&) = delete; - tree_identifier& operator = (const tree_identifier&) = delete; + tree_identifier& operator = (const tree_identifier&) = delete; - ~tree_identifier (void) = default; + ~tree_identifier (void) = default; - bool is_identifier (void) const { return true; } + bool is_identifier (void) const { return true; } - std::string name (void) const { return m_sym.name (); } + std::string name (void) const { return m_sym.name (); } - virtual bool is_black_hole (void) const { return false; } + virtual bool is_black_hole (void) const { return false; } - void mark_as_formal_parameter (void) { m_sym.mark_formal (); } + void mark_as_formal_parameter (void) { m_sym.mark_formal (); } - // We really need to know whether this symbol refers to a variable - // or a function, but we may not know that yet. + // We really need to know whether this symbol refers to a variable + // or a function, but we may not know that yet. - bool lvalue_ok (void) const { return true; } + bool lvalue_ok (void) const { return true; } - octave_lvalue lvalue (tree_evaluator& tw); + octave_lvalue lvalue (tree_evaluator& tw); - void eval_undefined_error (void); + void eval_undefined_error (void); - void static_workspace_error (void) - { - error (R"(can not add variable "%s" to a static workspace)", - name ().c_str ()); - } + void static_workspace_error (void) + { + error (R"(can not add variable "%s" to a static workspace)", + name ().c_str ()); + } - tree_identifier * dup (symbol_scope& scope) const; + tree_identifier * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator& tw, int nargout = 1) - { - octave_value_list retval = evaluate_n (tw, nargout); + octave_value evaluate (tree_evaluator& tw, int nargout = 1) + { + octave_value_list retval = evaluate_n (tw, nargout); - return retval.length () > 0 ? retval(0) : octave_value (); - } + return retval.length () > 0 ? retval(0) : octave_value (); + } - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); - void accept (tree_walker& tw) - { - tw.visit_identifier (*this); - } + void accept (tree_walker& tw) + { + tw.visit_identifier (*this); + } - symbol_record symbol (void) const { return m_sym; } + symbol_record symbol (void) const { return m_sym; } - protected: +protected: - // The symbol record that this identifier references. - symbol_record m_sym; - }; + // The symbol record that this identifier references. + symbol_record m_sym; +}; - class tree_black_hole : public tree_identifier - { - public: +class tree_black_hole : public tree_identifier +{ +public: - tree_black_hole (int l = -1, int c = -1) - : tree_identifier (l, c) { } + tree_black_hole (int l = -1, int c = -1) + : tree_identifier (l, c) { } - std::string name (void) const { return "~"; } + std::string name (void) const { return "~"; } - bool is_black_hole (void) const { return true; } + bool is_black_hole (void) const { return true; } - tree_black_hole * dup (symbol_scope&) const - { - return new tree_black_hole; - } + tree_black_hole * dup (symbol_scope&) const + { + return new tree_black_hole; + } - octave_lvalue lvalue (tree_evaluator& tw); - }; + octave_lvalue lvalue (tree_evaluator& tw); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-idx.cc --- a/libinterp/parse-tree/pt-idx.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-idx.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,181 +44,546 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Index expressions. +// Index expressions. + +tree_index_expression::tree_index_expression (int l, int c) + : tree_expression (l, c), m_expr (nullptr), m_args (0), m_type (), + m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) { } - tree_index_expression::tree_index_expression (int l, int c) - : tree_expression (l, c), m_expr (nullptr), m_args (0), m_type (), - m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) { } +tree_index_expression::tree_index_expression (tree_expression *e, + tree_argument_list *lst, + int l, int c, char t) + : tree_expression (l, c), m_expr (e), m_args (0), m_type (), + m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) +{ + append (lst, t); +} - tree_index_expression::tree_index_expression (tree_expression *e, - tree_argument_list *lst, - int l, int c, char t) - : tree_expression (l, c), m_expr (e), m_args (0), m_type (), - m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) - { - append (lst, t); - } +tree_index_expression::tree_index_expression (tree_expression *e, + const std::string& n, + int l, int c) + : tree_expression (l, c), m_expr (e), m_args (0), m_type (), + m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) +{ + append (n); +} + +tree_index_expression::tree_index_expression (tree_expression *e, + tree_expression *df, + int l, int c) + : tree_expression (l, c), m_expr (e), m_args (0), m_type (), + m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) +{ + append (df); +} + +tree_index_expression * +tree_index_expression::append (tree_argument_list *lst, char t) +{ + m_args.push_back (lst); + m_type.append (1, t); + m_arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ()); + m_dyn_field.push_back (static_cast (nullptr)); + + if (lst && lst->has_magic_tilde ()) + error ("invalid use of empty argument (~) in index expression"); + + return this; +} - tree_index_expression::tree_index_expression (tree_expression *e, - const std::string& n, - int l, int c) - : tree_expression (l, c), m_expr (e), m_args (0), m_type (), - m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) - { - append (n); - } +tree_index_expression * +tree_index_expression::append (const std::string& n) +{ + m_args.push_back (static_cast (nullptr)); + m_type += '.'; + m_arg_nm.push_back (n); + m_dyn_field.push_back (static_cast (nullptr)); + + return this; +} + +tree_index_expression * +tree_index_expression::append (tree_expression *df) +{ + m_args.push_back (static_cast (nullptr)); + m_type += '.'; + m_arg_nm.push_back (""); + m_dyn_field.push_back (df); + + return this; +} + +tree_index_expression::~tree_index_expression (void) +{ + delete m_expr; - tree_index_expression::tree_index_expression (tree_expression *e, - tree_expression *df, - int l, int c) - : tree_expression (l, c), m_expr (e), m_args (0), m_type (), - m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) - { - append (df); - } + while (! m_args.empty ()) + { + auto p = m_args.begin (); + delete *p; + m_args.erase (p); + } + + while (! m_dyn_field.empty ()) + { + auto p = m_dyn_field.begin (); + delete *p; + m_dyn_field.erase (p); + } +} + +// This is useful for printing the name of the variable in an indexed +// assignment. + +std::string +tree_index_expression::name (void) const +{ + return m_expr->name (); +} + +std::string +tree_index_expression::get_struct_index +(tree_evaluator& tw, + std::list::const_iterator p_arg_nm, + std::list::const_iterator p_dyn_field) const +{ + std::string fn = (*p_arg_nm)(0); + + if (fn.empty ()) + { + tree_expression *df = *p_dyn_field; - tree_index_expression * - tree_index_expression::append (tree_argument_list *lst, char t) + if (df) + { + octave_value t = df->evaluate (tw); + + fn = t.xstring_value ("dynamic structure field names must be strings"); + } + else + panic_impossible (); + } + + return fn; +} + +octave_lvalue +tree_index_expression::lvalue (tree_evaluator& tw) +{ + std::list idx; + + int n = m_args.size (); + + auto p_args = m_args.begin (); + auto p_arg_nm = m_arg_nm.begin (); + auto p_dyn_field = m_dyn_field.begin (); + + octave_lvalue retval = m_expr->lvalue (tw); + + unwind_action + act ([&tw] (const octave_value& val, + const std::string& index_type, + const std::list& index_list) { - m_args.push_back (lst); - m_type.append (1, t); - m_arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ()); - m_dyn_field.push_back (static_cast (nullptr)); + tw.set_indexed_object (val); + tw.set_index_list (index_type, index_list); + }, tw.indexed_object (), tw.index_type (), tw.index_list ()); + + tw.set_indexed_object (retval.value ()); + tw.clear_index_list (); - if (lst && lst->has_magic_tilde ()) - error ("invalid use of empty argument (~) in index expression"); + for (int i = 0; i < n; i++) + { + switch (m_type[i]) + { + case '(': + { + octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm); - return this; - } + tw.append_index_list ('(', tidx); + idx.push_back (tidx); + } + break; + + case '{': + { + octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm); - tree_index_expression * - tree_index_expression::append (const std::string& n) - { - m_args.push_back (static_cast (nullptr)); - m_type += '.'; - m_arg_nm.push_back (n); - m_dyn_field.push_back (static_cast (nullptr)); + tw.append_index_list ('{', tidx); + idx.push_back (tidx); + } + break; + + case '.': + { + octave_value tidx = get_struct_index (tw, p_arg_nm, p_dyn_field); + + tw.append_index_list ('.', tidx); + idx.push_back (tidx); + } + break; + + default: + panic_impossible (); + } + + if (idx.back ().empty ()) + error ("invalid empty index list"); + + p_args++; + p_arg_nm++; + p_dyn_field++; + } - return this; - } + retval.set_index (m_type, idx); + + return retval; +} + +tree_index_expression * +tree_index_expression::dup (symbol_scope& scope) const +{ + tree_index_expression *new_idx_expr + = new tree_index_expression (line (), column ()); + + new_idx_expr->m_expr = (m_expr ? m_expr->dup (scope) : nullptr); - tree_index_expression * - tree_index_expression::append (tree_expression *df) - { - m_args.push_back (static_cast (nullptr)); - m_type += '.'; - m_arg_nm.push_back (""); - m_dyn_field.push_back (df); + std::list new_args; + + for (const tree_argument_list *elt : m_args) + new_args.push_back (elt ? elt->dup (scope) : nullptr); + + new_idx_expr->m_args = new_args; + + new_idx_expr->m_type = m_type; + + new_idx_expr->m_arg_nm = m_arg_nm; + + std::list new_dyn_field; + + for (const tree_expression *elt : m_dyn_field) + new_dyn_field.push_back (elt ? elt->dup (scope) : nullptr); - return this; - } - - tree_index_expression::~tree_index_expression (void) - { - delete m_expr; + new_idx_expr->m_dyn_field = new_dyn_field; - while (! m_args.empty ()) - { - auto p = m_args.begin (); - delete *p; - m_args.erase (p); - } + new_idx_expr->copy_base (*this); + + return new_idx_expr; +} - while (! m_dyn_field.empty ()) - { - auto p = m_dyn_field.begin (); - delete *p; - m_dyn_field.erase (p); - } - } +// Unlike Matlab, which does not allow the result of a function call +// or array indexing expression to be further indexed, Octave attempts +// to handle arbitrary index expressions. For example, Octave allows +// expressions like +// +// svd (rand (10))(1:5) +// +// Although octave_value objects may contain function objects, no +// indexing operation or function call is supposed to return them +// directly. Instead, the language is supposed to only allow function +// objects to be stored as function handles (named or anonymous) or as +// inline functions. The only place a function object should appear +// directly is if the symbol stored in a tree_identifier object +// resolves to a function. This means that the only place we need to +// look for functions is in the first element of the index +// expression. +// +// Steps: +// +// * Obtain the initial value from the expression component of the +// tree_index_expression object. If it is a tree_identifier object +// indexed by '(args)' and the identifier is not a variable, then +// perform a function call. Use the (optional) arguments to perform +// the function lookup so we choose the correct function or class +// method to call. Otherwise, evaluate the first expression +// without any additional arguments. +// +// * Iterate over the remaining elements of the index expression and +// call the octave_value::subsref method. If indexing a class or +// classdef object, build up a list of indices for a call to the +// subsref method for the object. Otherwise, use the result of +// each temporary evaluation for the next index element. +// +// * If not indexing a class or classdef object and any partial +// expression evaluation produces a class or classdef object, then +// build up a complete argument list from that point on for a final +// subsref call for that object. +// +// Multiple partial evaluations may be required. For example, +// given a class or classdef object X, then for the expression +// +// x.a{end}(2:end).b +// +// we must evaluate x.a to obtain the size for the first {end} +// expression, then we must evaluate x.a{end} to obtain the size +// for the second (2:end) expression. Finally, the complete +// expression may be evaluated. +// +// If X is a cell array in the above expression, and none of the +// intermediate evaluations produces a class or classdef object, +// then the evaluation is performed as the following series of +// steps +// +// tmp = x.a +// tmp = tmp{end} +// tmp = tmp(2:end) +// result = tmp.b +// +// If any of the partial evaluations produces a class or classdef +// object, then the subsref method for that object is called as +// described above. For example, suppose x.a produces a classdef +// object. Then the evaluation is performed as the following +// series of steps +// +// base_expr = tmp = x.a +// tmp = base_expr{end} +// base_expr{end}(2:end).b +// +// In the last two steps, the partial value computed in the +// previous step is used to determine the value of END. - // This is useful for printing the name of the variable in an indexed - // assignment. +octave_value_list +tree_index_expression::evaluate_n (tree_evaluator& tw, int nargout) +{ + octave_value_list retval; + + panic_if (m_args.empty ()); + + auto p_args = m_args.begin (); + auto p_arg_nm = m_arg_nm.begin (); + auto p_dyn_field = m_dyn_field.begin (); - std::string - tree_index_expression::name (void) const - { - return m_expr->name (); - } + int n = m_args.size (); + int beg = 0; + + octave_value base_expr_val; + + if (m_expr->is_identifier () && m_type[beg] == '(') + { + tree_identifier *id = dynamic_cast (m_expr); + + bool is_var = tw.is_variable (m_expr); + + std::string nm = id->name (); - std::string - tree_index_expression::get_struct_index - (tree_evaluator& tw, - std::list::const_iterator p_arg_nm, - std::list::const_iterator p_dyn_field) const - { - std::string fn = (*p_arg_nm)(0); + if (is_var && is_word_list_cmd ()) + { + bool maybe_binary_op = false; + if ((*p_args) && (*p_args)->length () > 0) + { + // check if first character of first argument might be (the + // start of) a binary operator + std::string ops = "+-*/\\.^|&"; + string_vector arg_list = (*p_args)->get_arg_names (); + if (! arg_list.isempty () + && (ops.find (arg_list(0)[1]) != std::string::npos)) + maybe_binary_op = true; + } + + std::string advice; + if (maybe_binary_op) + advice = "\nCheck whitespace around potential binary operator."; + + error ("variable \"%s\" used as function in command style expression%s", + nm.c_str (), advice.c_str ()); + } + + if (! is_var) + { + octave_value_list first_args; - if (fn.empty ()) - { - tree_expression *df = *p_dyn_field; + tree_argument_list *al = *p_args; + + if (al && al->length () > 0) + { + unwind_action act ([&tw] (const std::list *lvl) + { + tw.set_lvalue_list (lvl); + }, tw.lvalue_list ()); + + tw.set_lvalue_list (nullptr); + + string_vector anm = *p_arg_nm; - if (df) - { - octave_value t = df->evaluate (tw); + first_args = tw.convert_to_const_vector (al); + + first_args.stash_name_tags (anm); + } + + interpreter& interp = tw.get_interpreter (); + + symbol_table& symtab = interp.get_symbol_table (); + + octave_value val = symtab.find_function (nm, first_args); + + octave_function *fcn = nullptr; + + if (val.is_function ()) + fcn = val.function_value (true); - fn = t.xstring_value ("dynamic structure field names must be strings"); - } - else - panic_impossible (); - } + if (fcn) + { + try + { + retval = fcn->call (tw, nargout, first_args); + } + catch (index_exception& ie) + { + tw.final_index_error (ie, m_expr); + } - return fn; - } + beg++; + p_args++; + p_arg_nm++; + p_dyn_field++; + + if (n > beg) + { + // More indices to follow. Silently ignore + // extra output values. + + if (retval.length () == 0) + error ("indexing undefined value"); + else + base_expr_val = retval(0); + } + else + { + // No more indices, so we are done. - octave_lvalue - tree_index_expression::lvalue (tree_evaluator& tw) - { - std::list idx; + // See note at end of function about deleting + // temporaries prior to pushing result. + + base_expr_val = octave_value (); + first_args = octave_value_list (); + + return retval; + } + } + } + } + + if (base_expr_val.is_undefined ()) + base_expr_val = m_expr->evaluate (tw); - int n = m_args.size (); + // If we are indexing an object or looking at something like + // + // classname.static_function (args, ...); + // + // then we'll just build a complete index list for one big subsref + // call. If the expression we are indexing is a classname then + // base_expr_val will be an octave_classdef_meta object. If we have + // files in a +packagename folder, they will also be an + // octave_classdef_meta object, but we don't want to index them. - auto p_args = m_args.begin (); - auto p_arg_nm = m_arg_nm.begin (); - auto p_dyn_field = m_dyn_field.begin (); + std::list idx_list; - octave_lvalue retval = m_expr->lvalue (tw); + { + // Note: need new scope so that the following unwind action will + // happen before we perform the final indexing for objects (for + // example). unwind_action - act ([&tw] (const octave_value& val, - const std::string& index_type, - const std::list& index_list) - { - tw.set_indexed_object (val); - tw.set_index_list (index_type, index_list); - }, tw.indexed_object (), tw.index_type (), tw.index_list ()); + act ([&tw] (const octave_value& val, + const std::string& index_type, + const std::list& index_list) + { + tw.set_indexed_object (val); + tw.set_index_list (index_type, index_list); + }, + tw.indexed_object (), + tw.index_type (), tw.index_list ()); - tw.set_indexed_object (retval.value ()); + tw.set_indexed_object (); tw.clear_index_list (); - for (int i = 0; i < n; i++) + bool indexing_object = (base_expr_val.isobject () + || base_expr_val.isjava () + || (base_expr_val.is_classdef_meta () + && ! base_expr_val.is_package ())); + + octave_value partial_expr_val = base_expr_val; + + for (int i = beg; i < n; i++) { + if (i > beg) + { + if (! indexing_object) + { + // Evaluate what we have so far. + + try + { + // Silently ignore extra output values. + + octave_value_list tmp_list + = base_expr_val.subsref (m_type.substr (beg, i-beg), + idx_list, nargout); + + partial_expr_val + = tmp_list.length () ? tmp_list(0) : octave_value (); + + base_expr_val = partial_expr_val; + + if (partial_expr_val.is_cs_list ()) + err_indexed_cs_list (); + + retval = partial_expr_val; + + beg = i; + idx_list.clear (); + tw.clear_index_list (); + + if (partial_expr_val.isobject () + || partial_expr_val.isjava () + || (partial_expr_val.is_classdef_meta () + && ! partial_expr_val.is_package ())) + { + // Found an object, so now we'll build up + // complete index list for one big subsref + // call from this point on. + + // FIXME: is is also possible to have a + // static method call buried somewhere in + // the depths of a complex indexing + // expression so that we would also need to + // check for an octave_classdef_meta object + // here? + + indexing_object = true; + } + } + catch (index_exception& ie) + { + tw.final_index_error (ie, m_expr); + } + } + } + + tw.set_indexed_object (partial_expr_val); + switch (m_type[i]) { case '(': { - octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm); - - tw.append_index_list ('(', tidx); - idx.push_back (tidx); + octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm); + tw.append_index_list ('(', tmp); + idx_list.push_back (tmp); } break; case '{': { - octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm); - - tw.append_index_list ('{', tidx); - idx.push_back (tidx); + octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm); + tw.append_index_list ('{', tmp); + idx_list.push_back (tmp); } break; case '.': { - octave_value tidx = get_struct_index (tw, p_arg_nm, p_dyn_field); - - tw.append_index_list ('.', tidx); - idx.push_back (tidx); + octave_value tmp = get_struct_index (tw, p_arg_nm, p_dyn_field); + tw.append_index_list ('.', tmp); + idx_list.push_back (tmp); } break; @@ -226,477 +591,112 @@ panic_impossible (); } - if (idx.back ().empty ()) - error ("invalid empty index list"); - p_args++; p_arg_nm++; p_dyn_field++; } - - retval.set_index (m_type, idx); - - return retval; - } - - tree_index_expression * - tree_index_expression::dup (symbol_scope& scope) const - { - tree_index_expression *new_idx_expr - = new tree_index_expression (line (), column ()); - - new_idx_expr->m_expr = (m_expr ? m_expr->dup (scope) : nullptr); - - std::list new_args; - - for (const tree_argument_list *elt : m_args) - new_args.push_back (elt ? elt->dup (scope) : nullptr); - - new_idx_expr->m_args = new_args; - - new_idx_expr->m_type = m_type; - - new_idx_expr->m_arg_nm = m_arg_nm; - - std::list new_dyn_field; - - for (const tree_expression *elt : m_dyn_field) - new_dyn_field.push_back (elt ? elt->dup (scope) : nullptr); - - new_idx_expr->m_dyn_field = new_dyn_field; - - new_idx_expr->copy_base (*this); - - return new_idx_expr; } - // Unlike Matlab, which does not allow the result of a function call - // or array indexing expression to be further indexed, Octave attempts - // to handle arbitrary index expressions. For example, Octave allows - // expressions like - // - // svd (rand (10))(1:5) - // - // Although octave_value objects may contain function objects, no - // indexing operation or function call is supposed to return them - // directly. Instead, the language is supposed to only allow function - // objects to be stored as function handles (named or anonymous) or as - // inline functions. The only place a function object should appear - // directly is if the symbol stored in a tree_identifier object - // resolves to a function. This means that the only place we need to - // look for functions is in the first element of the index - // expression. - // - // Steps: - // - // * Obtain the initial value from the expression component of the - // tree_index_expression object. If it is a tree_identifier object - // indexed by '(args)' and the identifier is not a variable, then - // perform a function call. Use the (optional) arguments to perform - // the function lookup so we choose the correct function or class - // method to call. Otherwise, evaluate the first expression - // without any additional arguments. - // - // * Iterate over the remaining elements of the index expression and - // call the octave_value::subsref method. If indexing a class or - // classdef object, build up a list of indices for a call to the - // subsref method for the object. Otherwise, use the result of - // each temporary evaluation for the next index element. - // - // * If not indexing a class or classdef object and any partial - // expression evaluation produces a class or classdef object, then - // build up a complete argument list from that point on for a final - // subsref call for that object. - // - // Multiple partial evaluations may be required. For example, - // given a class or classdef object X, then for the expression - // - // x.a{end}(2:end).b - // - // we must evaluate x.a to obtain the size for the first {end} - // expression, then we must evaluate x.a{end} to obtain the size - // for the second (2:end) expression. Finally, the complete - // expression may be evaluated. - // - // If X is a cell array in the above expression, and none of the - // intermediate evaluations produces a class or classdef object, - // then the evaluation is performed as the following series of - // steps - // - // tmp = x.a - // tmp = tmp{end} - // tmp = tmp(2:end) - // result = tmp.b - // - // If any of the partial evaluations produces a class or classdef - // object, then the subsref method for that object is called as - // described above. For example, suppose x.a produces a classdef - // object. Then the evaluation is performed as the following - // series of steps - // - // base_expr = tmp = x.a - // tmp = base_expr{end} - // base_expr{end}(2:end).b - // - // In the last two steps, the partial value computed in the - // previous step is used to determine the value of END. - - octave_value_list - tree_index_expression::evaluate_n (tree_evaluator& tw, int nargout) - { - octave_value_list retval; - - panic_if (m_args.empty ()); - - auto p_args = m_args.begin (); - auto p_arg_nm = m_arg_nm.begin (); - auto p_dyn_field = m_dyn_field.begin (); - - int n = m_args.size (); - int beg = 0; - - octave_value base_expr_val; - - if (m_expr->is_identifier () && m_type[beg] == '(') - { - tree_identifier *id = dynamic_cast (m_expr); - - bool is_var = tw.is_variable (m_expr); - - std::string nm = id->name (); - - if (is_var && is_word_list_cmd ()) - { - bool maybe_binary_op = false; - if ((*p_args) && (*p_args)->length () > 0) - { - // check if first character of first argument might be (the - // start of) a binary operator - std::string ops = "+-*/\\.^|&"; - string_vector arg_list = (*p_args)->get_arg_names (); - if (! arg_list.isempty () - && (ops.find (arg_list(0)[1]) != std::string::npos)) - maybe_binary_op = true; - } - - std::string advice; - if (maybe_binary_op) - advice = "\nCheck whitespace around potential binary operator."; - - error ("variable \"%s\" used as function in command style expression%s", - nm.c_str (), advice.c_str ()); - } - - if (! is_var) - { - octave_value_list first_args; - - tree_argument_list *al = *p_args; - - if (al && al->length () > 0) - { - unwind_action act ([&tw] (const std::list *lvl) - { - tw.set_lvalue_list (lvl); - }, tw.lvalue_list ()); - - tw.set_lvalue_list (nullptr); - - string_vector anm = *p_arg_nm; - - first_args = tw.convert_to_const_vector (al); - - first_args.stash_name_tags (anm); - } - - interpreter& interp = tw.get_interpreter (); - - symbol_table& symtab = interp.get_symbol_table (); + // If ! idx_list.empty () that means we still have stuff to index + // otherwise they would have been dealt with and idx_list would have + // been emptied. + if (! idx_list.empty ()) + { + // This is for +package and other classdef_meta objects + if (! base_expr_val.is_function () + || base_expr_val.is_classdef_meta ()) + { + try + { + retval = base_expr_val.subsref (m_type.substr (beg, n-beg), + idx_list, nargout); + beg = n; + idx_list.clear (); + } + catch (index_exception& ie) + { + tw.final_index_error (ie, m_expr); + } + } + else + { + // FIXME: we want this to only be a superclass constructor + // call Should we actually make a check for this or are all + // other types of calls already dealt with? - octave_value val = symtab.find_function (nm, first_args); - - octave_function *fcn = nullptr; - - if (val.is_function ()) - fcn = val.function_value (true); - - if (fcn) - { - try - { - retval = fcn->call (tw, nargout, first_args); - } - catch (index_exception& ie) - { - tw.final_index_error (ie, m_expr); - } - - beg++; - p_args++; - p_arg_nm++; - p_dyn_field++; - - if (n > beg) - { - // More indices to follow. Silently ignore - // extra output values. + octave_function *fcn = base_expr_val.function_value (); - if (retval.length () == 0) - error ("indexing undefined value"); - else - base_expr_val = retval(0); - } - else - { - // No more indices, so we are done. - - // See note at end of function about deleting - // temporaries prior to pushing result. - - base_expr_val = octave_value (); - first_args = octave_value_list (); + if (fcn) + { + try + { + // FIXME: is it possible for the IDX_LIST to have + // more than one element here? Do we need to check? - return retval; - } - } - } - } - - if (base_expr_val.is_undefined ()) - base_expr_val = m_expr->evaluate (tw); + octave_value_list final_args; - // If we are indexing an object or looking at something like - // - // classname.static_function (args, ...); - // - // then we'll just build a complete index list for one big subsref - // call. If the expression we are indexing is a classname then - // base_expr_val will be an octave_classdef_meta object. If we have - // files in a +packagename folder, they will also be an - // octave_classdef_meta object, but we don't want to index them. - - std::list idx_list; - - { - // Note: need new scope so that the following unwind action will - // happen before we perform the final indexing for objects (for - // example). + if (idx_list.size () != 1) + error ("unexpected extra index at end of expression"); - unwind_action - act ([&tw] (const octave_value& val, - const std::string& index_type, - const std::list& index_list) - { - tw.set_indexed_object (val); - tw.set_index_list (index_type, index_list); - }, - tw.indexed_object (), - tw.index_type (), tw.index_list ()); - - tw.set_indexed_object (); - tw.clear_index_list (); + if (m_type[beg] != '(') + error ("invalid index type '%c' for function call", + m_type[beg]); - bool indexing_object = (base_expr_val.isobject () - || base_expr_val.isjava () - || (base_expr_val.is_classdef_meta () - && ! base_expr_val.is_package ())); - - octave_value partial_expr_val = base_expr_val; - - for (int i = beg; i < n; i++) - { - if (i > beg) - { - if (! indexing_object) - { - // Evaluate what we have so far. - - try - { - // Silently ignore extra output values. - - octave_value_list tmp_list - = base_expr_val.subsref (m_type.substr (beg, i-beg), - idx_list, nargout); + final_args = idx_list.front (); - partial_expr_val - = tmp_list.length () ? tmp_list(0) : octave_value (); - - base_expr_val = partial_expr_val; - - if (partial_expr_val.is_cs_list ()) - err_indexed_cs_list (); - - retval = partial_expr_val; - - beg = i; - idx_list.clear (); - tw.clear_index_list (); + // FIXME: Do we ever need the names of the arguments + // passed to FCN here? - if (partial_expr_val.isobject () - || partial_expr_val.isjava () - || (partial_expr_val.is_classdef_meta () - && ! partial_expr_val.is_package ())) - { - // Found an object, so now we'll build up - // complete index list for one big subsref - // call from this point on. - - // FIXME: is is also possible to have a - // static method call buried somewhere in - // the depths of a complex indexing - // expression so that we would also need to - // check for an octave_classdef_meta object - // here? - - indexing_object = true; - } - } - catch (index_exception& ie) - { - tw.final_index_error (ie, m_expr); - } + retval = fcn->call (tw, nargout, final_args); + } + catch (index_exception& ie) + { + tw.final_index_error (ie, m_expr); } } - - tw.set_indexed_object (partial_expr_val); - - switch (m_type[i]) - { - case '(': - { - octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm); - tw.append_index_list ('(', tmp); - idx_list.push_back (tmp); - } - break; - - case '{': - { - octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm); - tw.append_index_list ('{', tmp); - idx_list.push_back (tmp); - } - break; - - case '.': - { - octave_value tmp = get_struct_index (tw, p_arg_nm, p_dyn_field); - tw.append_index_list ('.', tmp); - idx_list.push_back (tmp); - } - break; - - default: - panic_impossible (); - } - - p_args++; - p_arg_nm++; - p_dyn_field++; } } - // If ! idx_list.empty () that means we still have stuff to index - // otherwise they would have been dealt with and idx_list would have - // been emptied. - if (! idx_list.empty ()) - { - // This is for +package and other classdef_meta objects - if (! base_expr_val.is_function () - || base_expr_val.is_classdef_meta ()) - { - try - { - retval = base_expr_val.subsref (m_type.substr (beg, n-beg), - idx_list, nargout); - beg = n; - idx_list.clear (); - } - catch (index_exception& ie) - { - tw.final_index_error (ie, m_expr); - } - } - else - { - // FIXME: we want this to only be a superclass constructor - // call Should we actually make a check for this or are all - // other types of calls already dealt with? + // FIXME: when can the following happen? In what case does indexing + // result in a value that is a function? Classdef method calls? + // Something else? + + octave_value val = (retval.length () ? retval(0) : octave_value ()); - octave_function *fcn = base_expr_val.function_value (); - - if (fcn) - { - try - { - // FIXME: is it possible for the IDX_LIST to have - // more than one element here? Do we need to check? - - octave_value_list final_args; + if (val.is_function ()) + { + octave_function *fcn = val.function_value (true); - if (idx_list.size () != 1) - error ("unexpected extra index at end of expression"); + if (fcn) + { + octave_value_list final_args; - if (m_type[beg] != '(') - error ("invalid index type '%c' for function call", - m_type[beg]); - - final_args = idx_list.front (); - - // FIXME: Do we ever need the names of the arguments - // passed to FCN here? + if (! idx_list.empty ()) + { + if (n - beg != 1) + error ("unexpected extra index at end of expression"); - retval = fcn->call (tw, nargout, final_args); - } - catch (index_exception& ie) - { - tw.final_index_error (ie, m_expr); - } - } - } - } + if (m_type[beg] != '(') + error ("invalid index type '%c' for function call", + m_type[beg]); - // FIXME: when can the following happen? In what case does indexing - // result in a value that is a function? Classdef method calls? - // Something else? - - octave_value val = (retval.length () ? retval(0) : octave_value ()); + final_args = idx_list.front (); + } - if (val.is_function ()) - { - octave_function *fcn = val.function_value (true); - - if (fcn) - { - octave_value_list final_args; + retval = fcn->call (tw, nargout, final_args); + } + } - if (! idx_list.empty ()) - { - if (n - beg != 1) - error ("unexpected extra index at end of expression"); - - if (m_type[beg] != '(') - error ("invalid index type '%c' for function call", - m_type[beg]); - - final_args = idx_list.front (); - } + // Delete any temporary values prior to returning so that + // destructors for any temporary classdef handle objects will be + // called before we return. - retval = fcn->call (tw, nargout, final_args); - } - } + idx_list.clear (); + base_expr_val = octave_value (); + val = octave_value (); - // Delete any temporary values prior to returning so that - // destructors for any temporary classdef handle objects will be - // called before we return. - - idx_list.clear (); - base_expr_val = octave_value (); - val = octave_value (); - - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-idx.h --- a/libinterp/parse-tree/pt-idx.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-idx.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,112 +41,112 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class octave_lvalue; - class symbol_scope; - class tree_argument_list; - class tree_evaluator; +class octave_lvalue; +class symbol_scope; +class tree_argument_list; +class tree_evaluator; - // Index expressions. +// Index expressions. - class tree_index_expression : public tree_expression - { - public: +class tree_index_expression : public tree_expression +{ +public: - tree_index_expression (tree_expression *e = nullptr, - tree_argument_list *lst = nullptr, - int l = -1, int c = -1, char t = '('); + tree_index_expression (tree_expression *e = nullptr, + tree_argument_list *lst = nullptr, + int l = -1, int c = -1, char t = '('); - tree_index_expression (tree_expression *e, const std::string& n, - int l = -1, int c = -1); + tree_index_expression (tree_expression *e, const std::string& n, + int l = -1, int c = -1); - tree_index_expression (tree_expression *e, tree_expression *df, - int l = -1, int c = -1); + tree_index_expression (tree_expression *e, tree_expression *df, + int l = -1, int c = -1); - // No copying! + // No copying! - tree_index_expression (const tree_index_expression&) = delete; + tree_index_expression (const tree_index_expression&) = delete; - tree_index_expression& operator = (const tree_index_expression&) = delete; + tree_index_expression& operator = (const tree_index_expression&) = delete; - ~tree_index_expression (void); + ~tree_index_expression (void); - tree_index_expression * - append (tree_argument_list *lst = nullptr, char t = '('); + tree_index_expression * + append (tree_argument_list *lst = nullptr, char t = '('); - tree_index_expression * append (const std::string& n); + tree_index_expression * append (const std::string& n); - tree_index_expression * append (tree_expression *df); + tree_index_expression * append (tree_expression *df); - bool is_index_expression (void) const { return true; } + bool is_index_expression (void) const { return true; } - std::string name (void) const; + std::string name (void) const; - tree_expression * expression (void) { return m_expr; } + tree_expression * expression (void) { return m_expr; } - std::list arg_lists (void) { return m_args; } + std::list arg_lists (void) { return m_args; } - std::string type_tags (void) { return m_type; } + std::string type_tags (void) { return m_type; } - std::list arg_names (void) { return m_arg_nm; } + std::list arg_names (void) { return m_arg_nm; } - std::list dyn_fields (void) { return m_dyn_field; } + std::list dyn_fields (void) { return m_dyn_field; } - void mark_word_list_cmd (void) { m_word_list_cmd = true; } + void mark_word_list_cmd (void) { m_word_list_cmd = true; } - bool is_word_list_cmd (void) const { return m_word_list_cmd; } + bool is_word_list_cmd (void) const { return m_word_list_cmd; } - bool lvalue_ok (void) const { return m_expr->lvalue_ok (); } + bool lvalue_ok (void) const { return m_expr->lvalue_ok (); } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - octave_lvalue lvalue (tree_evaluator& tw); + octave_lvalue lvalue (tree_evaluator& tw); - tree_index_expression * dup (symbol_scope& scope) const; + tree_index_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator& tw, int nargout = 1) - { - octave_value_list retval = evaluate_n (tw, nargout); + octave_value evaluate (tree_evaluator& tw, int nargout = 1) + { + octave_value_list retval = evaluate_n (tw, nargout); - return retval.length () > 0 ? retval(0) : octave_value (); - } + return retval.length () > 0 ? retval(0) : octave_value (); + } - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1); - void accept (tree_walker& tw) - { - tw.visit_index_expression (*this); - } + void accept (tree_walker& tw) + { + tw.visit_index_expression (*this); + } - std::string - get_struct_index - (tree_evaluator& tw, std::list::const_iterator p_arg_nm, - std::list::const_iterator p_dyn_field) const; + std::string + get_struct_index + (tree_evaluator& tw, std::list::const_iterator p_arg_nm, + std::list::const_iterator p_dyn_field) const; - private: +private: - // The LHS of this index expression. - tree_expression *m_expr; + // The LHS of this index expression. + tree_expression *m_expr; - // The indices (only valid if type == paren || type == brace). - std::list m_args; + // The indices (only valid if type == paren || type == brace). + std::list m_args; - // The type of this index expression. - std::string m_type; + // The type of this index expression. + std::string m_type; - // The names of the arguments. Used for constant struct element - // references. - std::list m_arg_nm; + // The names of the arguments. Used for constant struct element + // references. + std::list m_arg_nm; - // The list of dynamic field names, if any. - std::list m_dyn_field; + // The list of dynamic field names, if any. + std::list m_dyn_field; - // TRUE if this expression was parsed as a word list command. - bool m_word_list_cmd; + // TRUE if this expression was parsed as a word list command. + bool m_word_list_cmd; - tree_index_expression (int l, int c); + tree_index_expression (int l, int c); - octave_map make_arg_struct (void) const; - }; + octave_map make_arg_struct (void) const; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-jump.h --- a/libinterp/parse-tree/pt-jump.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-jump.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,74 +33,74 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Break. +// Break. - class tree_break_command : public tree_command - { - public: +class tree_break_command : public tree_command +{ +public: - tree_break_command (int l = -1, int c = -1) - : tree_command (l, c) { } + tree_break_command (int l = -1, int c = -1) + : tree_command (l, c) { } - // No copying! + // No copying! - tree_break_command (const tree_break_command&) = delete; + tree_break_command (const tree_break_command&) = delete; - tree_break_command& operator = (const tree_break_command&) = delete; + tree_break_command& operator = (const tree_break_command&) = delete; - ~tree_break_command (void) = default; + ~tree_break_command (void) = default; - void accept (tree_walker& tw) - { - tw.visit_break_command (*this); - } - }; + void accept (tree_walker& tw) + { + tw.visit_break_command (*this); + } +}; - // Continue. +// Continue. - class tree_continue_command : public tree_command - { - public: +class tree_continue_command : public tree_command +{ +public: - tree_continue_command (int l = -1, int c = -1) - : tree_command (l, c) { } + tree_continue_command (int l = -1, int c = -1) + : tree_command (l, c) { } - // No copying! + // No copying! - tree_continue_command (const tree_continue_command&) = delete; + tree_continue_command (const tree_continue_command&) = delete; - tree_continue_command& operator = (const tree_continue_command&) = delete; - - ~tree_continue_command (void) = default; + tree_continue_command& operator = (const tree_continue_command&) = delete; - void accept (tree_walker& tw) - { - tw.visit_continue_command (*this); - } - }; + ~tree_continue_command (void) = default; - // Return. - - class tree_return_command : public tree_command + void accept (tree_walker& tw) { - public: + tw.visit_continue_command (*this); + } +}; + +// Return. - tree_return_command (int l = -1, int c = -1) - : tree_command (l, c) { } +class tree_return_command : public tree_command +{ +public: - // No copying! - - tree_return_command (const tree_return_command&) = delete; + tree_return_command (int l = -1, int c = -1) + : tree_command (l, c) { } - tree_return_command& operator = (const tree_return_command&) = delete; + // No copying! - ~tree_return_command (void) = default; + tree_return_command (const tree_return_command&) = delete; + + tree_return_command& operator = (const tree_return_command&) = delete; - void accept (tree_walker& tw) - { - tw.visit_return_command (*this); - } - }; + ~tree_return_command (void) = default; + + void accept (tree_walker& tw) + { + tw.visit_return_command (*this); + } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-loop.cc --- a/libinterp/parse-tree/pt-loop.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-loop.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,35 +34,35 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // While. +// While. - tree_while_command::~tree_while_command (void) - { - delete m_expr; - delete m_list; - delete m_lead_comm; - delete m_trail_comm; - } +tree_while_command::~tree_while_command (void) +{ + delete m_expr; + delete m_list; + delete m_lead_comm; + delete m_trail_comm; +} - // For. +// For. - tree_simple_for_command::~tree_simple_for_command (void) - { - delete m_lhs; - delete m_expr; - delete m_maxproc; - delete m_list; - delete m_lead_comm; - delete m_trail_comm; - } +tree_simple_for_command::~tree_simple_for_command (void) +{ + delete m_lhs; + delete m_expr; + delete m_maxproc; + delete m_list; + delete m_lead_comm; + delete m_trail_comm; +} - tree_complex_for_command::~tree_complex_for_command (void) - { - delete m_lhs; - delete m_expr; - delete m_list; - delete m_lead_comm; - delete m_trail_comm; - } +tree_complex_for_command::~tree_complex_for_command (void) +{ + delete m_lhs; + delete m_expr; + delete m_list; + delete m_lead_comm; + delete m_trail_comm; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-loop.h --- a/libinterp/parse-tree/pt-loop.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-loop.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,245 +35,245 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_argument_list; - class tree_expression; - class tree_statement_list; +class tree_argument_list; +class tree_expression; +class tree_statement_list; - // While. +// While. + +class tree_while_command : public tree_command +{ +public: - class tree_while_command : public tree_command - { - public: + tree_while_command (int l = -1, int c = -1) + : tree_command (l, c), m_expr (nullptr), m_list (nullptr), + m_lead_comm (nullptr), m_trail_comm (nullptr) + { } - tree_while_command (int l = -1, int c = -1) - : tree_command (l, c), m_expr (nullptr), m_list (nullptr), - m_lead_comm (nullptr), m_trail_comm (nullptr) - { } + tree_while_command (tree_expression *e, + comment_list *lc = nullptr, + comment_list *tc = nullptr, + int l = -1, int c = -1) + : tree_command (l, c), m_expr (e), m_list (nullptr), + m_lead_comm (lc), m_trail_comm (tc) + { } - tree_while_command (tree_expression *e, - comment_list *lc = nullptr, - comment_list *tc = nullptr, - int l = -1, int c = -1) - : tree_command (l, c), m_expr (e), m_list (nullptr), - m_lead_comm (lc), m_trail_comm (tc) - { } + tree_while_command (tree_expression *e, tree_statement_list *lst, + comment_list *lc = nullptr, + comment_list *tc = nullptr, + int l = -1, int c = -1) + : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc), + m_trail_comm (tc) + { } + + // No copying! + + tree_while_command (const tree_while_command&) = delete; + + tree_while_command& operator = (const tree_while_command&) = delete; + + ~tree_while_command (void); + + tree_expression * condition (void) { return m_expr; } - tree_while_command (tree_expression *e, tree_statement_list *lst, - comment_list *lc = nullptr, - comment_list *tc = nullptr, - int l = -1, int c = -1) - : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc), - m_trail_comm (tc) - { } + tree_statement_list * body (void) { return m_list; } - // No copying! + comment_list * leading_comment (void) { return m_lead_comm; } + + comment_list * trailing_comment (void) { return m_trail_comm; } - tree_while_command (const tree_while_command&) = delete; - - tree_while_command& operator = (const tree_while_command&) = delete; + void accept (tree_walker& tw) + { + tw.visit_while_command (*this); + } - ~tree_while_command (void); +protected: - tree_expression * condition (void) { return m_expr; } + // Expression to test. + tree_expression *m_expr; - tree_statement_list * body (void) { return m_list; } + // List of commands to execute. + tree_statement_list *m_list; - comment_list * leading_comment (void) { return m_lead_comm; } - - comment_list * trailing_comment (void) { return m_trail_comm; } + // Comment preceding WHILE token. + comment_list *m_lead_comm; - void accept (tree_walker& tw) - { - tw.visit_while_command (*this); - } + // Comment preceding ENDWHILE token. + comment_list *m_trail_comm; +}; + +// Do-Until. + +class tree_do_until_command : public tree_while_command +{ +public: - protected: - - // Expression to test. - tree_expression *m_expr; + tree_do_until_command (int l = -1, int c = -1) + : tree_while_command (l, c) + { } - // List of commands to execute. - tree_statement_list *m_list; + tree_do_until_command (tree_expression *e, + comment_list *lc = nullptr, + comment_list *tc = nullptr, + int l = -1, int c = -1) + : tree_while_command (e, lc, tc, l, c) + { } - // Comment preceding WHILE token. - comment_list *m_lead_comm; + tree_do_until_command (tree_expression *e, tree_statement_list *lst, + comment_list *lc = nullptr, + comment_list *tc = nullptr, + int l = -1, int c = -1) + : tree_while_command (e, lst, lc, tc, l, c) + { } - // Comment preceding ENDWHILE token. - comment_list *m_trail_comm; - }; + // No copying! + + tree_do_until_command (const tree_do_until_command&) = delete; + + tree_do_until_command& operator = (const tree_do_until_command&) = delete; - // Do-Until. + ~tree_do_until_command (void) = default; - class tree_do_until_command : public tree_while_command + void accept (tree_walker& tw) { - public: + tw.visit_do_until_command (*this); + } +}; - tree_do_until_command (int l = -1, int c = -1) - : tree_while_command (l, c) - { } +// For. + +class tree_simple_for_command : public tree_command +{ +public: - tree_do_until_command (tree_expression *e, - comment_list *lc = nullptr, - comment_list *tc = nullptr, - int l = -1, int c = -1) - : tree_while_command (e, lc, tc, l, c) - { } + tree_simple_for_command (int l = -1, int c = -1) + : tree_command (l, c), m_parallel (false), m_lhs (nullptr), + m_expr (nullptr), m_maxproc (nullptr), m_list (nullptr), + m_lead_comm (nullptr), m_trail_comm (nullptr) + { } - tree_do_until_command (tree_expression *e, tree_statement_list *lst, + tree_simple_for_command (bool parallel_arg, tree_expression *le, + tree_expression *re, + tree_expression *maxproc_arg, + tree_statement_list *lst, comment_list *lc = nullptr, comment_list *tc = nullptr, int l = -1, int c = -1) - : tree_while_command (e, lst, lc, tc, l, c) - { } - - // No copying! + : tree_command (l, c), m_parallel (parallel_arg), m_lhs (le), + m_expr (re), m_maxproc (maxproc_arg), m_list (lst), + m_lead_comm (lc), m_trail_comm (tc) + { } - tree_do_until_command (const tree_do_until_command&) = delete; + // No copying! + + tree_simple_for_command (const tree_simple_for_command&) = delete; - tree_do_until_command& operator = (const tree_do_until_command&) = delete; + tree_simple_for_command& operator = (const tree_simple_for_command&) = delete; - ~tree_do_until_command (void) = default; + ~tree_simple_for_command (void); - void accept (tree_walker& tw) - { - tw.visit_do_until_command (*this); - } - }; + bool in_parallel (void) { return m_parallel; } - // For. + tree_expression * left_hand_side (void) { return m_lhs; } + + tree_expression * control_expr (void) { return m_expr; } - class tree_simple_for_command : public tree_command - { - public: + tree_expression * maxproc_expr (void) { return m_maxproc; } + + tree_statement_list * body (void) { return m_list; } - tree_simple_for_command (int l = -1, int c = -1) - : tree_command (l, c), m_parallel (false), m_lhs (nullptr), - m_expr (nullptr), m_maxproc (nullptr), m_list (nullptr), - m_lead_comm (nullptr), m_trail_comm (nullptr) - { } + comment_list * leading_comment (void) { return m_lead_comm; } + + comment_list * trailing_comment (void) { return m_trail_comm; } - tree_simple_for_command (bool parallel_arg, tree_expression *le, - tree_expression *re, - tree_expression *maxproc_arg, - tree_statement_list *lst, - comment_list *lc = nullptr, - comment_list *tc = nullptr, - int l = -1, int c = -1) - : tree_command (l, c), m_parallel (parallel_arg), m_lhs (le), - m_expr (re), m_maxproc (maxproc_arg), m_list (lst), - m_lead_comm (lc), m_trail_comm (tc) - { } + void accept (tree_walker& tw) + { + tw.visit_simple_for_command (*this); + } - // No copying! - - tree_simple_for_command (const tree_simple_for_command&) = delete; +private: + // TRUE means operate in parallel (subject to the value of the + // maxproc expression). + bool m_parallel; - tree_simple_for_command& operator = (const tree_simple_for_command&) = delete; - - ~tree_simple_for_command (void); - - bool in_parallel (void) { return m_parallel; } + // Expression to modify. + tree_expression *m_lhs; - tree_expression * left_hand_side (void) { return m_lhs; } - - tree_expression * control_expr (void) { return m_expr; } - - tree_expression * maxproc_expr (void) { return m_maxproc; } + // Expression to evaluate. + tree_expression *m_expr; - tree_statement_list * body (void) { return m_list; } - - comment_list * leading_comment (void) { return m_lead_comm; } - - comment_list * trailing_comment (void) { return m_trail_comm; } + // Expression to tell how many processors should be used (only valid + // if parallel is TRUE). + tree_expression *m_maxproc; - void accept (tree_walker& tw) - { - tw.visit_simple_for_command (*this); - } + // List of commands to execute. + tree_statement_list *m_list; - private: - // TRUE means operate in parallel (subject to the value of the - // maxproc expression). - bool m_parallel; + // Comment preceding FOR token. + comment_list *m_lead_comm; - // Expression to modify. - tree_expression *m_lhs; + // Comment preceding ENDFOR token. + comment_list *m_trail_comm; +}; - // Expression to evaluate. - tree_expression *m_expr; - - // Expression to tell how many processors should be used (only valid - // if parallel is TRUE). - tree_expression *m_maxproc; +class tree_complex_for_command : public tree_command +{ +public: - // List of commands to execute. - tree_statement_list *m_list; - - // Comment preceding FOR token. - comment_list *m_lead_comm; - - // Comment preceding ENDFOR token. - comment_list *m_trail_comm; - }; + tree_complex_for_command (int l = -1, int c = -1) + : tree_command (l, c), m_lhs (nullptr), m_expr (nullptr), + m_list (nullptr), m_lead_comm (nullptr), m_trail_comm (nullptr) + { } - class tree_complex_for_command : public tree_command - { - public: - - tree_complex_for_command (int l = -1, int c = -1) - : tree_command (l, c), m_lhs (nullptr), m_expr (nullptr), - m_list (nullptr), m_lead_comm (nullptr), m_trail_comm (nullptr) - { } + tree_complex_for_command (tree_argument_list *le, tree_expression *re, + tree_statement_list *lst, + comment_list *lc = nullptr, + comment_list *tc = nullptr, + int l = -1, int c = -1) + : tree_command (l, c), m_lhs (le), m_expr (re), m_list (lst), + m_lead_comm (lc), m_trail_comm (tc) + { } - tree_complex_for_command (tree_argument_list *le, tree_expression *re, - tree_statement_list *lst, - comment_list *lc = nullptr, - comment_list *tc = nullptr, - int l = -1, int c = -1) - : tree_command (l, c), m_lhs (le), m_expr (re), m_list (lst), - m_lead_comm (lc), m_trail_comm (tc) - { } + // No copying! + + tree_complex_for_command (const tree_complex_for_command&) = delete; - // No copying! + tree_complex_for_command& operator = (const tree_complex_for_command&) = delete; + + ~tree_complex_for_command (void); + + tree_argument_list * left_hand_side (void) { return m_lhs; } - tree_complex_for_command (const tree_complex_for_command&) = delete; - - tree_complex_for_command& operator = (const tree_complex_for_command&) = delete; + tree_expression * control_expr (void) { return m_expr; } - ~tree_complex_for_command (void); + tree_statement_list * body (void) { return m_list; } - tree_argument_list * left_hand_side (void) { return m_lhs; } + comment_list * leading_comment (void) { return m_lead_comm; } - tree_expression * control_expr (void) { return m_expr; } - - tree_statement_list * body (void) { return m_list; } + comment_list * trailing_comment (void) { return m_trail_comm; } - comment_list * leading_comment (void) { return m_lead_comm; } + void accept (tree_walker& tw) + { + tw.visit_complex_for_command (*this); + } - comment_list * trailing_comment (void) { return m_trail_comm; } +private: - void accept (tree_walker& tw) - { - tw.visit_complex_for_command (*this); - } + // Expression to modify. + tree_argument_list *m_lhs; - private: - - // Expression to modify. - tree_argument_list *m_lhs; + // Expression to evaluate. + tree_expression *m_expr; - // Expression to evaluate. - tree_expression *m_expr; - - // List of commands to execute. - tree_statement_list *m_list; + // List of commands to execute. + tree_statement_list *m_list; - // Comment preceding FOR token. - comment_list *m_lead_comm; + // Comment preceding FOR token. + comment_list *m_lead_comm; - // Comment preceding ENDFOR token. - comment_list *m_trail_comm; - }; + // Comment preceding ENDFOR token. + comment_list *m_trail_comm; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-mat.cc --- a/libinterp/parse-tree/pt-mat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-mat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,101 +44,101 @@ OCTAVE_BEGIN_NAMESPACE(octave) - octave_value - tree_matrix::evaluate (tree_evaluator& tw, int) - { - tm_const tmp (*this, tw); +octave_value +tree_matrix::evaluate (tree_evaluator& tw, int) +{ + tm_const tmp (*this, tw); - return tmp.concat (tw.string_fill_char ()); - } + return tmp.concat (tw.string_fill_char ()); +} - std::string - get_concat_class (const std::string& c1, const std::string& c2) - { - std::string retval = octave_base_value::static_class_name (); +std::string +get_concat_class (const std::string& c1, const std::string& c2) +{ + std::string retval = octave_base_value::static_class_name (); - if (c1 == c2) - retval = c1; - else if (c1.empty ()) - retval = c2; - else if (c2.empty ()) - retval = c1; - else if (c1 == "class" || c2 == "class") - retval = "class"; - else - { - bool c1_is_int = (c1 == "int8" || c1 == "uint8" - || c1 == "int16" || c1 == "uint16" - || c1 == "int32" || c1 == "uint32" - || c1 == "int64" || c1 == "uint64"); - bool c2_is_int = (c2 == "int8" || c2 == "uint8" - || c2 == "int16" || c2 == "uint16" - || c2 == "int32" || c2 == "uint32" - || c2 == "int64" || c2 == "uint64"); + if (c1 == c2) + retval = c1; + else if (c1.empty ()) + retval = c2; + else if (c2.empty ()) + retval = c1; + else if (c1 == "class" || c2 == "class") + retval = "class"; + else + { + bool c1_is_int = (c1 == "int8" || c1 == "uint8" + || c1 == "int16" || c1 == "uint16" + || c1 == "int32" || c1 == "uint32" + || c1 == "int64" || c1 == "uint64"); + bool c2_is_int = (c2 == "int8" || c2 == "uint8" + || c2 == "int16" || c2 == "uint16" + || c2 == "int32" || c2 == "uint32" + || c2 == "int64" || c2 == "uint64"); - bool c1_is_char = (c1 == "char"); - bool c2_is_char = (c2 == "char"); + bool c1_is_char = (c1 == "char"); + bool c2_is_char = (c2 == "char"); - bool c1_is_double = (c1 == "double"); - bool c2_is_double = (c2 == "double"); + bool c1_is_double = (c1 == "double"); + bool c2_is_double = (c2 == "double"); - bool c1_is_single = (c1 == "single"); - bool c2_is_single = (c2 == "single"); + bool c1_is_single = (c1 == "single"); + bool c2_is_single = (c2 == "single"); - bool c1_is_logical = (c1 == "logical"); - bool c2_is_logical = (c2 == "logical"); + bool c1_is_logical = (c1 == "logical"); + bool c2_is_logical = (c2 == "logical"); - bool c1_is_built_in_type - = (c1_is_int || c1_is_char || c1_is_double || c1_is_single - || c1_is_logical); + bool c1_is_built_in_type + = (c1_is_int || c1_is_char || c1_is_double || c1_is_single + || c1_is_logical); - bool c2_is_built_in_type - = (c2_is_int || c2_is_char || c2_is_double || c2_is_single - || c2_is_logical); + bool c2_is_built_in_type + = (c2_is_int || c2_is_char || c2_is_double || c2_is_single + || c2_is_logical); - // Order is important here... + // Order is important here... - if (c1 == "cell" || c2 == "cell") - retval = "cell"; - else if (c1_is_char && c2_is_built_in_type) - retval = c1; - else if (c2_is_char && c1_is_built_in_type) - retval = c2; - else if (c1_is_int && c2_is_built_in_type) - retval = c1; - else if (c2_is_int && c1_is_built_in_type) - retval = c2; - else if (c1_is_single && c2_is_built_in_type) - retval = c1; - else if (c2_is_single && c1_is_built_in_type) - retval = c2; - else if (c1_is_double && c2_is_built_in_type) - retval = c1; - else if (c2_is_double && c1_is_built_in_type) - retval = c2; - else if (c1_is_logical && c2_is_logical) - retval = c1; - } + if (c1 == "cell" || c2 == "cell") + retval = "cell"; + else if (c1_is_char && c2_is_built_in_type) + retval = c1; + else if (c2_is_char && c1_is_built_in_type) + retval = c2; + else if (c1_is_int && c2_is_built_in_type) + retval = c1; + else if (c2_is_int && c1_is_built_in_type) + retval = c2; + else if (c1_is_single && c2_is_built_in_type) + retval = c1; + else if (c2_is_single && c1_is_built_in_type) + retval = c2; + else if (c1_is_double && c2_is_built_in_type) + retval = c1; + else if (c2_is_double && c1_is_built_in_type) + retval = c2; + else if (c1_is_logical && c2_is_logical) + retval = c1; + } - return retval; - } + return retval; +} - void - maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p) - { - if (! (all_dq_strings_p || all_sq_strings_p)) - warning_with_id ("Octave:mixed-string-concat", - "concatenation of different character string types may have unintended consequences"); - } +void +maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p) +{ + if (! (all_dq_strings_p || all_sq_strings_p)) + warning_with_id ("Octave:mixed-string-concat", + "concatenation of different character string types may have unintended consequences"); +} - tree_expression * - tree_matrix::dup (symbol_scope& scope) const - { - tree_matrix *new_matrix = new tree_matrix (nullptr, line (), column ()); +tree_expression * +tree_matrix::dup (symbol_scope& scope) const +{ + tree_matrix *new_matrix = new tree_matrix (nullptr, line (), column ()); - new_matrix->copy_base (*this, scope); + new_matrix->copy_base (*this, scope); - return new_matrix; - } + return new_matrix; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-mat.h --- a/libinterp/parse-tree/pt-mat.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-mat.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,52 +40,52 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_argument_list; +class symbol_scope; +class tree_argument_list; - // General matrices. This allows us to construct matrices from - // other matrices, variables, and functions. +// General matrices. This allows us to construct matrices from +// other matrices, variables, and functions. - class tree_matrix : public tree_array_list - { - public: +class tree_matrix : public tree_array_list +{ +public: - tree_matrix (tree_argument_list *row = nullptr, int l = -1, int c = -1) - : tree_array_list (row, l, c) - { } + tree_matrix (tree_argument_list *row = nullptr, int l = -1, int c = -1) + : tree_array_list (row, l, c) + { } - // No copying! + // No copying! - tree_matrix (const tree_matrix&) = delete; + tree_matrix (const tree_matrix&) = delete; - tree_matrix& operator = (const tree_matrix&) = delete; + tree_matrix& operator = (const tree_matrix&) = delete; - ~tree_matrix (void) = default; + ~tree_matrix (void) = default; - bool is_matrix (void) const { return true; } + bool is_matrix (void) const { return true; } - bool rvalue_ok (void) const { return true; } + bool rvalue_ok (void) const { return true; } - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator&, int nargout = 1); + octave_value evaluate (tree_evaluator&, int nargout = 1); - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) + { + return ovl (evaluate (tw, nargout)); + } - void accept (tree_walker& tw) - { - tw.visit_matrix (*this); - } - }; + void accept (tree_walker& tw) + { + tw.visit_matrix (*this); + } +}; - extern std::string - get_concat_class (const std::string& c1, const std::string& c2); +extern std::string +get_concat_class (const std::string& c1, const std::string& c2); - extern void - maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p); +extern void +maybe_warn_string_concat (bool all_dq_strings_p, bool all_sq_strings_p); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-misc.cc --- a/libinterp/parse-tree/pt-misc.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-misc.cc Thu Dec 01 20:05:44 2022 -0800 @@ -32,50 +32,50 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Parameter lists. +// Parameter lists. - tree_parameter_list::~tree_parameter_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } +tree_parameter_list::~tree_parameter_list (void) +{ + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } +} - void - tree_parameter_list::mark_as_formal_parameters (void) - { - for (tree_decl_elt *elt : *this) - elt->mark_as_formal_parameter (); - } +void +tree_parameter_list::mark_as_formal_parameters (void) +{ + for (tree_decl_elt *elt : *this) + elt->mark_as_formal_parameter (); +} - std::list - tree_parameter_list::variable_names (void) const - { - std::list retval; +std::list +tree_parameter_list::variable_names (void) const +{ + std::list retval; - for (tree_decl_elt *elt : *this) - retval.push_back (elt->name ()); + for (tree_decl_elt *elt : *this) + retval.push_back (elt->name ()); - if (m_marked_for_varargs) - retval.push_back (varargs_symbol_name ()); + if (m_marked_for_varargs) + retval.push_back (varargs_symbol_name ()); - return retval; - } + return retval; +} - tree_parameter_list * - tree_parameter_list::dup (symbol_scope& scope) const - { - tree_parameter_list *new_list = new tree_parameter_list (m_in_or_out); +tree_parameter_list * +tree_parameter_list::dup (symbol_scope& scope) const +{ + tree_parameter_list *new_list = new tree_parameter_list (m_in_or_out); - new_list->m_marked_for_varargs = m_marked_for_varargs; + new_list->m_marked_for_varargs = m_marked_for_varargs; - for (const tree_decl_elt *elt : *this) - new_list->append (elt->dup (scope)); + for (const tree_decl_elt *elt : *this) + new_list->append (elt->dup (scope)); - return new_list; - } + return new_list; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-misc.h --- a/libinterp/parse-tree/pt-misc.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-misc.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,85 +34,85 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; - class tree_identifier; - class tree_index_expression; +class symbol_scope; +class tree_identifier; +class tree_index_expression; - // Parameter lists. Used to hold the list of input and output - // parameters in a function definition. Elements are identifiers - // only. +// Parameter lists. Used to hold the list of input and output +// parameters in a function definition. Elements are identifiers +// only. - class tree_parameter_list : public base_list - { - public: +class tree_parameter_list : public base_list +{ +public: - enum in_or_out - { - in = 1, - out = 2 - }; + enum in_or_out + { + in = 1, + out = 2 + }; - tree_parameter_list (in_or_out io) - : m_in_or_out (io), m_marked_for_varargs (0) - { } + tree_parameter_list (in_or_out io) + : m_in_or_out (io), m_marked_for_varargs (0) + { } - tree_parameter_list (in_or_out io, tree_decl_elt *t) - : m_in_or_out (io), m_marked_for_varargs (0) - { - append (t); - } + tree_parameter_list (in_or_out io, tree_decl_elt *t) + : m_in_or_out (io), m_marked_for_varargs (0) + { + append (t); + } - tree_parameter_list (in_or_out io, tree_identifier *id) - : m_in_or_out (io), m_marked_for_varargs (0) - { - append (new tree_decl_elt (id)); - } + tree_parameter_list (in_or_out io, tree_identifier *id) + : m_in_or_out (io), m_marked_for_varargs (0) + { + append (new tree_decl_elt (id)); + } - // No copying! + // No copying! - tree_parameter_list (const tree_parameter_list&) = delete; + tree_parameter_list (const tree_parameter_list&) = delete; - tree_parameter_list& operator = (const tree_parameter_list&) = delete; + tree_parameter_list& operator = (const tree_parameter_list&) = delete; - ~tree_parameter_list (void); + ~tree_parameter_list (void); - void mark_as_formal_parameters (void); + void mark_as_formal_parameters (void); - void mark_varargs (void) { m_marked_for_varargs = 1; } + void mark_varargs (void) { m_marked_for_varargs = 1; } - void mark_varargs_only (void) { m_marked_for_varargs = -1; } + void mark_varargs_only (void) { m_marked_for_varargs = -1; } - bool takes_varargs (void) const { return m_marked_for_varargs != 0; } + bool takes_varargs (void) const { return m_marked_for_varargs != 0; } - bool varargs_only (void) { return (m_marked_for_varargs < 0); } + bool varargs_only (void) { return (m_marked_for_varargs < 0); } - bool is_input_list (void) const { return m_in_or_out == in; } + bool is_input_list (void) const { return m_in_or_out == in; } - bool is_output_list (void) const { return m_in_or_out == out; } + bool is_output_list (void) const { return m_in_or_out == out; } - std::list variable_names (void) const; + std::list variable_names (void) const; - std::string varargs_symbol_name (void) const - { - return m_in_or_out == in ? "varargin" : "varargout"; - } + std::string varargs_symbol_name (void) const + { + return m_in_or_out == in ? "varargin" : "varargout"; + } - tree_parameter_list * dup (symbol_scope& scope) const; + tree_parameter_list * dup (symbol_scope& scope) const; - void accept (tree_walker& tw) - { - tw.visit_parameter_list (*this); - } + void accept (tree_walker& tw) + { + tw.visit_parameter_list (*this); + } - private: +private: - in_or_out m_in_or_out; + in_or_out m_in_or_out; - // 1: takes varargs - // -1: takes varargs only - // 0: does not take varargs. - int m_marked_for_varargs; - }; + // 1: takes varargs + // -1: takes varargs only + // 0: does not take varargs. + int m_marked_for_varargs; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-pr-code.cc --- a/libinterp/parse-tree/pt-pr-code.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-pr-code.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,1309 +37,1309 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - tree_print_code::visit_anon_fcn_handle (tree_anon_fcn_handle& afh) - { - indent (); +void +tree_print_code::visit_anon_fcn_handle (tree_anon_fcn_handle& afh) +{ + indent (); - print_parens (afh, "("); + print_parens (afh, "("); - m_os << "@"; + m_os << "@"; - tree_parameter_list *param_list = afh.parameter_list (); + tree_parameter_list *param_list = afh.parameter_list (); - if (param_list) - param_list->accept (*this); + if (param_list) + param_list->accept (*this); - print_fcn_handle_body (afh.expression ()); + print_fcn_handle_body (afh.expression ()); - print_parens (afh, ")"); - } + print_parens (afh, ")"); +} - void - tree_print_code::visit_argument_list (tree_argument_list& lst) - { - auto p = lst.begin (); +void +tree_print_code::visit_argument_list (tree_argument_list& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_expression *elt = *p++; + while (p != lst.end ()) + { + tree_expression *elt = *p++; - if (elt) - { - elt->accept (*this); + if (elt) + { + elt->accept (*this); - if (p != lst.end ()) - m_os << ", "; - } - } - } + if (p != lst.end ()) + m_os << ", "; + } + } +} - void - tree_print_code::visit_arguments_block (tree_arguments_block&) - { - indent (); +void +tree_print_code::visit_arguments_block (tree_arguments_block&) +{ + indent (); - // FIXME - m_os << "arguments ... endarguments"; - } + // FIXME + m_os << "arguments ... endarguments"; +} - void - tree_print_code::visit_args_block_attribute_list (tree_args_block_attribute_list&) - { - panic_impossible (); - } +void +tree_print_code::visit_args_block_attribute_list (tree_args_block_attribute_list&) +{ + panic_impossible (); +} - void - tree_print_code::visit_args_block_validation_list (tree_args_block_validation_list&) - { - panic_impossible (); - } +void +tree_print_code::visit_args_block_validation_list (tree_args_block_validation_list&) +{ + panic_impossible (); +} - void - tree_print_code::visit_arg_validation (tree_arg_validation&) - { - panic_impossible (); - } +void +tree_print_code::visit_arg_validation (tree_arg_validation&) +{ + panic_impossible (); +} - void - tree_print_code::visit_arg_size_spec (tree_arg_size_spec&) - { - panic_impossible (); - } +void +tree_print_code::visit_arg_size_spec (tree_arg_size_spec&) +{ + panic_impossible (); +} - void - tree_print_code::visit_arg_validation_fcns (tree_arg_validation_fcns&) - { - panic_impossible (); - } - - void - tree_print_code::visit_binary_expression (tree_binary_expression& expr) - { - indent (); +void +tree_print_code::visit_arg_validation_fcns (tree_arg_validation_fcns&) +{ + panic_impossible (); +} - print_parens (expr, "("); +void +tree_print_code::visit_binary_expression (tree_binary_expression& expr) +{ + indent (); - tree_expression *op1 = expr.lhs (); - - if (op1) - op1->accept (*this); + print_parens (expr, "("); - m_os << ' ' << expr.oper () << ' '; + tree_expression *op1 = expr.lhs (); - tree_expression *op2 = expr.rhs (); + if (op1) + op1->accept (*this); - if (op2) - op2->accept (*this); + m_os << ' ' << expr.oper () << ' '; - print_parens (expr, ")"); - } + tree_expression *op2 = expr.rhs (); - void - tree_print_code::visit_break_command (tree_break_command&) - { - indent (); + if (op2) + op2->accept (*this); + + print_parens (expr, ")"); +} - m_os << "break"; - } +void +tree_print_code::visit_break_command (tree_break_command&) +{ + indent (); - void - tree_print_code::visit_colon_expression (tree_colon_expression& expr) - { - indent (); + m_os << "break"; +} - print_parens (expr, "("); - - tree_expression *op1 = expr.base (); +void +tree_print_code::visit_colon_expression (tree_colon_expression& expr) +{ + indent (); - if (op1) - op1->accept (*this); + print_parens (expr, "("); - // Stupid syntax. + tree_expression *op1 = expr.base (); - tree_expression *op3 = expr.increment (); + if (op1) + op1->accept (*this); - if (op3) - { - m_os << ':'; - op3->accept (*this); - } + // Stupid syntax. + + tree_expression *op3 = expr.increment (); - tree_expression *op2 = expr.limit (); + if (op3) + { + m_os << ':'; + op3->accept (*this); + } - if (op2) - { - m_os << ':'; - op2->accept (*this); - } + tree_expression *op2 = expr.limit (); - print_parens (expr, ")"); - } + if (op2) + { + m_os << ':'; + op2->accept (*this); + } - void - tree_print_code::visit_continue_command (tree_continue_command&) - { - indent (); + print_parens (expr, ")"); +} - m_os << "continue"; - } +void +tree_print_code::visit_continue_command (tree_continue_command&) +{ + indent (); - void - tree_print_code::visit_decl_command (tree_decl_command& cmd) - { - indent (); + m_os << "continue"; +} - m_os << cmd.name () << ' '; - - tree_decl_init_list *init_list = cmd.initializer_list (); +void +tree_print_code::visit_decl_command (tree_decl_command& cmd) +{ + indent (); - if (init_list) - init_list->accept (*this); - } + m_os << cmd.name () << ' '; + + tree_decl_init_list *init_list = cmd.initializer_list (); - void - tree_print_code::visit_decl_init_list (tree_decl_init_list& lst) - { - auto p = lst.begin (); + if (init_list) + init_list->accept (*this); +} - while (p != lst.end ()) - { - tree_decl_elt *elt = *p++; +void +tree_print_code::visit_decl_init_list (tree_decl_init_list& lst) +{ + auto p = lst.begin (); - if (elt) - { - elt->accept (*this); + while (p != lst.end ()) + { + tree_decl_elt *elt = *p++; - if (p != lst.end ()) - m_os << ", "; - } - } - } + if (elt) + { + elt->accept (*this); - void - tree_print_code::visit_decl_elt (tree_decl_elt& cmd) - { - tree_identifier *id = cmd.ident (); + if (p != lst.end ()) + m_os << ", "; + } + } +} - if (id) - id->accept (*this); +void +tree_print_code::visit_decl_elt (tree_decl_elt& cmd) +{ + tree_identifier *id = cmd.ident (); - tree_expression *expr = cmd.expression (); + if (id) + id->accept (*this); - if (expr) - { - m_os << " = "; + tree_expression *expr = cmd.expression (); - expr->accept (*this); - } - } + if (expr) + { + m_os << " = "; - void - tree_print_code::visit_simple_for_command (tree_simple_for_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + expr->accept (*this); + } +} - indent (); - - m_os << (cmd.in_parallel () ? "parfor " : "for "); - - tree_expression *lhs = cmd.left_hand_side (); +void +tree_print_code::visit_simple_for_command (tree_simple_for_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); - tree_expression *maxproc = cmd.maxproc_expr (); + indent (); + + m_os << (cmd.in_parallel () ? "parfor " : "for "); - if (maxproc) - m_os << '('; + tree_expression *lhs = cmd.left_hand_side (); + + tree_expression *maxproc = cmd.maxproc_expr (); - if (lhs) - lhs->accept (*this); - - m_os << " = "; + if (maxproc) + m_os << '('; - tree_expression *expr = cmd.control_expr (); + if (lhs) + lhs->accept (*this); - if (expr) - expr->accept (*this); + m_os << " = "; - if (maxproc) - { - m_os << ", "; - maxproc->accept (*this); - m_os << ')'; - } + tree_expression *expr = cmd.control_expr (); + + if (expr) + expr->accept (*this); - newline (); - - tree_statement_list *list = cmd.body (); + if (maxproc) + { + m_os << ", "; + maxproc->accept (*this); + m_os << ')'; + } - if (list) - { - increment_indent_level (); + newline (); - list->accept (*this); + tree_statement_list *list = cmd.body (); - decrement_indent_level (); - } - - print_indented_comment (cmd.trailing_comment ()); + if (list) + { + increment_indent_level (); - indent (); + list->accept (*this); - m_os << (cmd.in_parallel () ? "endparfor" : "endfor"); - } + decrement_indent_level (); + } + + print_indented_comment (cmd.trailing_comment ()); - void - tree_print_code::visit_complex_for_command (tree_complex_for_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + indent (); - indent (); + m_os << (cmd.in_parallel () ? "endparfor" : "endfor"); +} - m_os << "for ["; - m_nesting.push ('['); +void +tree_print_code::visit_complex_for_command (tree_complex_for_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); - tree_argument_list *lhs = cmd.left_hand_side (); - - if (lhs) - lhs->accept (*this); + indent (); - m_nesting.pop (); - m_os << "] = "; + m_os << "for ["; + m_nesting.push ('['); - tree_expression *expr = cmd.control_expr (); + tree_argument_list *lhs = cmd.left_hand_side (); - if (expr) - expr->accept (*this); + if (lhs) + lhs->accept (*this); - newline (); - - tree_statement_list *list = cmd.body (); + m_nesting.pop (); + m_os << "] = "; - if (list) - { - increment_indent_level (); + tree_expression *expr = cmd.control_expr (); + + if (expr) + expr->accept (*this); - list->accept (*this); + newline (); - decrement_indent_level (); - } + tree_statement_list *list = cmd.body (); - print_indented_comment (cmd.trailing_comment ()); + if (list) + { + increment_indent_level (); - indent (); + list->accept (*this); - m_os << "endfor"; - } + decrement_indent_level (); + } - void - tree_print_code::visit_spmd_command (tree_spmd_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + print_indented_comment (cmd.trailing_comment ()); - indent (); + indent (); + + m_os << "endfor"; +} - m_os << "spmd"; - - newline (); +void +tree_print_code::visit_spmd_command (tree_spmd_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); - tree_statement_list *list = cmd.body (); - - if (list) - { - increment_indent_level (); + indent (); - list->accept (*this); + m_os << "spmd"; - decrement_indent_level (); - } + newline (); + + tree_statement_list *list = cmd.body (); - print_indented_comment (cmd.trailing_comment ()); + if (list) + { + increment_indent_level (); - indent (); - - m_os << "endspmd"; - } + list->accept (*this); - void - tree_print_code::visit_octave_user_script (octave_user_script& fcn) - { - reset (); + decrement_indent_level (); + } - tree_statement_list *cmd_list = fcn.body (); + print_indented_comment (cmd.trailing_comment ()); + + indent (); - if (cmd_list) - cmd_list->accept (*this); - } + m_os << "endspmd"; +} - void - tree_print_code::visit_octave_user_function (octave_user_function& fcn) - { - reset (); +void +tree_print_code::visit_octave_user_script (octave_user_script& fcn) +{ + reset (); - visit_octave_user_function_header (fcn); + tree_statement_list *cmd_list = fcn.body (); - tree_statement_list *cmd_list = fcn.body (); + if (cmd_list) + cmd_list->accept (*this); +} - if (cmd_list) - { - increment_indent_level (); +void +tree_print_code::visit_octave_user_function (octave_user_function& fcn) +{ + reset (); - cmd_list->accept (*this); - - // endfunction will decrement the indent level. - } + visit_octave_user_function_header (fcn); - visit_octave_user_function_trailer (fcn); - } + tree_statement_list *cmd_list = fcn.body (); - void - tree_print_code::visit_octave_user_function_header (octave_user_function& fcn) - { - comment_list *leading_comment = fcn.leading_comment (); + if (cmd_list) + { + increment_indent_level (); - if (leading_comment) - { - print_comment_list (leading_comment); - newline (); - } + cmd_list->accept (*this); - indent (); + // endfunction will decrement the indent level. + } + + visit_octave_user_function_trailer (fcn); +} - m_os << "function "; - - tree_parameter_list *ret_list = fcn.return_list (); +void +tree_print_code::visit_octave_user_function_header (octave_user_function& fcn) +{ + comment_list *leading_comment = fcn.leading_comment (); - if (ret_list) - { - ret_list->accept (*this); + if (leading_comment) + { + print_comment_list (leading_comment); + newline (); + } - m_os << " = "; - } - std::string fcn_name = fcn.name (); - - m_os << (fcn_name.empty () ? "(empty)" : fcn_name) << ' '; + indent (); - tree_parameter_list *param_list = fcn.parameter_list (); + m_os << "function "; + + tree_parameter_list *ret_list = fcn.return_list (); - if (param_list) - param_list->accept (*this); - - newline (); - } + if (ret_list) + { + ret_list->accept (*this); - void - tree_print_code::visit_octave_user_function_trailer (octave_user_function& fcn) - { - print_indented_comment (fcn.trailing_comment ()); + m_os << " = "; + } + std::string fcn_name = fcn.name (); - newline (); - } + m_os << (fcn_name.empty () ? "(empty)" : fcn_name) << ' '; + + tree_parameter_list *param_list = fcn.parameter_list (); - void - tree_print_code::visit_function_def (tree_function_def& fdef) - { - indent (); + if (param_list) + param_list->accept (*this); - octave_value fcn = fdef.function (); - - octave_function *f = fcn.function_value (); + newline (); +} - if (f) - f->accept (*this); - } +void +tree_print_code::visit_octave_user_function_trailer (octave_user_function& fcn) +{ + print_indented_comment (fcn.trailing_comment ()); - void - tree_print_code::visit_identifier (tree_identifier& id) - { - indent (); + newline (); +} + +void +tree_print_code::visit_function_def (tree_function_def& fdef) +{ + indent (); - print_parens (id, "("); + octave_value fcn = fdef.function (); + + octave_function *f = fcn.function_value (); - std::string nm = id.name (); - m_os << (nm.empty () ? "(empty)" : nm); - - print_parens (id, ")"); - } + if (f) + f->accept (*this); +} - void - tree_print_code::visit_if_clause (tree_if_clause& cmd) - { - tree_expression *expr = cmd.condition (); - - if (expr) - expr->accept (*this); +void +tree_print_code::visit_identifier (tree_identifier& id) +{ + indent (); - newline (); - - tree_statement_list *list = cmd.commands (); + print_parens (id, "("); - if (list) - { - increment_indent_level (); + std::string nm = id.name (); + m_os << (nm.empty () ? "(empty)" : nm); + + print_parens (id, ")"); +} - list->accept (*this); +void +tree_print_code::visit_if_clause (tree_if_clause& cmd) +{ + tree_expression *expr = cmd.condition (); - decrement_indent_level (); - } - } + if (expr) + expr->accept (*this); - void - tree_print_code::visit_if_command (tree_if_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + newline (); + + tree_statement_list *list = cmd.commands (); - indent (); - - m_os << "if "; + if (list) + { + increment_indent_level (); - tree_if_command_list *list = cmd.cmd_list (); - - if (list) list->accept (*this); - print_indented_comment (cmd.trailing_comment ()); - - indent (); - - m_os << "endif"; - } - - void - tree_print_code::visit_if_command_list (tree_if_command_list& lst) - { - auto p = lst.begin (); - - bool first_elt = true; - - while (p != lst.end ()) - { - tree_if_clause *elt = *p++; - - if (elt) - { - if (! first_elt) - { - print_indented_comment (elt->leading_comment ()); + decrement_indent_level (); + } +} - indent (); - - if (elt->is_else_clause ()) - m_os << "else"; - else - m_os << "elseif "; - } - - elt->accept (*this); - } +void +tree_print_code::visit_if_command (tree_if_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); - first_elt = false; - } - } + indent (); - void - tree_print_code::visit_index_expression (tree_index_expression& expr) - { - indent (); + m_os << "if "; - print_parens (expr, "("); - - tree_expression *e = expr.expression (); - - if (e) - e->accept (*this); + tree_if_command_list *list = cmd.cmd_list (); - std::list arg_lists = expr.arg_lists (); - std::string type_tags = expr.type_tags (); - std::list arg_names = expr.arg_names (); - std::list dyn_fields = expr.dyn_fields (); - - int n = type_tags.length (); - - auto p_arg_lists = arg_lists.begin (); - auto p_arg_names = arg_names.begin (); - auto p_dyn_fields = dyn_fields.begin (); + if (list) + list->accept (*this); - for (int i = 0; i < n; i++) - { - switch (type_tags[i]) - { - case '(': - { - char nc = m_nesting.top (); - if ((nc == '[' || nc == '{') && expr.paren_count () == 0) - m_os << '('; - else - m_os << " ("; - m_nesting.push ('('); + print_indented_comment (cmd.trailing_comment ()); + + indent (); - tree_argument_list *l = *p_arg_lists; - if (l) - l->accept (*this); - - m_nesting.pop (); - m_os << ')'; - } - break; + m_os << "endif"; +} - case '{': - { - char nc = m_nesting.top (); - if ((nc == '[' || nc == '{') && expr.paren_count () == 0) - m_os << '{'; - else - m_os << " {"; - // We only care about whitespace inside [] and {} when we - // are defining matrix and cell objects, not when indexing. - m_nesting.push ('('); +void +tree_print_code::visit_if_command_list (tree_if_command_list& lst) +{ + auto p = lst.begin (); - tree_argument_list *l = *p_arg_lists; - if (l) - l->accept (*this); - - m_nesting.pop (); - m_os << '}'; - } - break; + bool first_elt = true; - case '.': - { - std::string fn = (*p_arg_names)(0); - if (fn.empty ()) - { - tree_expression *df = *p_dyn_fields; - - if (df) - { - m_nesting.push ('('); - m_os << ".("; - df->accept (*this); - m_os << ")"; - m_nesting.pop (); - } - } - else - m_os << '.' << fn; - } - break; + while (p != lst.end ()) + { + tree_if_clause *elt = *p++; - default: - panic_impossible (); - } - - p_arg_lists++; - p_arg_names++; - p_dyn_fields++; - } - - print_parens (expr, ")"); - } + if (elt) + { + if (! first_elt) + { + print_indented_comment (elt->leading_comment ()); - void - tree_print_code::visit_matrix (tree_matrix& lst) - { - indent (); - - print_parens (lst, "("); + indent (); - m_os << '['; - m_nesting.push ('['); - - auto p = lst.begin (); - - while (p != lst.end ()) - { - tree_argument_list *elt = *p++; + if (elt->is_else_clause ()) + m_os << "else"; + else + m_os << "elseif "; + } - if (elt) - { - elt->accept (*this); - - if (p != lst.end ()) - m_os << "; "; - } - } - - m_nesting.pop (); - m_os << ']'; + elt->accept (*this); + } - print_parens (lst, ")"); - } - - void - tree_print_code::visit_cell (tree_cell& lst) - { - indent (); - - print_parens (lst, "("); - - m_os << '{'; - m_nesting.push ('{'); - - auto p = lst.begin (); + first_elt = false; + } +} - while (p != lst.end ()) - { - tree_argument_list *elt = *p++; - - if (elt) - { - elt->accept (*this); - - if (p != lst.end ()) - m_os << "; "; - } - } +void +tree_print_code::visit_index_expression (tree_index_expression& expr) +{ + indent (); - m_nesting.pop (); - m_os << '}'; - - print_parens (lst, ")"); - } + print_parens (expr, "("); - void - tree_print_code::visit_multi_assignment (tree_multi_assignment& expr) - { - indent (); + tree_expression *e = expr.expression (); - print_parens (expr, "("); - - tree_argument_list *lhs = expr.left_hand_side (); + if (e) + e->accept (*this); - if (lhs) - { - int len = lhs->length (); - - if (len > 1) - { - m_os << '['; - m_nesting.push ('['); - } - - lhs->accept (*this); - - if (len > 1) - { - m_nesting.pop (); - m_os << ']'; - } - } - - m_os << ' ' << expr.oper () << ' '; - - tree_expression *rhs = expr.right_hand_side (); - - if (rhs) - rhs->accept (*this); + std::list arg_lists = expr.arg_lists (); + std::string type_tags = expr.type_tags (); + std::list arg_names = expr.arg_names (); + std::list dyn_fields = expr.dyn_fields (); - print_parens (expr, ")"); - } - - void - tree_print_code::visit_no_op_command (tree_no_op_command& cmd) - { - if (cmd.is_end_of_fcn_or_script () && m_curr_print_indent_level > 1) - decrement_indent_level (); - - indent (); + int n = type_tags.length (); - m_os << cmd.original_command (); - } - - void - tree_print_code::visit_constant (tree_constant& val) - { - indent (); - - print_parens (val, "("); - - val.print_raw (m_os, true, m_print_original_text); - - print_parens (val, ")"); - } + auto p_arg_lists = arg_lists.begin (); + auto p_arg_names = arg_names.begin (); + auto p_dyn_fields = dyn_fields.begin (); - void - tree_print_code::visit_fcn_handle (tree_fcn_handle& fh) - { - indent (); - - print_parens (fh, "("); - - fh.print_raw (m_os, true, m_print_original_text); - - print_parens (fh, ")"); - } - - void - tree_print_code::visit_parameter_list (tree_parameter_list& lst) - { - bool is_input_list = lst.is_input_list (); + for (int i = 0; i < n; i++) + { + switch (type_tags[i]) + { + case '(': + { + char nc = m_nesting.top (); + if ((nc == '[' || nc == '{') && expr.paren_count () == 0) + m_os << '('; + else + m_os << " ("; + m_nesting.push ('('); - if (is_input_list) - { - m_os << '('; - m_nesting.push ('('); - } - else - { - int len = lst.length (); - if (lst.takes_varargs ()) - len++; - - if (len != 1) - { - m_os << '['; - m_nesting.push ('['); - } - } + tree_argument_list *l = *p_arg_lists; + if (l) + l->accept (*this); - auto p = lst.begin (); - - while (p != lst.end ()) - { - tree_decl_elt *elt = *p++; - - if (elt) - { - elt->accept (*this); - - if (p != lst.end () || lst.takes_varargs ()) - m_os << ", "; + m_nesting.pop (); + m_os << ')'; } - } - - if (lst.takes_varargs ()) - m_os << lst.varargs_symbol_name (); + break; - if (is_input_list) - { - m_nesting.pop (); - m_os << ')'; - } - else - { - int len = lst.length (); - if (lst.takes_varargs ()) - len++; - - if (len != 1) + case '{': { - m_nesting.pop (); - m_os << ']'; - } - } - } - - void - tree_print_code::visit_postfix_expression (tree_postfix_expression& expr) - { - indent (); - - print_parens (expr, "("); + char nc = m_nesting.top (); + if ((nc == '[' || nc == '{') && expr.paren_count () == 0) + m_os << '{'; + else + m_os << " {"; + // We only care about whitespace inside [] and {} when we + // are defining matrix and cell objects, not when indexing. + m_nesting.push ('('); - tree_expression *e = expr.operand (); - - if (e) - e->accept (*this); - - m_os << expr.oper (); - - print_parens (expr, ")"); - } - - void - tree_print_code::visit_prefix_expression (tree_prefix_expression& expr) - { - indent (); - - print_parens (expr, "("); - - m_os << expr.oper (); - - tree_expression *e = expr.operand (); - - if (e) - e->accept (*this); - - print_parens (expr, ")"); - } + tree_argument_list *l = *p_arg_lists; + if (l) + l->accept (*this); - void - tree_print_code::visit_return_command (tree_return_command&) - { - indent (); - - m_os << "return"; - } - - void - tree_print_code::visit_simple_assignment (tree_simple_assignment& expr) - { - indent (); - - print_parens (expr, "("); - - tree_expression *lhs = expr.left_hand_side (); - - if (lhs) - lhs->accept (*this); - - m_os << ' ' << expr.oper () << ' '; - - tree_expression *rhs = expr.right_hand_side (); - - if (rhs) - rhs->accept (*this); + m_nesting.pop (); + m_os << '}'; + } + break; - print_parens (expr, ")"); - } - - void - tree_print_code::visit_statement (tree_statement& stmt) - { - print_comment_list (stmt.comment_text ()); - - tree_command *cmd = stmt.command (); - - if (cmd) - { - cmd->accept (*this); + case '.': + { + std::string fn = (*p_arg_names)(0); + if (fn.empty ()) + { + tree_expression *df = *p_dyn_fields; - newline (); - } - else - { - tree_expression *expr = stmt.expression (); - - if (expr) - { - expr->accept (*this); - - if (! stmt.print_result ()) - { - m_os << ';'; - newline (" "); + if (df) + { + m_nesting.push ('('); + m_os << ".("; + df->accept (*this); + m_os << ")"; + m_nesting.pop (); + } } else - newline (); + m_os << '.' << fn; } - } - } + break; + + default: + panic_impossible (); + } + + p_arg_lists++; + p_arg_names++; + p_dyn_fields++; + } + + print_parens (expr, ")"); +} - void - tree_print_code::visit_statement_list (tree_statement_list& lst) - { - for (tree_statement *elt : lst) - { - if (elt) +void +tree_print_code::visit_matrix (tree_matrix& lst) +{ + indent (); + + print_parens (lst, "("); + + m_os << '['; + m_nesting.push ('['); + + auto p = lst.begin (); + + while (p != lst.end ()) + { + tree_argument_list *elt = *p++; + + if (elt) + { elt->accept (*this); - } - } - void - tree_print_code::visit_switch_case (tree_switch_case& cs) - { - print_comment_list (cs.leading_comment ()); - - indent (); + if (p != lst.end ()) + m_os << "; "; + } + } - if (cs.is_default_case ()) - m_os << "otherwise"; - else - m_os << "case "; + m_nesting.pop (); + m_os << ']'; + + print_parens (lst, ")"); +} + +void +tree_print_code::visit_cell (tree_cell& lst) +{ + indent (); - tree_expression *label = cs.case_label (); + print_parens (lst, "("); + + m_os << '{'; + m_nesting.push ('{'); - if (label) - label->accept (*this); + auto p = lst.begin (); - newline (); + while (p != lst.end ()) + { + tree_argument_list *elt = *p++; - tree_statement_list *list = cs.commands (); + if (elt) + { + elt->accept (*this); - if (list) - { - increment_indent_level (); + if (p != lst.end ()) + m_os << "; "; + } + } + + m_nesting.pop (); + m_os << '}'; - list->accept (*this); - - newline (); + print_parens (lst, ")"); +} - decrement_indent_level (); - } - } +void +tree_print_code::visit_multi_assignment (tree_multi_assignment& expr) +{ + indent (); + + print_parens (expr, "("); + + tree_argument_list *lhs = expr.left_hand_side (); - void - tree_print_code::visit_switch_command (tree_switch_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + if (lhs) + { + int len = lhs->length (); + + if (len > 1) + { + m_os << '['; + m_nesting.push ('['); + } - indent (); + lhs->accept (*this); - m_os << "switch "; + if (len > 1) + { + m_nesting.pop (); + m_os << ']'; + } + } - tree_expression *expr = cmd.switch_value (); + m_os << ' ' << expr.oper () << ' '; - if (expr) - expr->accept (*this); + tree_expression *rhs = expr.right_hand_side (); - newline (); + if (rhs) + rhs->accept (*this); - tree_switch_case_list *list = cmd.case_list (); + print_parens (expr, ")"); +} - if (list) - { - increment_indent_level (); +void +tree_print_code::visit_no_op_command (tree_no_op_command& cmd) +{ + if (cmd.is_end_of_fcn_or_script () && m_curr_print_indent_level > 1) + decrement_indent_level (); + + indent (); - list->accept (*this); + m_os << cmd.original_command (); +} - decrement_indent_level (); - } +void +tree_print_code::visit_constant (tree_constant& val) +{ + indent (); - print_indented_comment (cmd.leading_comment ()); + print_parens (val, "("); + + val.print_raw (m_os, true, m_print_original_text); - indent (); + print_parens (val, ")"); +} + +void +tree_print_code::visit_fcn_handle (tree_fcn_handle& fh) +{ + indent (); - m_os << "endswitch"; - } + print_parens (fh, "("); + + fh.print_raw (m_os, true, m_print_original_text); - void - tree_print_code::visit_try_catch_command (tree_try_catch_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + print_parens (fh, ")"); +} + +void +tree_print_code::visit_parameter_list (tree_parameter_list& lst) +{ + bool is_input_list = lst.is_input_list (); - indent (); - - m_os << "try"; - - newline (); + if (is_input_list) + { + m_os << '('; + m_nesting.push ('('); + } + else + { + int len = lst.length (); + if (lst.takes_varargs ()) + len++; - tree_statement_list *try_code = cmd.body (); - tree_identifier *expr_id = cmd.identifier (); + if (len != 1) + { + m_os << '['; + m_nesting.push ('['); + } + } - if (try_code) - { - increment_indent_level (); + auto p = lst.begin (); - try_code->accept (*this); + while (p != lst.end ()) + { + tree_decl_elt *elt = *p++; - decrement_indent_level (); - } + if (elt) + { + elt->accept (*this); - print_indented_comment (cmd.middle_comment ()); + if (p != lst.end () || lst.takes_varargs ()) + m_os << ", "; + } + } - indent (); - - m_os << "catch"; + if (lst.takes_varargs ()) + m_os << lst.varargs_symbol_name (); - if (expr_id) - { - m_os << ' '; - expr_id->accept (*this); - } - - newline (); + if (is_input_list) + { + m_nesting.pop (); + m_os << ')'; + } + else + { + int len = lst.length (); + if (lst.takes_varargs ()) + len++; - tree_statement_list *catch_code = cmd.cleanup (); + if (len != 1) + { + m_nesting.pop (); + m_os << ']'; + } + } +} - if (catch_code) - { - increment_indent_level (); +void +tree_print_code::visit_postfix_expression (tree_postfix_expression& expr) +{ + indent (); - catch_code->accept (*this); + print_parens (expr, "("); + + tree_expression *e = expr.operand (); + + if (e) + e->accept (*this); - decrement_indent_level (); - } + m_os << expr.oper (); + + print_parens (expr, ")"); +} - print_indented_comment (cmd.trailing_comment ()); +void +tree_print_code::visit_prefix_expression (tree_prefix_expression& expr) +{ + indent (); - indent (); + print_parens (expr, "("); + + m_os << expr.oper (); + + tree_expression *e = expr.operand (); - m_os << "end_try_catch"; - } + if (e) + e->accept (*this); + + print_parens (expr, ")"); +} - void - tree_print_code::visit_unwind_protect_command (tree_unwind_protect_command& cmd) - { - print_comment_list (cmd.leading_comment ()); +void +tree_print_code::visit_return_command (tree_return_command&) +{ + indent (); - indent (); + m_os << "return"; +} - m_os << "unwind_protect"; +void +tree_print_code::visit_simple_assignment (tree_simple_assignment& expr) +{ + indent (); - newline (); + print_parens (expr, "("); - tree_statement_list *unwind_protect_code = cmd.body (); + tree_expression *lhs = expr.left_hand_side (); - if (unwind_protect_code) - { - increment_indent_level (); + if (lhs) + lhs->accept (*this); + + m_os << ' ' << expr.oper () << ' '; + + tree_expression *rhs = expr.right_hand_side (); - unwind_protect_code->accept (*this); + if (rhs) + rhs->accept (*this); - decrement_indent_level (); - } + print_parens (expr, ")"); +} - print_indented_comment (cmd.middle_comment ()); - - indent (); +void +tree_print_code::visit_statement (tree_statement& stmt) +{ + print_comment_list (stmt.comment_text ()); - m_os << "unwind_protect_cleanup"; + tree_command *cmd = stmt.command (); - newline (); + if (cmd) + { + cmd->accept (*this); - tree_statement_list *cleanup_code = cmd.cleanup (); + newline (); + } + else + { + tree_expression *expr = stmt.expression (); - if (cleanup_code) - { - increment_indent_level (); + if (expr) + { + expr->accept (*this); - cleanup_code->accept (*this); - - decrement_indent_level (); - } - - print_indented_comment (cmd.trailing_comment ()); + if (! stmt.print_result ()) + { + m_os << ';'; + newline (" "); + } + else + newline (); + } + } +} - indent (); - - m_os << "end_unwind_protect"; - } +void +tree_print_code::visit_statement_list (tree_statement_list& lst) +{ + for (tree_statement *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void - tree_print_code::visit_while_command (tree_while_command& cmd) - { - print_comment_list (cmd.leading_comment ()); +void +tree_print_code::visit_switch_case (tree_switch_case& cs) +{ + print_comment_list (cs.leading_comment ()); + + indent (); - indent (); + if (cs.is_default_case ()) + m_os << "otherwise"; + else + m_os << "case "; - m_os << "while "; + tree_expression *label = cs.case_label (); + + if (label) + label->accept (*this); - tree_expression *expr = cmd.condition (); + newline (); + + tree_statement_list *list = cs.commands (); - if (expr) - expr->accept (*this); + if (list) + { + increment_indent_level (); - newline (); + list->accept (*this); + + newline (); - tree_statement_list *list = cmd.body (); + decrement_indent_level (); + } +} - if (list) - { - increment_indent_level (); +void +tree_print_code::visit_switch_command (tree_switch_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); - list->accept (*this); + indent (); + + m_os << "switch "; + + tree_expression *expr = cmd.switch_value (); - decrement_indent_level (); - } + if (expr) + expr->accept (*this); - print_indented_comment (cmd.trailing_comment ()); + newline (); + + tree_switch_case_list *list = cmd.case_list (); - indent (); + if (list) + { + increment_indent_level (); + + list->accept (*this); - m_os << "endwhile"; - } + decrement_indent_level (); + } + + print_indented_comment (cmd.leading_comment ()); + + indent (); - void - tree_print_code::visit_do_until_command (tree_do_until_command& cmd) - { - print_comment_list (cmd.leading_comment ()); + m_os << "endswitch"; +} + +void +tree_print_code::visit_try_catch_command (tree_try_catch_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); + + indent (); - indent (); + m_os << "try"; - m_os << "do"; + newline (); - newline (); + tree_statement_list *try_code = cmd.body (); + tree_identifier *expr_id = cmd.identifier (); - tree_statement_list *list = cmd.body (); + if (try_code) + { + increment_indent_level (); + + try_code->accept (*this); - if (list) - { - increment_indent_level (); + decrement_indent_level (); + } - list->accept (*this); + print_indented_comment (cmd.middle_comment ()); + + indent (); + + m_os << "catch"; - decrement_indent_level (); - } + if (expr_id) + { + m_os << ' '; + expr_id->accept (*this); + } - print_indented_comment (cmd.trailing_comment ()); + newline (); + + tree_statement_list *catch_code = cmd.cleanup (); - indent (); + if (catch_code) + { + increment_indent_level (); - m_os << "until "; + catch_code->accept (*this); - tree_expression *expr = cmd.condition (); + decrement_indent_level (); + } - if (expr) - expr->accept (*this); + print_indented_comment (cmd.trailing_comment ()); + + indent (); - newline (); - } + m_os << "end_try_catch"; +} - void - tree_print_code::visit_superclass_ref (tree_superclass_ref& scr) - { - m_os << scr.method_name () << "@" << scr.class_name (); - } +void +tree_print_code::visit_unwind_protect_command (tree_unwind_protect_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); + + indent (); + + m_os << "unwind_protect"; + + newline (); - void - tree_print_code::visit_metaclass_query (tree_metaclass_query& mcq) - { - m_os << "?" << mcq.class_name (); - } + tree_statement_list *unwind_protect_code = cmd.body (); + + if (unwind_protect_code) + { + increment_indent_level (); + + unwind_protect_code->accept (*this); + + decrement_indent_level (); + } + + print_indented_comment (cmd.middle_comment ()); + + indent (); + + m_os << "unwind_protect_cleanup"; + + newline (); + + tree_statement_list *cleanup_code = cmd.cleanup (); - void - tree_print_code::print_fcn_handle_body (tree_expression *e) - { - if (e) - { - m_suppress_newlines++; - e->accept (*this); - m_suppress_newlines--; - } - } + if (cleanup_code) + { + increment_indent_level (); + + cleanup_code->accept (*this); + + decrement_indent_level (); + } + + print_indented_comment (cmd.trailing_comment ()); - // Each print_code() function should call this before printing anything. + indent (); + + m_os << "end_unwind_protect"; +} - void - tree_print_code::indent (void) - { - panic_unless (m_curr_print_indent_level >= 0); +void +tree_print_code::visit_while_command (tree_while_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); + + indent (); - if (m_beginning_of_line) - { - m_os << m_prefix; + m_os << "while "; + + tree_expression *expr = cmd.condition (); - m_os << std::string (m_curr_print_indent_level, ' '); + if (expr) + expr->accept (*this); + + newline (); + + tree_statement_list *list = cmd.body (); - m_beginning_of_line = false; - } - } + if (list) + { + increment_indent_level (); - // All print_code() functions should use this to print new lines. + list->accept (*this); + + decrement_indent_level (); + } + + print_indented_comment (cmd.trailing_comment ()); - void - tree_print_code::newline (const char *alt_txt) - { - if (m_suppress_newlines) - m_os << alt_txt; - else - { - // Print prefix for blank lines. - indent (); + indent (); + + m_os << "endwhile"; +} + +void +tree_print_code::visit_do_until_command (tree_do_until_command& cmd) +{ + print_comment_list (cmd.leading_comment ()); + + indent (); - m_os << "\n"; + m_os << "do"; + + newline (); + + tree_statement_list *list = cmd.body (); - m_beginning_of_line = true; - } - } + if (list) + { + increment_indent_level (); - // For resetting print_code state. + list->accept (*this); - void - tree_print_code::reset (void) - { - m_beginning_of_line = true; - m_curr_print_indent_level = 0; - while (m_nesting.top () != 'n') - m_nesting.pop (); - } + decrement_indent_level (); + } + + print_indented_comment (cmd.trailing_comment ()); + + indent (); + + m_os << "until "; + + tree_expression *expr = cmd.condition (); + + if (expr) + expr->accept (*this); + + newline (); +} - void - tree_print_code::print_parens (const tree_expression& expr, const char *txt) - { - int n = expr.paren_count (); +void +tree_print_code::visit_superclass_ref (tree_superclass_ref& scr) +{ + m_os << scr.method_name () << "@" << scr.class_name (); +} + +void +tree_print_code::visit_metaclass_query (tree_metaclass_query& mcq) +{ + m_os << "?" << mcq.class_name (); +} - for (int i = 0; i < n; i++) - m_os << txt; - } +void +tree_print_code::print_fcn_handle_body (tree_expression *e) +{ + if (e) + { + m_suppress_newlines++; + e->accept (*this); + m_suppress_newlines--; + } +} - void - tree_print_code::print_comment_elt (const comment_elt& elt) - { - bool printed_something = false; - - bool prev_char_was_newline = false; +// Each print_code() function should call this before printing anything. - std::string comment = elt.text (); - - std::size_t len = comment.length (); +void +tree_print_code::indent (void) +{ + panic_unless (m_curr_print_indent_level >= 0); - std::size_t i = 0; + if (m_beginning_of_line) + { + m_os << m_prefix; + + m_os << std::string (m_curr_print_indent_level, ' '); - while (i < len && comment[i++] == '\n') - ; // Skip leading new lines. - i--; + m_beginning_of_line = false; + } +} + +// All print_code() functions should use this to print new lines. - while (i < len) - { - char c = comment[i++]; +void +tree_print_code::newline (const char *alt_txt) +{ + if (m_suppress_newlines) + m_os << alt_txt; + else + { + // Print prefix for blank lines. + indent (); + + m_os << "\n"; + + m_beginning_of_line = true; + } +} - if (c == '\n') - { - if (prev_char_was_newline) - { - printed_something = true; +// For resetting print_code state. - indent (); +void +tree_print_code::reset (void) +{ + m_beginning_of_line = true; + m_curr_print_indent_level = 0; + while (m_nesting.top () != 'n') + m_nesting.pop (); +} - m_os << "##"; - } - - newline (); +void +tree_print_code::print_parens (const tree_expression& expr, const char *txt) +{ + int n = expr.paren_count (); - prev_char_was_newline = true; - } - else - { - if (m_beginning_of_line) - { - printed_something = true; + for (int i = 0; i < n; i++) + m_os << txt; +} + +void +tree_print_code::print_comment_elt (const comment_elt& elt) +{ + bool printed_something = false; - indent (); + bool prev_char_was_newline = false; + + std::string comment = elt.text (); + + std::size_t len = comment.length (); - m_os << "##"; + std::size_t i = 0; + + while (i < len && comment[i++] == '\n') + ; // Skip leading new lines. + i--; - if (! (isspace (c) || c == '!')) - m_os << ' '; - } + while (i < len) + { + char c = comment[i++]; - m_os << static_cast (c); + if (c == '\n') + { + if (prev_char_was_newline) + { + printed_something = true; + + indent (); - prev_char_was_newline = false; - } - } + m_os << "##"; + } + + newline (); - if (printed_something && ! m_beginning_of_line) - newline (); - } + prev_char_was_newline = true; + } + else + { + if (m_beginning_of_line) + { + printed_something = true; - void - tree_print_code::print_comment_list (comment_list *comment_list) - { - if (comment_list) - { - auto p = comment_list->begin (); + indent (); + + m_os << "##"; + + if (! (isspace (c) || c == '!')) + m_os << ' '; + } - while (p != comment_list->end ()) - { - comment_elt elt = *p++; + m_os << static_cast (c); - print_comment_elt (elt); + prev_char_was_newline = false; + } + } + + if (printed_something && ! m_beginning_of_line) + newline (); +} - if (p != comment_list->end ()) - newline (); - } - } - } +void +tree_print_code::print_comment_list (comment_list *comment_list) +{ + if (comment_list) + { + auto p = comment_list->begin (); + + while (p != comment_list->end ()) + { + comment_elt elt = *p++; + + print_comment_elt (elt); - void - tree_print_code::print_indented_comment (comment_list *comment_list) - { - increment_indent_level (); + if (p != comment_list->end ()) + newline (); + } + } +} - print_comment_list (comment_list); +void +tree_print_code::print_indented_comment (comment_list *comment_list) +{ + increment_indent_level (); - decrement_indent_level (); - } + print_comment_list (comment_list); + + decrement_indent_level (); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-pr-code.h --- a/libinterp/parse-tree/pt-pr-code.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-pr-code.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,180 +35,180 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class comment_elt; - class comment_list; - class tree_decl_command; - class tree_expression; +class comment_elt; +class comment_list; +class tree_decl_command; +class tree_expression; - // How to print the code that the parse trees represent. +// How to print the code that the parse trees represent. - class tree_print_code : public tree_walker - { - public: +class tree_print_code : public tree_walker +{ +public: - tree_print_code (std::ostream& os_arg, - const std::string& pfx = "", - bool pr_orig_txt = true) - : m_os (os_arg), m_prefix (pfx), m_nesting (), - m_print_original_text (pr_orig_txt), - m_curr_print_indent_level (0), m_beginning_of_line (true), - m_suppress_newlines (0) - { - // For "none". - m_nesting.push ('n'); - } + tree_print_code (std::ostream& os_arg, + const std::string& pfx = "", + bool pr_orig_txt = true) + : m_os (os_arg), m_prefix (pfx), m_nesting (), + m_print_original_text (pr_orig_txt), + m_curr_print_indent_level (0), m_beginning_of_line (true), + m_suppress_newlines (0) + { + // For "none". + m_nesting.push ('n'); + } - // No copying! + // No copying! - tree_print_code (const tree_print_code&) = delete; + tree_print_code (const tree_print_code&) = delete; - tree_print_code& operator = (const tree_print_code&) = delete; + tree_print_code& operator = (const tree_print_code&) = delete; - ~tree_print_code (void) = default; + ~tree_print_code (void) = default; - void visit_anon_fcn_handle (tree_anon_fcn_handle&); + void visit_anon_fcn_handle (tree_anon_fcn_handle&); - void visit_argument_list (tree_argument_list&); + void visit_argument_list (tree_argument_list&); - void visit_arguments_block (tree_arguments_block&); + void visit_arguments_block (tree_arguments_block&); - void visit_args_block_attribute_list (tree_args_block_attribute_list&); + void visit_args_block_attribute_list (tree_args_block_attribute_list&); - void visit_args_block_validation_list (tree_args_block_validation_list&); + void visit_args_block_validation_list (tree_args_block_validation_list&); - void visit_arg_validation (tree_arg_validation&); + void visit_arg_validation (tree_arg_validation&); - void visit_arg_size_spec (tree_arg_size_spec&); + void visit_arg_size_spec (tree_arg_size_spec&); - void visit_arg_validation_fcns (tree_arg_validation_fcns&); + void visit_arg_validation_fcns (tree_arg_validation_fcns&); - void visit_binary_expression (tree_binary_expression&); + void visit_binary_expression (tree_binary_expression&); - void visit_break_command (tree_break_command&); + void visit_break_command (tree_break_command&); - void visit_colon_expression (tree_colon_expression&); + void visit_colon_expression (tree_colon_expression&); - void visit_continue_command (tree_continue_command&); + void visit_continue_command (tree_continue_command&); - void visit_decl_command (tree_decl_command&); + void visit_decl_command (tree_decl_command&); - void visit_decl_init_list (tree_decl_init_list&); + void visit_decl_init_list (tree_decl_init_list&); - void visit_decl_elt (tree_decl_elt&); + void visit_decl_elt (tree_decl_elt&); - void visit_simple_for_command (tree_simple_for_command&); + void visit_simple_for_command (tree_simple_for_command&); - void visit_complex_for_command (tree_complex_for_command&); + void visit_complex_for_command (tree_complex_for_command&); - void visit_spmd_command (tree_spmd_command&); + void visit_spmd_command (tree_spmd_command&); - void visit_octave_user_script (octave_user_script&); + void visit_octave_user_script (octave_user_script&); - void visit_octave_user_function (octave_user_function&); + void visit_octave_user_function (octave_user_function&); - void visit_octave_user_function_header (octave_user_function&); + void visit_octave_user_function_header (octave_user_function&); - void visit_octave_user_function_trailer (octave_user_function&); + void visit_octave_user_function_trailer (octave_user_function&); - void visit_function_def (tree_function_def&); + void visit_function_def (tree_function_def&); - void visit_identifier (tree_identifier&); + void visit_identifier (tree_identifier&); - void visit_if_clause (tree_if_clause&); + void visit_if_clause (tree_if_clause&); - void visit_if_command (tree_if_command&); + void visit_if_command (tree_if_command&); - void visit_if_command_list (tree_if_command_list&); + void visit_if_command_list (tree_if_command_list&); - void visit_index_expression (tree_index_expression&); + void visit_index_expression (tree_index_expression&); - void visit_matrix (tree_matrix&); + void visit_matrix (tree_matrix&); - void visit_cell (tree_cell&); + void visit_cell (tree_cell&); - void visit_multi_assignment (tree_multi_assignment&); + void visit_multi_assignment (tree_multi_assignment&); - void visit_no_op_command (tree_no_op_command&); + void visit_no_op_command (tree_no_op_command&); - void visit_constant (tree_constant&); + void visit_constant (tree_constant&); - void visit_fcn_handle (tree_fcn_handle&); + void visit_fcn_handle (tree_fcn_handle&); - void visit_parameter_list (tree_parameter_list&); + void visit_parameter_list (tree_parameter_list&); - void visit_postfix_expression (tree_postfix_expression&); + void visit_postfix_expression (tree_postfix_expression&); - void visit_prefix_expression (tree_prefix_expression&); + void visit_prefix_expression (tree_prefix_expression&); - void visit_return_command (tree_return_command&); + void visit_return_command (tree_return_command&); - void visit_simple_assignment (tree_simple_assignment&); + void visit_simple_assignment (tree_simple_assignment&); - void visit_statement (tree_statement&); + void visit_statement (tree_statement&); - void visit_statement_list (tree_statement_list&); + void visit_statement_list (tree_statement_list&); - void visit_switch_case (tree_switch_case&); + void visit_switch_case (tree_switch_case&); - void visit_switch_command (tree_switch_command&); + void visit_switch_command (tree_switch_command&); - void visit_try_catch_command (tree_try_catch_command&); + void visit_try_catch_command (tree_try_catch_command&); - void visit_unwind_protect_command (tree_unwind_protect_command&); + void visit_unwind_protect_command (tree_unwind_protect_command&); - void visit_while_command (tree_while_command&); + void visit_while_command (tree_while_command&); - void visit_do_until_command (tree_do_until_command&); + void visit_do_until_command (tree_do_until_command&); - void visit_superclass_ref (tree_superclass_ref&); + void visit_superclass_ref (tree_superclass_ref&); - void visit_metaclass_query (tree_metaclass_query&); + void visit_metaclass_query (tree_metaclass_query&); - void print_fcn_handle_body (tree_expression *); + void print_fcn_handle_body (tree_expression *); - private: +private: - std::ostream& m_os; + std::ostream& m_os; - std::string m_prefix; + std::string m_prefix; - std::stack m_nesting; + std::stack m_nesting; - bool m_print_original_text; + bool m_print_original_text; - // Current indentation. - int m_curr_print_indent_level; + // Current indentation. + int m_curr_print_indent_level; - // TRUE means we are at the beginning of a line. - bool m_beginning_of_line; + // TRUE means we are at the beginning of a line. + bool m_beginning_of_line; - // Nonzero means we are not printing newlines and indenting. - int m_suppress_newlines; + // Nonzero means we are not printing newlines and indenting. + int m_suppress_newlines; - void reset_indent_level (void) { m_curr_print_indent_level = 0; } + void reset_indent_level (void) { m_curr_print_indent_level = 0; } - void increment_indent_level (void) { m_curr_print_indent_level += 2; } + void increment_indent_level (void) { m_curr_print_indent_level += 2; } - void decrement_indent_level (void) { m_curr_print_indent_level -= 2; } + void decrement_indent_level (void) { m_curr_print_indent_level -= 2; } - void newline (const char *alt_txt = ", "); + void newline (const char *alt_txt = ", "); - void indent (void); + void indent (void); - void reset (void); + void reset (void); - void print_parens (const tree_expression& expr, const char *txt); + void print_parens (const tree_expression& expr, const char *txt); - void print_comment_list (comment_list *comment_list); + void print_comment_list (comment_list *comment_list); - void print_comment_elt (const comment_elt& comment_elt); + void print_comment_elt (const comment_elt& comment_elt); - void print_indented_comment (comment_list *comment_list); + void print_indented_comment (comment_list *comment_list); - // Must create with an output stream! + // Must create with an output stream! - tree_print_code (void); - }; + tree_print_code (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-select.cc --- a/libinterp/parse-tree/pt-select.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-select.cc Thu Dec 01 20:05:44 2022 -0800 @@ -33,41 +33,41 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // If clauses. +// If clauses. - tree_if_clause::~tree_if_clause (void) - { - delete m_expr; - delete m_list; - delete m_lead_comm; - } +tree_if_clause::~tree_if_clause (void) +{ + delete m_expr; + delete m_list; + delete m_lead_comm; +} - // If. +// If. - tree_if_command::~tree_if_command (void) - { - delete m_list; - delete m_lead_comm; - delete m_trail_comm; - } +tree_if_command::~tree_if_command (void) +{ + delete m_list; + delete m_lead_comm; + delete m_trail_comm; +} - // Switch cases. +// Switch cases. - tree_switch_case::~tree_switch_case (void) - { - delete m_label; - delete m_list; - delete m_lead_comm; - } +tree_switch_case::~tree_switch_case (void) +{ + delete m_label; + delete m_list; + delete m_lead_comm; +} - // Switch. +// Switch. - tree_switch_command::~tree_switch_command (void) - { - delete m_expr; - delete m_list; - delete m_lead_comm; - delete m_trail_comm; - } +tree_switch_command::~tree_switch_command (void) +{ + delete m_expr; + delete m_list; + delete m_lead_comm; + delete m_trail_comm; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-select.h --- a/libinterp/parse-tree/pt-select.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-select.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,267 +35,267 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_expression; - class tree_statement_list; +class tree_expression; +class tree_statement_list; + +// If. + +class tree_if_clause : public tree +{ +public: + + tree_if_clause (int l = -1, int c = -1) + : tree (l, c), m_expr (nullptr), m_list (nullptr), m_lead_comm (nullptr) + { } + + tree_if_clause (tree_statement_list *sl, comment_list *lc = nullptr, + int l = -1, int c = -1) + : tree (l, c), m_expr (nullptr), m_list (sl), m_lead_comm (lc) { } + + tree_if_clause (tree_expression *e, tree_statement_list *sl, + comment_list *lc = nullptr, + int l = -1, int c = -1) + : tree (l, c), m_expr (e), m_list (sl), m_lead_comm (lc) { } + + // No copying! + + tree_if_clause (const tree_if_clause&) = delete; + + tree_if_clause& operator = (const tree_if_clause&) = delete; + + ~tree_if_clause (void); + + bool is_else_clause (void) { return ! m_expr; } + + tree_expression * condition (void) { return m_expr; } - // If. + tree_statement_list * commands (void) { return m_list; } + + comment_list * leading_comment (void) { return m_lead_comm; } + + void accept (tree_walker& tw) + { + tw.visit_if_clause (*this); + } + +private: + + // The condition to test. + tree_expression *m_expr; + + // The list of statements to evaluate if expr is true. + tree_statement_list *m_list; - class tree_if_clause : public tree - { - public: + // Comment preceding ELSE or ELSEIF token. + comment_list *m_lead_comm; +}; + +class tree_if_command_list : public base_list +{ +public: + + tree_if_command_list (void) { } + + tree_if_command_list (tree_if_clause *t) { append (t); } + + // No copying! + + tree_if_command_list (const tree_if_command_list&) = delete; + + tree_if_command_list& operator = (const tree_if_command_list&) = delete; - tree_if_clause (int l = -1, int c = -1) - : tree (l, c), m_expr (nullptr), m_list (nullptr), m_lead_comm (nullptr) - { } + ~tree_if_command_list (void) + { + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } + } + + void accept (tree_walker& tw) + { + tw.visit_if_command_list (*this); + } +}; + +class tree_if_command : public tree_command +{ +public: + + tree_if_command (int l = -1, int c = -1) + : tree_command (l, c), m_list (nullptr), + m_lead_comm (nullptr), m_trail_comm (nullptr) + { } + + tree_if_command (tree_if_command_list *lst, comment_list *lc, + comment_list *tc, int l = -1, int c = -1) + : tree_command (l, c), m_list (lst), m_lead_comm (lc), m_trail_comm (tc) + { } + + // No copying! + + tree_if_command (const tree_if_command&) = delete; + + tree_if_command& operator = (const tree_if_command&) = delete; + + ~tree_if_command (void); - tree_if_clause (tree_statement_list *sl, comment_list *lc = nullptr, + tree_if_command_list * cmd_list (void) { return m_list; } + + 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_if_command (*this); + } + +private: + + // List of if commands (if, elseif, elseif, ... else, endif) + tree_if_command_list *m_list; + + // Comment preceding IF token. + comment_list *m_lead_comm; + + // Comment preceding ENDIF token. + comment_list *m_trail_comm; +}; + +// Switch. + +class tree_switch_case : public tree +{ +public: + + tree_switch_case (int l = -1, int c = -1) + : tree (l, c), m_label (nullptr), m_list (nullptr), m_lead_comm (nullptr) + { } + + tree_switch_case (tree_statement_list *sl, comment_list *lc = nullptr, int l = -1, int c = -1) - : tree (l, c), m_expr (nullptr), m_list (sl), m_lead_comm (lc) { } + : tree (l, c), m_label (nullptr), m_list (sl), m_lead_comm (lc) { } - tree_if_clause (tree_expression *e, tree_statement_list *sl, + tree_switch_case (tree_expression *e, tree_statement_list *sl, comment_list *lc = nullptr, int l = -1, int c = -1) - : tree (l, c), m_expr (e), m_list (sl), m_lead_comm (lc) { } - - // No copying! - - tree_if_clause (const tree_if_clause&) = delete; + : tree (l, c), m_label (e), m_list (sl), m_lead_comm (lc) { } - tree_if_clause& operator = (const tree_if_clause&) = delete; - - ~tree_if_clause (void); - - bool is_else_clause (void) { return ! m_expr; } - - tree_expression * condition (void) { return m_expr; } + // No copying! - tree_statement_list * commands (void) { return m_list; } - - comment_list * leading_comment (void) { return m_lead_comm; } + tree_switch_case (const tree_switch_case&) = delete; - void accept (tree_walker& tw) - { - tw.visit_if_clause (*this); - } + tree_switch_case& operator = (const tree_switch_case&) = delete; - private: - - // The condition to test. - tree_expression *m_expr; + ~tree_switch_case (void); - // The list of statements to evaluate if expr is true. - tree_statement_list *m_list; - - // Comment preceding ELSE or ELSEIF token. - comment_list *m_lead_comm; - }; + bool is_default_case (void) { return ! m_label; } - class tree_if_command_list : public base_list - { - public: + tree_expression * case_label (void) { return m_label; } - tree_if_command_list (void) { } - - tree_if_command_list (tree_if_clause *t) { append (t); } + tree_statement_list * commands (void) { return m_list; } - // No copying! - - tree_if_command_list (const tree_if_command_list&) = delete; - - tree_if_command_list& operator = (const tree_if_command_list&) = delete; + comment_list * leading_comment (void) { return m_lead_comm; } - ~tree_if_command_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } + void accept (tree_walker& tw) + { + tw.visit_switch_case (*this); + } - void accept (tree_walker& tw) - { - tw.visit_if_command_list (*this); - } - }; +private: - class tree_if_command : public tree_command - { - public: - - tree_if_command (int l = -1, int c = -1) - : tree_command (l, c), m_list (nullptr), - m_lead_comm (nullptr), m_trail_comm (nullptr) - { } + // The case label. + tree_expression *m_label; - tree_if_command (tree_if_command_list *lst, comment_list *lc, - comment_list *tc, int l = -1, int c = -1) - : tree_command (l, c), m_list (lst), m_lead_comm (lc), m_trail_comm (tc) - { } - - // No copying! + // The list of statements to evaluate if the label matches. + tree_statement_list *m_list; - tree_if_command (const tree_if_command&) = delete; - - tree_if_command& operator = (const tree_if_command&) = delete; - - ~tree_if_command (void); - - tree_if_command_list * cmd_list (void) { return m_list; } + // Comment preceding CASE or OTHERWISE token. + comment_list *m_lead_comm; +}; - comment_list * leading_comment (void) { return m_lead_comm; } - - comment_list * trailing_comment (void) { return m_trail_comm; } +class tree_switch_case_list : public base_list +{ +public: - void accept (tree_walker& tw) - { - tw.visit_if_command (*this); - } - - private: - - // List of if commands (if, elseif, elseif, ... else, endif) - tree_if_command_list *m_list; + tree_switch_case_list (void) { } - // Comment preceding IF token. - comment_list *m_lead_comm; + tree_switch_case_list (tree_switch_case *t) { append (t); } - // Comment preceding ENDIF token. - comment_list *m_trail_comm; - }; + // No copying! - // Switch. + tree_switch_case_list (const tree_switch_case_list&) = delete; - class tree_switch_case : public tree - { - public: - - tree_switch_case (int l = -1, int c = -1) - : tree (l, c), m_label (nullptr), m_list (nullptr), m_lead_comm (nullptr) - { } + tree_switch_case_list& operator = (const tree_switch_case_list&) = delete; - tree_switch_case (tree_statement_list *sl, comment_list *lc = nullptr, - int l = -1, int c = -1) - : tree (l, c), m_label (nullptr), m_list (sl), m_lead_comm (lc) { } - - tree_switch_case (tree_expression *e, tree_statement_list *sl, - comment_list *lc = nullptr, - int l = -1, int c = -1) - : tree (l, c), m_label (e), m_list (sl), m_lead_comm (lc) { } - - // No copying! + ~tree_switch_case_list (void) + { + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } + } - tree_switch_case (const tree_switch_case&) = delete; - - tree_switch_case& operator = (const tree_switch_case&) = delete; - - ~tree_switch_case (void); - - bool is_default_case (void) { return ! m_label; } - - tree_expression * case_label (void) { return m_label; } - - tree_statement_list * commands (void) { return m_list; } - - comment_list * leading_comment (void) { return m_lead_comm; } + void accept (tree_walker& tw) + { + tw.visit_switch_case_list (*this); + } +}; - void accept (tree_walker& tw) - { - tw.visit_switch_case (*this); - } +class tree_switch_command : public tree_command +{ +public: - private: - - // The case label. - tree_expression *m_label; - - // The list of statements to evaluate if the label matches. - tree_statement_list *m_list; + tree_switch_command (int l = -1, int c = -1) + : tree_command (l, c), m_expr (nullptr), m_list (nullptr), + m_lead_comm (nullptr), m_trail_comm (nullptr) { } - // Comment preceding CASE or OTHERWISE token. - comment_list *m_lead_comm; - }; - - class tree_switch_case_list : public base_list - { - public: + tree_switch_command (tree_expression *e, tree_switch_case_list *lst, + comment_list *lc, comment_list *tc, + int l = -1, int c = -1) + : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc), + m_trail_comm (tc) { } - tree_switch_case_list (void) { } - - tree_switch_case_list (tree_switch_case *t) { append (t); } - - // No copying! - - tree_switch_case_list (const tree_switch_case_list&) = delete; - - tree_switch_case_list& operator = (const tree_switch_case_list&) = delete; + // No copying! - ~tree_switch_case_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } + tree_switch_command (const tree_switch_command&) = delete; - void accept (tree_walker& tw) - { - tw.visit_switch_case_list (*this); - } - }; + tree_switch_command& operator = (const tree_switch_command&) = delete; + + ~tree_switch_command (void); - class tree_switch_command : public tree_command - { - public: + tree_expression * switch_value (void) { return m_expr; } - tree_switch_command (int l = -1, int c = -1) - : tree_command (l, c), m_expr (nullptr), m_list (nullptr), - m_lead_comm (nullptr), m_trail_comm (nullptr) { } + tree_switch_case_list * case_list (void) { return m_list; } - tree_switch_command (tree_expression *e, tree_switch_case_list *lst, - comment_list *lc, comment_list *tc, - int l = -1, int c = -1) - : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc), - m_trail_comm (tc) { } + comment_list * leading_comment (void) { return m_lead_comm; } - // No copying! + comment_list * trailing_comment (void) { return m_trail_comm; } - tree_switch_command (const tree_switch_command&) = delete; - - tree_switch_command& operator = (const tree_switch_command&) = delete; - - ~tree_switch_command (void); + void accept (tree_walker& tw) + { + tw.visit_switch_command (*this); + } - tree_expression * switch_value (void) { return m_expr; } - - tree_switch_case_list * case_list (void) { return m_list; } +private: - comment_list * leading_comment (void) { return m_lead_comm; } - - comment_list * trailing_comment (void) { return m_trail_comm; } + // Value on which to switch. + tree_expression *m_expr; - void accept (tree_walker& tw) - { - tw.visit_switch_command (*this); - } - - private: - - // Value on which to switch. - tree_expression *m_expr; + // List of cases (case 1, case 2, ..., default) + tree_switch_case_list *m_list; - // List of cases (case 1, case 2, ..., default) - tree_switch_case_list *m_list; + // Comment preceding SWITCH token. + comment_list *m_lead_comm; - // Comment preceding SWITCH token. - comment_list *m_lead_comm; - - // Comment preceding ENDSWITCH token. - comment_list *m_trail_comm; - }; + // Comment preceding ENDSWITCH token. + comment_list *m_trail_comm; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-spmd.cc --- a/libinterp/parse-tree/pt-spmd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-spmd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -33,11 +33,11 @@ OCTAVE_BEGIN_NAMESPACE(octave) - tree_spmd_command::~tree_spmd_command (void) - { - delete m_body; - delete m_lead_comm; - delete m_trail_comm; - } +tree_spmd_command::~tree_spmd_command (void) +{ + delete m_body; + delete m_lead_comm; + delete m_trail_comm; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-spmd.h --- a/libinterp/parse-tree/pt-spmd.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-spmd.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,50 +34,50 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_comment_list; - class tree_statement_list; +class tree_comment_list; +class tree_statement_list; - // Spmd. +// Spmd. - class tree_spmd_command : public tree_command - { - public: +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) - { } + 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! + // No copying! - tree_spmd_command (const tree_spmd_command&) = delete; + tree_spmd_command (const tree_spmd_command&) = delete; - tree_spmd_command& operator = (const tree_spmd_command&) = delete; + tree_spmd_command& operator = (const tree_spmd_command&) = delete; - ~tree_spmd_command (void); + ~tree_spmd_command (void); - tree_statement_list * body (void) { return m_body; } + tree_statement_list * body (void) { return m_body; } - comment_list * leading_comment (void) { return m_lead_comm; } + comment_list * leading_comment (void) { return m_lead_comm; } - comment_list * trailing_comment (void) { return m_trail_comm; } + comment_list * trailing_comment (void) { return m_trail_comm; } - void accept (tree_walker& tw) - { - tw.visit_spmd_command (*this); - } + void accept (tree_walker& tw) + { + tw.visit_spmd_command (*this); + } - private: +private: - // List of commands. - tree_statement_list *m_body; + // List of commands. + tree_statement_list *m_body; - // Comment preceding SPMD token. - comment_list *m_lead_comm; + // Comment preceding SPMD token. + comment_list *m_lead_comm; - // Comment preceding ENDSPMD token. - comment_list *m_trail_comm; - }; + // Comment preceding ENDSPMD token. + comment_list *m_trail_comm; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-stmt.cc --- a/libinterp/parse-tree/pt-stmt.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-stmt.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,251 +51,251 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // A list of commands to be executed. +// A list of commands to be executed. - tree_statement::~tree_statement (void) - { - delete m_command; - delete m_expression; - delete m_comment_list; - } +tree_statement::~tree_statement (void) +{ + delete m_command; + delete m_expression; + delete m_comment_list; +} - void - tree_statement::set_print_flag (bool print_flag) - { - if (m_expression) - m_expression->set_print_flag (print_flag); - } +void +tree_statement::set_print_flag (bool print_flag) +{ + if (m_expression) + m_expression->set_print_flag (print_flag); +} - bool - tree_statement::print_result (void) - { - return m_expression && m_expression->print_result (); - } +bool +tree_statement::print_result (void) +{ + return m_expression && m_expression->print_result (); +} - void - tree_statement::set_breakpoint (const std::string& condition) - { - if (m_command) - m_command->set_breakpoint (condition); - else if (m_expression) - m_expression->set_breakpoint (condition); - } +void +tree_statement::set_breakpoint (const std::string& condition) +{ + if (m_command) + m_command->set_breakpoint (condition); + else if (m_expression) + m_expression->set_breakpoint (condition); +} - void - tree_statement::delete_breakpoint (void) - { - if (m_command) - m_command->delete_breakpoint (); - else if (m_expression) - m_expression->delete_breakpoint (); - } +void +tree_statement::delete_breakpoint (void) +{ + if (m_command) + m_command->delete_breakpoint (); + else if (m_expression) + m_expression->delete_breakpoint (); +} - bool - tree_statement::is_breakpoint (void) const - { - return m_command ? m_command->is_breakpoint () - : (m_expression ? m_expression->is_breakpoint () - : false); - } +bool +tree_statement::is_breakpoint (void) const +{ + return m_command ? m_command->is_breakpoint () + : (m_expression ? m_expression->is_breakpoint () + : false); +} - bool - tree_statement::is_active_breakpoint (tree_evaluator& tw) const - { - return m_command ? m_command->is_active_breakpoint (tw) - : (m_expression ? m_expression->is_active_breakpoint (tw) - : false); - } +bool +tree_statement::is_active_breakpoint (tree_evaluator& tw) const +{ + return m_command ? m_command->is_active_breakpoint (tw) + : (m_expression ? m_expression->is_active_breakpoint (tw) + : false); +} - std::string - tree_statement::bp_cond () const - { - return (m_command - ? m_command->bp_cond () - : (m_expression ? m_expression->bp_cond () : "0")); - } +std::string +tree_statement::bp_cond () const +{ + return (m_command + ? m_command->bp_cond () + : (m_expression ? m_expression->bp_cond () : "0")); +} - int - tree_statement::line (void) const - { - return (m_command - ? m_command->line () - : (m_expression ? m_expression->line () : -1)); - } +int +tree_statement::line (void) const +{ + return (m_command + ? m_command->line () + : (m_expression ? m_expression->line () : -1)); +} - int - tree_statement::column (void) const - { - return (m_command - ? m_command->column () - : (m_expression ? m_expression->column () : -1)); - } +int +tree_statement::column (void) const +{ + return (m_command + ? m_command->column () + : (m_expression ? m_expression->column () : -1)); +} - void - tree_statement::set_location (int l, int c) - { - if (m_command) - m_command->set_location (l, c); - else if (m_expression) - m_expression->set_location (l, c); - } +void +tree_statement::set_location (int l, int c) +{ + if (m_command) + m_command->set_location (l, c); + else if (m_expression) + m_expression->set_location (l, c); +} - void - tree_statement::echo_code (const std::string& prefix) - { - tree_print_code tpc (octave_stdout, prefix); +void +tree_statement::echo_code (const std::string& prefix) +{ + tree_print_code tpc (octave_stdout, prefix); - accept (tpc); - } + accept (tpc); +} - bool - tree_statement::is_end_of_fcn_or_script (void) const - { - bool retval = false; +bool +tree_statement::is_end_of_fcn_or_script (void) const +{ + bool retval = false; - if (m_command) - { - tree_no_op_command *no_op_cmd - = dynamic_cast (m_command); + if (m_command) + { + tree_no_op_command *no_op_cmd + = dynamic_cast (m_command); - if (no_op_cmd) - retval = no_op_cmd->is_end_of_fcn_or_script (); - } + if (no_op_cmd) + retval = no_op_cmd->is_end_of_fcn_or_script (); + } - return retval; - } + return retval; +} - bool - tree_statement::is_end_of_file (void) const - { - bool retval = false; +bool +tree_statement::is_end_of_file (void) const +{ + bool retval = false; - if (m_command) - { - tree_no_op_command *no_op_cmd - = dynamic_cast (m_command); + if (m_command) + { + tree_no_op_command *no_op_cmd + = dynamic_cast (m_command); - if (no_op_cmd) - retval = no_op_cmd->is_end_of_file (); - } + if (no_op_cmd) + retval = no_op_cmd->is_end_of_file (); + } - return retval; - } + return retval; +} - // Create a "breakpoint" tree-walker, and get it to "walk" this - // statement list - // (FIXME: What does that do???) +// Create a "breakpoint" tree-walker, and get it to "walk" this +// statement list +// (FIXME: What does that do???) - int - tree_statement_list::set_breakpoint (int line, const std::string& condition) - { - tree_breakpoint tbp (line, tree_breakpoint::set, condition); - accept (tbp); +int +tree_statement_list::set_breakpoint (int line, const std::string& condition) +{ + tree_breakpoint tbp (line, tree_breakpoint::set, condition); + accept (tbp); - return tbp.get_line (); - } + return tbp.get_line (); +} - void - tree_statement_list::delete_breakpoint (int line) - { - if (line < 0) - { - octave_value_list bp_lst = list_breakpoints (); +void +tree_statement_list::delete_breakpoint (int line) +{ + if (line < 0) + { + octave_value_list bp_lst = list_breakpoints (); - int len = bp_lst.length (); + int len = bp_lst.length (); - for (int i = 0; i < len; i++) - { - tree_breakpoint tbp (i, tree_breakpoint::clear); - accept (tbp); - } - } - else - { - tree_breakpoint tbp (line, tree_breakpoint::clear); - accept (tbp); - } - } + for (int i = 0; i < len; i++) + { + tree_breakpoint tbp (i, tree_breakpoint::clear); + accept (tbp); + } + } + else + { + tree_breakpoint tbp (line, tree_breakpoint::clear); + accept (tbp); + } +} - octave_value_list - tree_statement_list::list_breakpoints (void) - { - tree_breakpoint tbp (0, tree_breakpoint::list); - accept (tbp); +octave_value_list +tree_statement_list::list_breakpoints (void) +{ + tree_breakpoint tbp (0, tree_breakpoint::list); + accept (tbp); - return tbp.get_list (); - } + return tbp.get_list (); +} - // Get list of pairs (breakpoint line, breakpoint condition) - std::list - tree_statement_list::breakpoints_and_conds (void) - { - tree_breakpoint tbp (0, tree_breakpoint::list); - accept (tbp); +// Get list of pairs (breakpoint line, breakpoint condition) +std::list +tree_statement_list::breakpoints_and_conds (void) +{ + tree_breakpoint tbp (0, tree_breakpoint::list); + accept (tbp); - std::list retval; - octave_value_list lines = tbp.get_list (); - octave_value_list conds = tbp.get_cond_list (); + std::list retval; + octave_value_list lines = tbp.get_list (); + octave_value_list conds = tbp.get_cond_list (); - for (int i = 0; i < lines.length (); i++) - { - retval.push_back (bp_type (lines(i).double_value (), - conds(i).string_value ())); - } + for (int i = 0; i < lines.length (); i++) + { + retval.push_back (bp_type (lines(i).double_value (), + conds(i).string_value ())); + } - return retval; - } + return retval; +} - // Add breakpoints to file at multiple lines (the second arguments - // of line), to stop only if condition is true. - // Updates GUI via event_manager::update_breakpoint. - // FIXME: COME BACK TO ME. +// Add breakpoints to file at multiple lines (the second arguments +// of line), to stop only if condition is true. +// Updates GUI via event_manager::update_breakpoint. +// FIXME: COME BACK TO ME. - bp_table::bp_lines - tree_statement_list::add_breakpoint (event_manager& evmgr, - const std::string& file, - const bp_table::bp_lines& lines, - const std::string& condition) - { - bp_table::bp_lines retval; +bp_table::bp_lines +tree_statement_list::add_breakpoint (event_manager& evmgr, + const std::string& file, + const bp_table::bp_lines& lines, + const std::string& condition) +{ + bp_table::bp_lines retval; - for (const auto& lineno : lines) - { - int line = set_breakpoint (lineno, condition); + for (const auto& lineno : lines) + { + int line = set_breakpoint (lineno, condition); - if (line) - { - if (! file.empty ()) - evmgr.update_breakpoint (true, file, line, condition); + if (line) + { + if (! file.empty ()) + evmgr.update_breakpoint (true, file, line, condition); - retval.insert (line); - } - } + retval.insert (line); + } + } - return retval; - } + return retval; +} - bp_table::bp_lines - tree_statement_list::remove_all_breakpoints (event_manager& evmgr, - const std::string& file) - { - bp_table::bp_lines retval; +bp_table::bp_lines +tree_statement_list::remove_all_breakpoints (event_manager& evmgr, + const std::string& file) +{ + bp_table::bp_lines retval; - octave_value_list bkpts = list_breakpoints (); + octave_value_list bkpts = list_breakpoints (); - for (int i = 0; i < bkpts.length (); i++) - { - int lineno = bkpts(i).int_value (); + for (int i = 0; i < bkpts.length (); i++) + { + int lineno = bkpts(i).int_value (); - delete_breakpoint (lineno); + delete_breakpoint (lineno); - retval.insert (lineno); + retval.insert (lineno); - if (! file.empty ()) - evmgr.update_breakpoint (false, file, lineno); - } + if (! file.empty ()) + evmgr.update_breakpoint (false, file, lineno); + } - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-stmt.h --- a/libinterp/parse-tree/pt-stmt.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-stmt.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,177 +41,177 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class comment_list; - class tree_command; - class tree_evaluator; - class tree_expression; +class comment_list; +class tree_command; +class tree_evaluator; +class tree_expression; - // A statement is either a command to execute or an expression to - // evaluate. +// A statement is either a command to execute or an expression to +// evaluate. - class tree_statement : public tree - { - public: +class tree_statement : public tree +{ +public: - tree_statement (void) - : m_command (nullptr), m_expression (nullptr), - m_comment_list (nullptr) { } + tree_statement (void) + : m_command (nullptr), m_expression (nullptr), + m_comment_list (nullptr) { } - tree_statement (tree_command *c, comment_list *cl) - : m_command (c), m_expression (nullptr), m_comment_list (cl) { } + tree_statement (tree_command *c, comment_list *cl) + : m_command (c), m_expression (nullptr), m_comment_list (cl) { } - tree_statement (tree_expression *e, comment_list *cl) - : m_command (nullptr), m_expression (e), m_comment_list (cl) { } + tree_statement (tree_expression *e, comment_list *cl) + : m_command (nullptr), m_expression (e), m_comment_list (cl) { } - // No copying! + // No copying! - tree_statement (const tree_statement&) = delete; + tree_statement (const tree_statement&) = delete; - tree_statement& operator = (const tree_statement&) = delete; + tree_statement& operator = (const tree_statement&) = delete; - ~tree_statement (void); + ~tree_statement (void); - void set_print_flag (bool print_flag); + void set_print_flag (bool print_flag); - bool print_result (void); + bool print_result (void); - bool is_command (void) const { return m_command != nullptr; } + bool is_command (void) const { return m_command != nullptr; } - bool is_expression (void) const { return m_expression != nullptr; } + bool is_expression (void) const { return m_expression != nullptr; } - void set_breakpoint (const std::string& condition); + void set_breakpoint (const std::string& condition); - void delete_breakpoint (void); + void delete_breakpoint (void); - bool is_breakpoint (void) const; + bool is_breakpoint (void) const; - bool is_active_breakpoint (tree_evaluator& tw) const; + bool is_active_breakpoint (tree_evaluator& tw) const; - std::string bp_cond () const; + std::string bp_cond () const; - int line (void) const; - int column (void) const; + int line (void) const; + int column (void) const; - void set_location (int l, int c); + void set_location (int l, int c); - void echo_code (const std::string& prefix); + void echo_code (const std::string& prefix); - tree_command * command (void) { return m_command; } + tree_command * command (void) { return m_command; } - tree_expression * expression (void) { return m_expression; } + tree_expression * expression (void) { return m_expression; } - comment_list * comment_text (void) { return m_comment_list; } + comment_list * comment_text (void) { return m_comment_list; } - bool is_null_statement (void) const - { - return ! (m_command || m_expression || m_comment_list); - } + bool is_null_statement (void) const + { + return ! (m_command || m_expression || m_comment_list); + } - bool is_end_of_fcn_or_script (void) const; + bool is_end_of_fcn_or_script (void) const; - bool is_end_of_file (void) const; + bool is_end_of_file (void) const; - // Allow modification of this statement. Note that there is no - // checking. If you use these, are you sure you know what you are - // doing? + // Allow modification of this statement. Note that there is no + // checking. If you use these, are you sure you know what you are + // doing? - void set_command (tree_command *c) { m_command = c; } + void set_command (tree_command *c) { m_command = c; } - void set_expression (tree_expression *e) { m_expression = e; } + void set_expression (tree_expression *e) { m_expression = e; } - void accept (tree_walker& tw) - { - tw.visit_statement (*this); - } + void accept (tree_walker& tw) + { + tw.visit_statement (*this); + } - private: +private: - // Only one of cmd or expr can be valid at once. + // Only one of cmd or expr can be valid at once. - // Command to execute. - tree_command *m_command; + // Command to execute. + tree_command *m_command; - // Expression to evaluate. - tree_expression *m_expression; + // Expression to evaluate. + tree_expression *m_expression; - // Comment associated with this statement. - comment_list *m_comment_list; - }; + // Comment associated with this statement. + comment_list *m_comment_list; +}; - // A list of statements to evaluate. +// A list of statements to evaluate. - class tree_statement_list : public base_list - { - public: +class tree_statement_list : public base_list +{ +public: - tree_statement_list (void) - : m_function_body (false), m_anon_function_body (false), - m_script_body (false) { } + tree_statement_list (void) + : m_function_body (false), m_anon_function_body (false), + m_script_body (false) { } - tree_statement_list (tree_statement *s) - : m_function_body (false), m_anon_function_body (false), - m_script_body (false) { append (s); } + tree_statement_list (tree_statement *s) + : m_function_body (false), m_anon_function_body (false), + m_script_body (false) { append (s); } - // No copying! + // No copying! - tree_statement_list (const tree_statement_list&) = delete; + tree_statement_list (const tree_statement_list&) = delete; - tree_statement_list& operator = (const tree_statement_list&) = delete; + tree_statement_list& operator = (const tree_statement_list&) = delete; - ~tree_statement_list (void) - { - while (! empty ()) - { - auto p = begin (); - delete *p; - erase (p); - } - } + ~tree_statement_list (void) + { + while (! empty ()) + { + auto p = begin (); + delete *p; + erase (p); + } + } - void mark_as_function_body (void) { m_function_body = true; } + void mark_as_function_body (void) { m_function_body = true; } - void mark_as_anon_function_body (void) { m_anon_function_body = true; } + void mark_as_anon_function_body (void) { m_anon_function_body = true; } - void mark_as_script_body (void) { m_script_body = true; } + void mark_as_script_body (void) { m_script_body = true; } - bool is_function_body (void) const { return m_function_body; } + bool is_function_body (void) const { return m_function_body; } - bool is_anon_function_body (void) const { return m_anon_function_body; } + bool is_anon_function_body (void) const { return m_anon_function_body; } - bool is_script_body (void) const { return m_script_body; } + bool is_script_body (void) const { return m_script_body; } - int set_breakpoint (int line, const std::string& condition); + int set_breakpoint (int line, const std::string& condition); - void delete_breakpoint (int line); + void delete_breakpoint (int line); - octave_value_list list_breakpoints (void); + octave_value_list list_breakpoints (void); - std::list breakpoints_and_conds (void); + std::list breakpoints_and_conds (void); - bp_table::bp_lines add_breakpoint (event_manager& evmgr, - const std::string& file, - const bp_table::bp_lines& lines, - const std::string& condition); + bp_table::bp_lines add_breakpoint (event_manager& evmgr, + const std::string& file, + const bp_table::bp_lines& lines, + const std::string& condition); - bp_table::bp_lines remove_all_breakpoints (event_manager& evmgr, - const std::string& file); + bp_table::bp_lines remove_all_breakpoints (event_manager& evmgr, + const std::string& file); - void accept (tree_walker& tw) - { - tw.visit_statement_list (*this); - } + void accept (tree_walker& tw) + { + tw.visit_statement_list (*this); + } - private: +private: - // Does this list of statements make up the body of a function? - bool m_function_body; + // Does this list of statements make up the body of a function? + bool m_function_body; - // Does this list of statements make up the body of a function? - bool m_anon_function_body; + // Does this list of statements make up the body of a function? + bool m_anon_function_body; - // Does this list of statements make up the body of a script? - bool m_script_body; - }; + // Does this list of statements make up the body of a script? + bool m_script_body; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-tm-const.cc --- a/libinterp/parse-tree/pt-tm-const.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-tm-const.cc Thu Dec 01 20:05:44 2022 -0800 @@ -60,648 +60,648 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void tm_row_const::cellify (void) - { - bool elt_changed = false; - - for (auto& elt : m_values) - { - octave_quit (); - - if (! elt.iscell ()) - { - elt_changed = true; +void tm_row_const::cellify (void) +{ + bool elt_changed = false; - if (elt.isempty ()) - elt = Cell (); - else - elt = Cell (elt); - } - } + for (auto& elt : m_values) + { + octave_quit (); - if (! elt_changed) - return; - - bool first_elem = true; - - for (const auto& val : m_values) - { - octave_quit (); - - dim_vector this_elt_dv = val.dims (); + if (! elt.iscell ()) + { + elt_changed = true; - if (! this_elt_dv.zero_by_zero ()) - { - if (first_elem) - { - first_elem = false; - m_dv = this_elt_dv; - } - else if (! m_dv.hvcat (this_elt_dv, 1)) - eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv); - } - } - } - - void tm_row_const::init_element (const octave_value& val, bool& first_elem) - { - std::string this_elt_class_name - = val.isobject () ? "class" : val.class_name (); + if (elt.isempty ()) + elt = Cell (); + else + elt = Cell (elt); + } + } - m_class_name = get_concat_class (m_class_name, this_elt_class_name); - - dim_vector this_elt_dv = val.dims (); + if (! elt_changed) + return; - if (! this_elt_dv.zero_by_zero ()) - { - m_all_empty = false; + bool first_elem = true; - if (first_elem) - { - if (val.isstruct ()) - m_first_elem_is_struct = true; + for (const auto& val : m_values) + { + octave_quit (); - first_elem = false; - } - } - else if (val.iscell ()) - first_elem = false; - - m_values.push_back (val); + dim_vector this_elt_dv = val.dims (); - if (m_all_strings && ! val.is_string ()) - m_all_strings = false; - - if (m_all_sq_strings && ! val.is_sq_string ()) - m_all_sq_strings = false; - - if (m_all_dq_strings && ! val.is_dq_string ()) - m_all_dq_strings = false; - - if (! m_some_strings && val.is_string ()) - m_some_strings = true; - - if (m_all_real && ! val.isreal ()) - m_all_real = false; + if (! this_elt_dv.zero_by_zero ()) + { + if (first_elem) + { + first_elem = false; + m_dv = this_elt_dv; + } + else if (! m_dv.hvcat (this_elt_dv, 1)) + eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv); + } + } +} - if (m_all_complex && ! (val.iscomplex () || val.isreal ())) - m_all_complex = false; - - if (! m_any_cell && val.iscell ()) - m_any_cell = true; - - if (! m_any_sparse && val.issparse ()) - m_any_sparse = true; - - if (! m_any_class && val.isobject ()) - m_any_class = true; - - // Special treatment of sparse matrices to avoid out-of-memory error - m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1; - } - - void tm_row_const::init (const tree_argument_list& row, tree_evaluator& tw) - { - bool first_elem = true; +void tm_row_const::init_element (const octave_value& val, bool& first_elem) +{ + std::string this_elt_class_name + = val.isobject () ? "class" : val.class_name (); - for (auto *elt : row) - { - octave_quit (); + m_class_name = get_concat_class (m_class_name, this_elt_class_name); - octave_value tmp = elt->evaluate (tw); + dim_vector this_elt_dv = val.dims (); - if (tmp.is_undefined ()) - error ("undefined element in matrix list"); - - if (tmp.is_cs_list ()) - { - octave_value_list tlst = tmp.list_value (); - - for (octave_idx_type i = 0; i < tlst.length (); i++) - { - octave_quit (); + if (! this_elt_dv.zero_by_zero ()) + { + m_all_empty = false; - init_element (tlst(i), first_elem); - } - } - else - init_element (tmp, first_elem); - } + if (first_elem) + { + if (val.isstruct ()) + m_first_elem_is_struct = true; - if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct) - cellify (); - - first_elem = true; + first_elem = false; + } + } + else if (val.iscell ()) + first_elem = false; - for (const auto& val : m_values) - { - octave_quit (); - - dim_vector this_elt_dv = val.dims (); + m_values.push_back (val); - if (! this_elt_dv.zero_by_zero ()) - { - m_all_empty = false; + if (m_all_strings && ! val.is_string ()) + m_all_strings = false; + + if (m_all_sq_strings && ! val.is_sq_string ()) + m_all_sq_strings = false; - if (first_elem) - { - first_elem = false; - m_dv = this_elt_dv; - } - else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1))) - eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv); - } - } - } + if (m_all_dq_strings && ! val.is_dq_string ()) + m_all_dq_strings = false; - octave_value tm_const::concat (char string_fill_char) const - { - if (m_tm_rows.empty ()) - return Matrix (); + if (! m_some_strings && val.is_string ()) + m_some_strings = true; - // Try to speed up the common cases. - - std::string result_type = m_class_name; + if (m_all_real && ! val.isreal ()) + m_all_real = false; - if (m_any_class) - return class_concat (); - else if (result_type == "double") - { - if (m_any_sparse) - { - if (m_all_real) - return sparse_array_concat (); - else - return sparse_array_concat (); - } - else - { - if (m_all_real) - return array_concat (); - else - return array_concat (); - } - } - else if (result_type == "single") - { - if (m_all_real) - return array_concat (); - else - return array_concat (); - } - else if (result_type == "char") - { - if (! m_all_strings) - warn_implicit_conversion ("Octave:num-to-str", - "numeric", result_type); - else - maybe_warn_string_concat (m_all_dq_strings, m_all_sq_strings); + if (m_all_complex && ! (val.iscomplex () || val.isreal ())) + m_all_complex = false; + + if (! m_any_cell && val.iscell ()) + m_any_cell = true; + + if (! m_any_sparse && val.issparse ()) + m_any_sparse = true; + + if (! m_any_class && val.isobject ()) + m_any_class = true; + + // Special treatment of sparse matrices to avoid out-of-memory error + m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1; +} + +void tm_row_const::init (const tree_argument_list& row, tree_evaluator& tw) +{ + bool first_elem = true; - return char_array_concat (string_fill_char); - } - else if (result_type == "logical") - { - if (m_any_sparse) - return sparse_array_concat (); - else - return array_concat (); - } - else if (result_type == "int8") - return array_concat (); - else if (result_type == "int16") - return array_concat (); - else if (result_type == "int32") - return array_concat (); - else if (result_type == "int64") - return array_concat (); - else if (result_type == "uint8") - return array_concat (); - else if (result_type == "uint16") - return array_concat (); - else if (result_type == "uint32") - return array_concat (); - else if (result_type == "uint64") - return array_concat (); - else if (result_type == "cell") - return array_concat (); - else if (result_type == "struct") - { - if (m_all_1x1) - return map_concat (); - else - return map_concat (); - } - else - return generic_concat (); - } + for (auto *elt : row) + { + octave_quit (); + + octave_value tmp = elt->evaluate (tw); + + if (tmp.is_undefined ()) + error ("undefined element in matrix list"); + + if (tmp.is_cs_list ()) + { + octave_value_list tlst = tmp.list_value (); + + for (octave_idx_type i = 0; i < tlst.length (); i++) + { + octave_quit (); - void tm_const::init (const tree_matrix& tm) - { - bool first_elem = true; - bool first_elem_is_struct = false; - - // Just eval and figure out if what we have is complex or all strings. - // We can't check columns until we know that this is a numeric matrix -- - // collections of strings can have elements of different lengths. + init_element (tlst(i), first_elem); + } + } + else + init_element (tmp, first_elem); + } - for (const auto *elt : tm) - { - octave_quit (); - - tm_row_const row (*elt, m_evaluator); - - if (first_elem) - { - first_elem_is_struct = row.first_elem_struct_p (); - - first_elem = false; - } + if (m_any_cell && ! m_any_class && ! m_first_elem_is_struct) + cellify (); - if (row.empty ()) - continue; - - if (m_all_strings && ! row.all_strings_p ()) - m_all_strings = false; - - if (m_all_sq_strings && ! row.all_sq_strings_p ()) - m_all_sq_strings = false; + first_elem = true; - if (m_all_dq_strings && ! row.all_dq_strings_p ()) - m_all_dq_strings = false; - - if (! m_some_strings && row.some_strings_p ()) - m_some_strings = true; + for (const auto& val : m_values) + { + octave_quit (); - if (m_all_real && ! row.all_real_p ()) - m_all_real = false; + dim_vector this_elt_dv = val.dims (); - if (m_all_complex && ! row.all_complex_p ()) - m_all_complex = false; - - if (m_all_empty && ! row.all_empty_p ()) + if (! this_elt_dv.zero_by_zero ()) + { m_all_empty = false; - if (! m_any_cell && row.any_cell_p ()) - m_any_cell = true; + if (first_elem) + { + first_elem = false; + m_dv = this_elt_dv; + } + else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1))) + eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv); + } + } +} - if (! m_any_sparse && row.any_sparse_p ()) - m_any_sparse = true; +octave_value tm_const::concat (char string_fill_char) const +{ + if (m_tm_rows.empty ()) + return Matrix (); + + // Try to speed up the common cases. + + std::string result_type = m_class_name; - if (! m_any_class && row.any_class_p ()) - m_any_class = true; - - m_all_1x1 = m_all_1x1 && row.all_1x1_p (); - - m_tm_rows.push_back (row); - } + if (m_any_class) + return class_concat (); + else if (result_type == "double") + { + if (m_any_sparse) + { + if (m_all_real) + return sparse_array_concat (); + else + return sparse_array_concat (); + } + else + { + if (m_all_real) + return array_concat (); + else + return array_concat (); + } + } + else if (result_type == "single") + { + if (m_all_real) + return array_concat (); + else + return array_concat (); + } + else if (result_type == "char") + { + if (! m_all_strings) + warn_implicit_conversion ("Octave:num-to-str", + "numeric", result_type); + else + maybe_warn_string_concat (m_all_dq_strings, m_all_sq_strings); - if (m_any_cell && ! m_any_class && ! first_elem_is_struct) - { - for (auto& elt : m_tm_rows) - { - octave_quit (); - - elt.cellify (); - } - } - - first_elem = true; + return char_array_concat (string_fill_char); + } + else if (result_type == "logical") + { + if (m_any_sparse) + return sparse_array_concat (); + else + return array_concat (); + } + else if (result_type == "int8") + return array_concat (); + else if (result_type == "int16") + return array_concat (); + else if (result_type == "int32") + return array_concat (); + else if (result_type == "int64") + return array_concat (); + else if (result_type == "uint8") + return array_concat (); + else if (result_type == "uint16") + return array_concat (); + else if (result_type == "uint32") + return array_concat (); + else if (result_type == "uint64") + return array_concat (); + else if (result_type == "cell") + return array_concat (); + else if (result_type == "struct") + { + if (m_all_1x1) + return map_concat (); + else + return map_concat (); + } + else + return generic_concat (); +} - for (const auto& elt : m_tm_rows) - { - octave_quit (); +void tm_const::init (const tree_matrix& tm) +{ + bool first_elem = true; + bool first_elem_is_struct = false; + + // Just eval and figure out if what we have is complex or all strings. + // We can't check columns until we know that this is a numeric matrix -- + // collections of strings can have elements of different lengths. + + for (const auto *elt : tm) + { + octave_quit (); + + tm_row_const row (*elt, m_evaluator); + + if (first_elem) + { + first_elem_is_struct = row.first_elem_struct_p (); + + first_elem = false; + } - octave_idx_type this_elt_nr = elt.rows (); - octave_idx_type this_elt_nc = elt.cols (); + if (row.empty ()) + continue; + + if (m_all_strings && ! row.all_strings_p ()) + m_all_strings = false; + + if (m_all_sq_strings && ! row.all_sq_strings_p ()) + m_all_sq_strings = false; - std::string this_elt_class_name = elt.class_name (); - m_class_name = get_concat_class (m_class_name, this_elt_class_name); + if (m_all_dq_strings && ! row.all_dq_strings_p ()) + m_all_dq_strings = false; + + if (! m_some_strings && row.some_strings_p ()) + m_some_strings = true; - dim_vector this_elt_dv = elt.dims (); + if (m_all_real && ! row.all_real_p ()) + m_all_real = false; + if (m_all_complex && ! row.all_complex_p ()) + m_all_complex = false; + + if (m_all_empty && ! row.all_empty_p ()) m_all_empty = false; - if (first_elem) - { - first_elem = false; + if (! m_any_cell && row.any_cell_p ()) + m_any_cell = true; + + if (! m_any_sparse && row.any_sparse_p ()) + m_any_sparse = true; + + if (! m_any_class && row.any_class_p ()) + m_any_class = true; + + m_all_1x1 = m_all_1x1 && row.all_1x1_p (); + + m_tm_rows.push_back (row); + } + + if (m_any_cell && ! m_any_class && ! first_elem_is_struct) + { + for (auto& elt : m_tm_rows) + { + octave_quit (); - m_dv = this_elt_dv; - } - else if (m_all_strings && m_dv.ndims () == 2 - && this_elt_dv.ndims () == 2) - { - // This is Octave's specialty. - // Character matrices support rows of unequal length. - if (m_dv.any_zero ()) - { - // Empty existing element (bug #52542). - // Replace empty element with non-empty one. - m_dv = this_elt_dv; - } - else - { - if (this_elt_nc > cols ()) - m_dv(1) = this_elt_nc; - m_dv(0) += this_elt_nr; - } - } - else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0))) - eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv); - } - } + elt.cellify (); + } + } + + first_elem = true; + + for (const auto& elt : m_tm_rows) + { + octave_quit (); - octave_value tm_const::char_array_concat (char string_fill_char) const - { - char type = (m_all_dq_strings ? '"' : '\''); + octave_idx_type this_elt_nr = elt.rows (); + octave_idx_type this_elt_nc = elt.cols (); - charNDArray result (m_dv, string_fill_char); + std::string this_elt_class_name = elt.class_name (); + m_class_name = get_concat_class (m_class_name, this_elt_class_name); + + dim_vector this_elt_dv = elt.dims (); + + m_all_empty = false; - array_concat_internal (result); - - return octave_value (result, type); - } - - octave_value tm_const::class_concat (void) const - { - octave_value retval; - - octave_value_list rows (m_tm_rows.size (), octave_value ()); - - octave_idx_type j = 0; - for (const auto& tmrc : m_tm_rows) - { - octave_quit (); + if (first_elem) + { + first_elem = false; - if (tmrc.length () == 1) - rows(j++) = *(tmrc.begin ()); - else - { - octave_value_list row (tmrc.length (), octave_value ()); - - octave_idx_type i = 0; - for (const auto& elt : tmrc) - row(i++) = elt; + m_dv = this_elt_dv; + } + else if (m_all_strings && m_dv.ndims () == 2 + && this_elt_dv.ndims () == 2) + { + // This is Octave's specialty. + // Character matrices support rows of unequal length. + if (m_dv.any_zero ()) + { + // Empty existing element (bug #52542). + // Replace empty element with non-empty one. + m_dv = this_elt_dv; + } + else + { + if (this_elt_nc > cols ()) + m_dv(1) = this_elt_nc; + m_dv(0) += this_elt_nr; + } + } + else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0))) + eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv); + } +} - rows(j++) = do_class_concat (row, "horzcat", 1); - } - } +octave_value tm_const::char_array_concat (char string_fill_char) const +{ + char type = (m_all_dq_strings ? '"' : '\''); + + charNDArray result (m_dv, string_fill_char); + + array_concat_internal (result); - if (rows.length () == 1) - retval = rows(0); - else - retval = do_class_concat (rows, "vertcat", 0); + return octave_value (result, type); +} - return retval; - } +octave_value tm_const::class_concat (void) const +{ + octave_value retval; + + octave_value_list rows (m_tm_rows.size (), octave_value ()); - octave_value tm_const::generic_concat (void) const - { - // The line below might seem crazy, since we take a copy of the - // first argument, resize it to be empty and then resize it to be - // full. This is done since it means that there is no recopying of - // data, as would happen if we used a single resize. It should be - // noted that resize operation is also significantly slower than the - // cat_op function, so it makes sense to have an empty matrix and - // copy all data. - // - // We might also start with a empty octave_value using - // - // ctmp = type_info::lookup_type (tmp.begin() -> begin() -> type_name()); - // - // and then directly resize. However, for some types there might be - // some additional setup needed, and so this should be avoided. + octave_idx_type j = 0; + for (const auto& tmrc : m_tm_rows) + { + octave_quit (); - octave_value ctmp; + if (tmrc.length () == 1) + rows(j++) = *(tmrc.begin ()); + else + { + octave_value_list row (tmrc.length (), octave_value ()); - // Find the first non-empty object + octave_idx_type i = 0; + for (const auto& elt : tmrc) + row(i++) = elt; + + rows(j++) = do_class_concat (row, "horzcat", 1); + } + } - if (m_any_sparse) - { - // Start with sparse matrix to avoid issues memory issues with - // things like [ones(1,4),sprandn(1e8,4,1e-4)] + if (rows.length () == 1) + retval = rows(0); + else + retval = do_class_concat (rows, "vertcat", 0); + + return retval; +} - if (m_all_real) - ctmp = octave_sparse_matrix ().resize (m_dv); - else - ctmp = octave_sparse_complex_matrix ().resize (m_dv); - } - else - { - for (const auto& row : m_tm_rows) - { - octave_quit (); +octave_value tm_const::generic_concat (void) const +{ + // The line below might seem crazy, since we take a copy of the + // first argument, resize it to be empty and then resize it to be + // full. This is done since it means that there is no recopying of + // data, as would happen if we used a single resize. It should be + // noted that resize operation is also significantly slower than the + // cat_op function, so it makes sense to have an empty matrix and + // copy all data. + // + // We might also start with a empty octave_value using + // + // ctmp = type_info::lookup_type (tmp.begin() -> begin() -> type_name()); + // + // and then directly resize. However, for some types there might be + // some additional setup needed, and so this should be avoided. - for (const auto& elt : row) - { - octave_quit (); - - ctmp = elt; + octave_value ctmp; - if (! ctmp.all_zero_dims ()) - goto found_non_empty; - } - } + // Find the first non-empty object - ctmp = (*(m_tm_rows.begin () -> begin ())); - - found_non_empty: + if (m_any_sparse) + { + // Start with sparse matrix to avoid issues memory issues with + // things like [ones(1,4),sprandn(1e8,4,1e-4)] - if (! m_all_empty) - ctmp = ctmp.resize (dim_vector (0, 0)).resize (m_dv); - } + if (m_all_real) + ctmp = octave_sparse_matrix ().resize (m_dv); + else + ctmp = octave_sparse_complex_matrix ().resize (m_dv); + } + else + { + for (const auto& row : m_tm_rows) + { + octave_quit (); - // Now, extract the values from the individual elements and insert - // them in the result matrix. + for (const auto& elt : row) + { + octave_quit (); - interpreter& interp = m_evaluator.get_interpreter (); - - type_info& ti = interp.get_type_info (); + ctmp = elt; - int dv_len = m_dv.ndims (); - octave_idx_type ntmp = (dv_len > 1 ? dv_len : 2); - Array ra_idx (dim_vector (ntmp, 1), 0); + if (! ctmp.all_zero_dims ()) + goto found_non_empty; + } + } - for (const auto& row : m_tm_rows) - { - octave_quit (); + ctmp = (*(m_tm_rows.begin () -> begin ())); - for (const auto& elt : row) - { - octave_quit (); + found_non_empty: - if (elt.isempty ()) - continue; + if (! m_all_empty) + ctmp = ctmp.resize (dim_vector (0, 0)).resize (m_dv); + } - ctmp = cat_op (ti, ctmp, elt, ra_idx); + // Now, extract the values from the individual elements and insert + // them in the result matrix. - ra_idx (1) += elt.columns (); - } + interpreter& interp = m_evaluator.get_interpreter (); + + type_info& ti = interp.get_type_info (); - ra_idx (0) += row.rows (); - ra_idx (1) = 0; - } + int dv_len = m_dv.ndims (); + octave_idx_type ntmp = (dv_len > 1 ? dv_len : 2); + Array ra_idx (dim_vector (ntmp, 1), 0); - octave_value retval = ctmp; + for (const auto& row : m_tm_rows) + { + octave_quit (); - // If some elements are strings, force the result to be a string. - - if (m_some_strings && ! retval.is_string ()) - retval = retval.convert_to_str (); + for (const auto& elt : row) + { + octave_quit (); - return retval; - } + if (elt.isempty ()) + continue; - // The result is passed as a parameter to this function so that the - // char_array_concat function can create the array externally. - // Otherwise, we would need a specialization of this function for - // character arrays just to handle string_fill_char. + ctmp = cat_op (ti, ctmp, elt, ra_idx); + + ra_idx (1) += elt.columns (); + } - template - void tm_const::array_concat_internal (TYPE& result) const - { - octave_idx_type r = 0; - octave_idx_type c = 0; + ra_idx (0) += row.rows (); + ra_idx (1) = 0; + } - for (const auto& row : m_tm_rows) - { - // Skip empty arrays to allow looser rules. - if (row.dims ().any_zero ()) - continue; + octave_value retval = ctmp; + + // If some elements are strings, force the result to be a string. - for (const auto& elt : row) - { - octave_quit (); - - TYPE ra = octave_value_extract (elt); + if (m_some_strings && ! retval.is_string ()) + retval = retval.convert_to_str (); - // Skip empty arrays to allow looser rules. + return retval; +} - if (! ra.isempty ()) - { - result.insert (ra, r, c); +// The result is passed as a parameter to this function so that the +// char_array_concat function can create the array externally. +// Otherwise, we would need a specialization of this function for +// character arrays just to handle string_fill_char. - c += ra.columns (); - } - } +template +void tm_const::array_concat_internal (TYPE& result) const +{ + octave_idx_type r = 0; + octave_idx_type c = 0; - r += row.rows (); - c = 0; - } - } + for (const auto& row : m_tm_rows) + { + // Skip empty arrays to allow looser rules. + if (row.dims ().any_zero ()) + continue; - template - TYPE tm_const::array_concat (void) const - { - typedef typename TYPE::element_type ELT_T; + for (const auto& elt : row) + { + octave_quit (); - if (m_dv.any_zero ()) - return TYPE (m_dv); + TYPE ra = octave_value_extract (elt); + + // Skip empty arrays to allow looser rules. - if (m_tm_rows.size () == 1) - { - // If possible, forward the operation to liboctave. - // Single row. - const tm_row_const& row = m_tm_rows.front (); - if (! (equal_types::value - || equal_types::value) - && row.all_1x1_p ()) - { - // Optimize all scalars case. - TYPE result (m_dv); - panic_unless (static_cast (result.numel ()) - == row.length ()); - octave_idx_type i = 0; - for (const auto& elt : row) - result(i++) = octave_value_extract (elt); + if (! ra.isempty ()) + { + result.insert (ra, r, c); + + c += ra.columns (); + } + } - return result; - } + r += row.rows (); + c = 0; + } +} - octave_idx_type ncols = row.length (); - octave_idx_type i = 0; - OCTAVE_LOCAL_BUFFER (TYPE, array_list, ncols); +template +TYPE tm_const::array_concat (void) const +{ + typedef typename TYPE::element_type ELT_T; + + if (m_dv.any_zero ()) + return TYPE (m_dv); - for (const auto& elt : row) - { - octave_quit (); - - array_list[i++] = octave_value_extract (elt); - } + if (m_tm_rows.size () == 1) + { + // If possible, forward the operation to liboctave. + // Single row. + const tm_row_const& row = m_tm_rows.front (); + if (! (equal_types::value + || equal_types::value) + && row.all_1x1_p ()) + { + // Optimize all scalars case. + TYPE result (m_dv); + panic_unless (static_cast (result.numel ()) + == row.length ()); + octave_idx_type i = 0; + for (const auto& elt : row) + result(i++) = octave_value_extract (elt); - return TYPE::cat (-2, ncols, array_list); - } - else - { - TYPE result (m_dv); - array_concat_internal (result); - return result; - } - } + return result; + } - template - TYPE tm_const::sparse_array_concat (void) const - { - if (m_dv.any_zero ()) - return TYPE (m_dv); + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; + OCTAVE_LOCAL_BUFFER (TYPE, array_list, ncols); + + for (const auto& elt : row) + { + octave_quit (); + + array_list[i++] = octave_value_extract (elt); + } - // Sparse matrices require preallocation for efficient indexing; besides, - // only horizontal concatenation can be efficiently handled by indexing. - // So we just cat all rows through liboctave, then cat the final column. - octave_idx_type nrows = m_tm_rows.size (); - octave_idx_type j = 0; - OCTAVE_LOCAL_BUFFER (TYPE, sparse_row_list, nrows); - for (const auto& row : m_tm_rows) - { - octave_idx_type ncols = row.length (); - octave_idx_type i = 0; - OCTAVE_LOCAL_BUFFER (TYPE, sparse_list, ncols); + return TYPE::cat (-2, ncols, array_list); + } + else + { + TYPE result (m_dv); + array_concat_internal (result); + return result; + } +} - for (auto& elt : row) - { - octave_quit (); +template +TYPE tm_const::sparse_array_concat (void) const +{ + if (m_dv.any_zero ()) + return TYPE (m_dv); - sparse_list[i] = octave_value_extract (elt); - i++; - } - - TYPE stmp = TYPE::cat (-2, ncols, sparse_list); - sparse_row_list[j] = stmp; - j++; - } + // Sparse matrices require preallocation for efficient indexing; besides, + // only horizontal concatenation can be efficiently handled by indexing. + // So we just cat all rows through liboctave, then cat the final column. + octave_idx_type nrows = m_tm_rows.size (); + octave_idx_type j = 0; + OCTAVE_LOCAL_BUFFER (TYPE, sparse_row_list, nrows); + for (const auto& row : m_tm_rows) + { + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; + OCTAVE_LOCAL_BUFFER (TYPE, sparse_list, ncols); - return TYPE::cat (-1, nrows, sparse_row_list); - } + for (auto& elt : row) + { + octave_quit (); + + sparse_list[i] = octave_value_extract (elt); + i++; + } - template - octave_map tm_const::map_concat (void) const - { - if (m_dv.any_zero ()) - return octave_map (m_dv); + TYPE stmp = TYPE::cat (-2, ncols, sparse_list); + sparse_row_list[j] = stmp; + j++; + } + + return TYPE::cat (-1, nrows, sparse_row_list); +} - octave_idx_type nrows = m_tm_rows.size (); - octave_idx_type j = 0; - OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows); - for (const auto& row : m_tm_rows) - { - octave_idx_type ncols = row.length (); - octave_idx_type i = 0; - OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols); +template +octave_map tm_const::map_concat (void) const +{ + if (m_dv.any_zero ()) + return octave_map (m_dv); + + octave_idx_type nrows = m_tm_rows.size (); + octave_idx_type j = 0; + OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows); + for (const auto& row : m_tm_rows) + { + octave_idx_type ncols = row.length (); + octave_idx_type i = 0; + OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols); - for (auto& elt : row) - { - octave_quit (); + for (auto& elt : row) + { + octave_quit (); - map_list[i] = octave_value_extract (elt); - i++; - } + map_list[i] = octave_value_extract (elt); + i++; + } - octave_map mtmp = octave_map::cat (-2, ncols, map_list); - map_row_list[j] = mtmp; - j++; - } + octave_map mtmp = octave_map::cat (-2, ncols, map_list); + map_row_list[j] = mtmp; + j++; + } - return octave_map::cat (-1, nrows, map_row_list); - } + return octave_map::cat (-1, nrows, map_row_list); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-tm-const.h --- a/libinterp/parse-tree/pt-tm-const.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-tm-const.h Thu Dec 01 20:05:44 2022 -0800 @@ -45,200 +45,200 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; +class tree_evaluator; - // Evaluate tree_matrix objects and convert them to octave_value - // arrays (full and sparse numeric, char, cell, struct, class and - // anything else that works like an array). Use a separate class - // (tm_const) and pass the evaluator object to it instead of doing - // all this work in tree_evaluator::visit_matrix because the job is - // fairly large and requires extra data (stored in the tm_info - // class) for each row and for the overall array. +// Evaluate tree_matrix objects and convert them to octave_value +// arrays (full and sparse numeric, char, cell, struct, class and +// anything else that works like an array). Use a separate class +// (tm_const) and pass the evaluator object to it instead of doing +// all this work in tree_evaluator::visit_matrix because the job is +// fairly large and requires extra data (stored in the tm_info +// class) for each row and for the overall array. - // Evaluate all elements of the array, recording info about each - // row, then create summary info for the full array. Compute the - // result type and dimension first before copying values. +// Evaluate all elements of the array, recording info about each +// row, then create summary info for the full array. Compute the +// result type and dimension first before copying values. - // FIXME: Handle overloading of horzcat and vertcat for for built-in - // types. +// FIXME: Handle overloading of horzcat and vertcat for for built-in +// types. - // Summary info about the current row or matrix. +// Summary info about the current row or matrix. - class tm_info - { - public: +class tm_info +{ +public: - tm_info (bool obj_is_empty) - : m_dv (0, 0), m_all_strings (true), m_all_sq_strings (true), - m_all_dq_strings (true), m_some_strings (false), - m_all_real (true), m_all_complex (true), m_all_empty (true), - m_any_cell (false), m_any_sparse (false), - m_any_class (false), m_all_1x1 (! obj_is_empty), - m_first_elem_is_struct (false), m_class_name () - { } + tm_info (bool obj_is_empty) + : m_dv (0, 0), m_all_strings (true), m_all_sq_strings (true), + m_all_dq_strings (true), m_some_strings (false), + m_all_real (true), m_all_complex (true), m_all_empty (true), + m_any_cell (false), m_any_sparse (false), + m_any_class (false), m_all_1x1 (! obj_is_empty), + m_first_elem_is_struct (false), m_class_name () + { } - dim_vector dims (void) const { return m_dv; } + dim_vector dims (void) const { return m_dv; } - octave_idx_type rows (void) const { return m_dv(0); } - octave_idx_type cols (void) const { return m_dv(1); } + octave_idx_type rows (void) const { return m_dv(0); } + octave_idx_type cols (void) const { return m_dv(1); } - bool all_strings_p (void) const { return m_all_strings; } - bool all_sq_strings_p (void) const { return m_all_sq_strings; } - bool all_dq_strings_p (void) const { return m_all_dq_strings; } - bool some_strings_p (void) const { return m_some_strings; } - bool all_real_p (void) const { return m_all_real; } - bool all_complex_p (void) const { return m_all_complex; } - bool all_empty_p (void) const { return m_all_empty; } - bool any_cell_p (void) const { return m_any_cell; } - bool any_sparse_p (void) const { return m_any_sparse; } - bool any_class_p (void) const { return m_any_class; } - bool all_1x1_p (void) const { return m_all_1x1; } - bool first_elem_struct_p (void) const { return m_first_elem_is_struct; } + bool all_strings_p (void) const { return m_all_strings; } + bool all_sq_strings_p (void) const { return m_all_sq_strings; } + bool all_dq_strings_p (void) const { return m_all_dq_strings; } + bool some_strings_p (void) const { return m_some_strings; } + bool all_real_p (void) const { return m_all_real; } + bool all_complex_p (void) const { return m_all_complex; } + bool all_empty_p (void) const { return m_all_empty; } + bool any_cell_p (void) const { return m_any_cell; } + bool any_sparse_p (void) const { return m_any_sparse; } + bool any_class_p (void) const { return m_any_class; } + bool all_1x1_p (void) const { return m_all_1x1; } + bool first_elem_struct_p (void) const { return m_first_elem_is_struct; } - std::string class_name (void) const { return m_class_name; } + std::string class_name (void) const { return m_class_name; } - protected: +protected: - // Size of this row or matrix after evaluation. - dim_vector m_dv; + // Size of this row or matrix after evaluation. + dim_vector m_dv; - // Are all elements character strings? - bool m_all_strings; + // Are all elements character strings? + bool m_all_strings; - // Are all elements double-quoted character strings? - bool m_all_sq_strings; + // Are all elements double-quoted character strings? + bool m_all_sq_strings; - // Are all elements single-quoted character strings? - bool m_all_dq_strings; + // Are all elements single-quoted character strings? + bool m_all_dq_strings; - // Are any elements character strings? - bool m_some_strings; + // Are any elements character strings? + bool m_some_strings; - // Are all elements real valued? - bool m_all_real; + // Are all elements real valued? + bool m_all_real; - // Are all elements complex valued? - bool m_all_complex; + // Are all elements complex valued? + bool m_all_complex; - // Are all elements empty? - bool m_all_empty; + // Are all elements empty? + bool m_all_empty; - // Are any elements cells? - bool m_any_cell; + // Are any elements cells? + bool m_any_cell; - // Are any elements sparse arrays? - bool m_any_sparse; + // Are any elements sparse arrays? + bool m_any_sparse; - // Are any elements sparse class objects? - bool m_any_class; + // Are any elements sparse class objects? + bool m_any_class; - // Do all elements have dimensions 1x1? - bool m_all_1x1; + // Do all elements have dimensions 1x1? + bool m_all_1x1; - // Is the first element a struct? - bool m_first_elem_is_struct; + // Is the first element a struct? + bool m_first_elem_is_struct; - // Class name of result. - std::string m_class_name; - }; + // Class name of result. + std::string m_class_name; +}; - class tm_row_const : public tm_info - { - public: +class tm_row_const : public tm_info +{ +public: - typedef std::list::iterator iterator; - typedef std::list::const_iterator const_iterator; + typedef std::list::iterator iterator; + typedef std::list::const_iterator const_iterator; - tm_row_const (void) = delete; + tm_row_const (void) = delete; - tm_row_const (const tree_argument_list& row, tree_evaluator& tw) - : tm_info (row.empty ()), m_values () - { - init (row, tw); - } + tm_row_const (const tree_argument_list& row, tree_evaluator& tw) + : tm_info (row.empty ()), m_values () + { + init (row, tw); + } - tm_row_const (const tm_row_const&) = default; + tm_row_const (const tm_row_const&) = default; - tm_row_const& operator = (const tm_row_const&) = delete; + tm_row_const& operator = (const tm_row_const&) = delete; - ~tm_row_const (void) = default; + ~tm_row_const (void) = default; - iterator begin (void) { return m_values.begin (); } - const_iterator begin (void) const { return m_values.begin (); } + iterator begin (void) { return m_values.begin (); } + const_iterator begin (void) const { return m_values.begin (); } - iterator end (void) { return m_values.end (); } - const_iterator end (void) const { return m_values.end (); } + iterator end (void) { return m_values.end (); } + const_iterator end (void) const { return m_values.end (); } - bool empty (void) const { return m_values.empty (); } + bool empty (void) const { return m_values.empty (); } - std::size_t length (void) const { return m_values.size (); } + std::size_t length (void) const { return m_values.size (); } - void cellify (void); + void cellify (void); - private: +private: - std::list m_values; + std::list m_values; - void init_element (const octave_value&, bool&); + void init_element (const octave_value&, bool&); - void init (const tree_argument_list&, tree_evaluator& tw); - }; + void init (const tree_argument_list&, tree_evaluator& tw); +}; - class tm_const : public tm_info - { - public: +class tm_const : public tm_info +{ +public: - typedef std::list::iterator iterator; - typedef std::list::const_iterator const_iterator; + typedef std::list::iterator iterator; + typedef std::list::const_iterator const_iterator; - tm_const (void) = delete; + tm_const (void) = delete; - tm_const (const tree_matrix& tm, tree_evaluator& tw) - : tm_info (tm.empty ()), m_evaluator (tw), m_tm_rows () - { - init (tm); - } + tm_const (const tree_matrix& tm, tree_evaluator& tw) + : tm_info (tm.empty ()), m_evaluator (tw), m_tm_rows () + { + init (tm); + } - // No copying! + // No copying! - tm_const (const tm_const&) = delete; + tm_const (const tm_const&) = delete; - tm_const& operator = (const tm_const&) = delete; + tm_const& operator = (const tm_const&) = delete; - ~tm_const (void) = default; + ~tm_const (void) = default; - octave_value concat (char string_fill_char) const; + octave_value concat (char string_fill_char) const; - private: +private: - tree_evaluator& m_evaluator; + tree_evaluator& m_evaluator; - // The list of lists of octave_value objects that contain the - // values of elements in each row of the tree_matrix object we are - // evaluating. + // The list of lists of octave_value objects that contain the + // values of elements in each row of the tree_matrix object we are + // evaluating. - std::list m_tm_rows; + std::list m_tm_rows; - void init (const tree_matrix& tm); + void init (const tree_matrix& tm); - octave_value char_array_concat (char string_fill_char) const; + octave_value char_array_concat (char string_fill_char) const; - octave_value class_concat (void) const; + octave_value class_concat (void) const; - octave_value generic_concat (void) const; + octave_value generic_concat (void) const; - template - void array_concat_internal (TYPE& result) const; + template + void array_concat_internal (TYPE& result) const; - template - TYPE array_concat (void) const; + template + TYPE array_concat (void) const; - template - TYPE sparse_array_concat (void) const; + template + TYPE sparse_array_concat (void) const; - template - octave_map map_concat (void) const; - }; + template + octave_map map_concat (void) const; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-unop.cc --- a/libinterp/parse-tree/pt-unop.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-unop.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,127 +34,127 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Unary expressions. +// Unary expressions. - std::string - tree_unary_expression::oper (void) const - { - return octave_value::unary_op_as_string (m_etype); - } +std::string +tree_unary_expression::oper (void) const +{ + return octave_value::unary_op_as_string (m_etype); +} + +// Prefix expressions. - // Prefix expressions. +tree_expression * +tree_prefix_expression::dup (symbol_scope& scope) const +{ + tree_prefix_expression *new_pe + = new tree_prefix_expression (m_op ? m_op->dup (scope) : nullptr, + line (), column (), m_etype); - tree_expression * - tree_prefix_expression::dup (symbol_scope& scope) const - { - tree_prefix_expression *new_pe - = new tree_prefix_expression (m_op ? m_op->dup (scope) : nullptr, - line (), column (), m_etype); + new_pe->copy_base (*this); + + return new_pe; +} - new_pe->copy_base (*this); +octave_value +tree_prefix_expression::evaluate (tree_evaluator& tw, int) +{ + octave_value val; - return new_pe; - } + if (m_op) + { + if (m_etype == octave_value::op_incr + || m_etype == octave_value::op_decr) + { + octave_lvalue op_ref = m_op->lvalue (tw); - octave_value - tree_prefix_expression::evaluate (tree_evaluator& tw, int) - { - octave_value val; + profiler::enter + block (tw.get_profiler (), *this); + + op_ref.unary_op (m_etype); - if (m_op) - { - if (m_etype == octave_value::op_incr - || m_etype == octave_value::op_decr) - { - octave_lvalue op_ref = m_op->lvalue (tw); + val = op_ref.value (); + } + else + { + octave_value op_val = m_op->evaluate (tw); - profiler::enter + if (op_val.is_defined ()) + { + profiler::enter block (tw.get_profiler (), *this); - op_ref.unary_op (m_etype); + // Attempt to do the operation in-place if it is unshared + // (a temporary expression). + if (op_val.get_count () == 1) + val = op_val.non_const_unary_op (m_etype); + else + { + interpreter& interp = tw.get_interpreter (); - val = op_ref.value (); - } - else - { - octave_value op_val = m_op->evaluate (tw); - - if (op_val.is_defined ()) - { - profiler::enter - block (tw.get_profiler (), *this); + type_info& ti = interp.get_type_info (); - // Attempt to do the operation in-place if it is unshared - // (a temporary expression). - if (op_val.get_count () == 1) - val = op_val.non_const_unary_op (m_etype); - else - { - interpreter& interp = tw.get_interpreter (); + val = unary_op (ti, m_etype, op_val); + } + } + } + } + + return val; +} - type_info& ti = interp.get_type_info (); +// Postfix expressions. - val = unary_op (ti, m_etype, op_val); - } - } - } - } +tree_expression * +tree_postfix_expression::dup (symbol_scope& scope) const +{ + tree_postfix_expression *new_pe + = new tree_postfix_expression (m_op ? m_op->dup (scope) : nullptr, + line (), column (), m_etype); + + new_pe->copy_base (*this); - return val; - } - - // Postfix expressions. + return new_pe; +} - tree_expression * - tree_postfix_expression::dup (symbol_scope& scope) const - { - tree_postfix_expression *new_pe - = new tree_postfix_expression (m_op ? m_op->dup (scope) : nullptr, - line (), column (), m_etype); +octave_value +tree_postfix_expression::evaluate (tree_evaluator& tw, int) +{ + octave_value val; - new_pe->copy_base (*this); + if (m_op) + { + if (m_etype == octave_value::op_incr + || m_etype == octave_value::op_decr) + { + octave_lvalue ref = m_op->lvalue (tw); - return new_pe; - } + val = ref.value (); - octave_value - tree_postfix_expression::evaluate (tree_evaluator& tw, int) - { - octave_value val; + profiler::enter + block (tw.get_profiler (), *this); - if (m_op) - { - if (m_etype == octave_value::op_incr - || m_etype == octave_value::op_decr) - { - octave_lvalue ref = m_op->lvalue (tw); + ref.unary_op (m_etype); + } + else + { + octave_value op_val = m_op->evaluate (tw); - val = ref.value (); - - profiler::enter + if (op_val.is_defined ()) + { + profiler::enter block (tw.get_profiler (), *this); - ref.unary_op (m_etype); - } - else - { - octave_value op_val = m_op->evaluate (tw); + interpreter& interp = tw.get_interpreter (); - if (op_val.is_defined ()) - { - profiler::enter - block (tw.get_profiler (), *this); + type_info& ti = interp.get_type_info (); - interpreter& interp = tw.get_interpreter (); - - type_info& ti = interp.get_type_info (); + val = unary_op (ti, m_etype, op_val); + } + } + } - val = unary_op (ti, m_etype, op_val); - } - } - } - - return val; - } + return val; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-unop.h --- a/libinterp/parse-tree/pt-unop.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-unop.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,132 +39,132 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class symbol_scope; +class symbol_scope; + +// Unary expressions. + +class tree_unary_expression : public tree_expression +{ +protected: + + tree_unary_expression (int l = -1, int c = -1, + octave_value::unary_op t + = octave_value::unknown_unary_op) + : tree_expression (l, c), m_op (nullptr), m_etype (t) { } + + tree_unary_expression (tree_expression *e, int l = -1, int c = -1, + octave_value::unary_op t + = octave_value::unknown_unary_op) + : tree_expression (l, c), m_op (e), m_etype (t) { } + +public: + + // No copying! + + tree_unary_expression (const tree_unary_expression&) = delete; + + tree_unary_expression& operator = (const tree_unary_expression&) = delete; + + ~tree_unary_expression (void) { delete m_op; } + + bool is_unary_expression (void) const { return true; } + + tree_expression * operand (void) { return m_op; } + + std::string oper (void) const; + + octave_value::unary_op op_type (void) const { return m_etype; } - // Unary expressions. +protected: + + // The operand for the expression. + tree_expression *m_op; + + // The type of the expression. + octave_value::unary_op m_etype; +}; + +// Prefix expressions. + +class tree_prefix_expression : public tree_unary_expression +{ +public: + + tree_prefix_expression (int l = -1, int c = -1) + : tree_unary_expression (l, c, octave_value::unknown_unary_op) { } - class tree_unary_expression : public tree_expression + tree_prefix_expression (tree_expression *e, int l = -1, int c = -1, + octave_value::unary_op t + = octave_value::unknown_unary_op) + : tree_unary_expression (e, l, c, t) { } + + // No copying! + + tree_prefix_expression (const tree_prefix_expression&) = delete; + + tree_prefix_expression& operator = (const tree_prefix_expression&) = delete; + + ~tree_prefix_expression (void) = default; + + bool rvalue_ok (void) const { return true; } + + tree_expression * dup (symbol_scope& scope) const; + + octave_value evaluate (tree_evaluator&, int nargout = 1); + + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) { - protected: + return ovl (evaluate (tw, nargout)); + } + + void accept (tree_walker& tw) + { + tw.visit_prefix_expression (*this); + } + + std::string profiler_name (void) const { return "prefix " + oper (); } +}; - tree_unary_expression (int l = -1, int c = -1, - octave_value::unary_op t - = octave_value::unknown_unary_op) - : tree_expression (l, c), m_op (nullptr), m_etype (t) { } +// Postfix expressions. - tree_unary_expression (tree_expression *e, int l = -1, int c = -1, +class tree_postfix_expression : public tree_unary_expression +{ +public: + + tree_postfix_expression (int l = -1, int c = -1) + : tree_unary_expression (l, c, octave_value::unknown_unary_op) { } + + tree_postfix_expression (tree_expression *e, int l = -1, int c = -1, octave_value::unary_op t = octave_value::unknown_unary_op) - : tree_expression (l, c), m_op (e), m_etype (t) { } - - public: - - // No copying! - - tree_unary_expression (const tree_unary_expression&) = delete; - - tree_unary_expression& operator = (const tree_unary_expression&) = delete; - - ~tree_unary_expression (void) { delete m_op; } + : tree_unary_expression (e, l, c, t) { } - bool is_unary_expression (void) const { return true; } - - tree_expression * operand (void) { return m_op; } - - std::string oper (void) const; + // No copying! - octave_value::unary_op op_type (void) const { return m_etype; } - - protected: - - // The operand for the expression. - tree_expression *m_op; + tree_postfix_expression (const tree_postfix_expression&) = delete; - // The type of the expression. - octave_value::unary_op m_etype; - }; - - // Prefix expressions. + tree_postfix_expression& operator = (const tree_postfix_expression&) = delete; - class tree_prefix_expression : public tree_unary_expression - { - public: - - tree_prefix_expression (int l = -1, int c = -1) - : tree_unary_expression (l, c, octave_value::unknown_unary_op) { } + ~tree_postfix_expression (void) = default; - tree_prefix_expression (tree_expression *e, int l = -1, int c = -1, - octave_value::unary_op t - = octave_value::unknown_unary_op) - : tree_unary_expression (e, l, c, t) { } - - // No copying! + bool rvalue_ok (void) const { return true; } - tree_prefix_expression (const tree_prefix_expression&) = delete; - - tree_prefix_expression& operator = (const tree_prefix_expression&) = delete; - - ~tree_prefix_expression (void) = default; - - bool rvalue_ok (void) const { return true; } - - tree_expression * dup (symbol_scope& scope) const; + tree_expression * dup (symbol_scope& scope) const; - octave_value evaluate (tree_evaluator&, int nargout = 1); - - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } - - void accept (tree_walker& tw) - { - tw.visit_prefix_expression (*this); - } + octave_value evaluate (tree_evaluator&, int nargout = 1); - std::string profiler_name (void) const { return "prefix " + oper (); } - }; - - // Postfix expressions. - - class tree_postfix_expression : public tree_unary_expression + octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) { - public: - - tree_postfix_expression (int l = -1, int c = -1) - : tree_unary_expression (l, c, octave_value::unknown_unary_op) { } + return ovl (evaluate (tw, nargout)); + } - tree_postfix_expression (tree_expression *e, int l = -1, int c = -1, - octave_value::unary_op t - = octave_value::unknown_unary_op) - : tree_unary_expression (e, l, c, t) { } - - // No copying! - - tree_postfix_expression (const tree_postfix_expression&) = delete; - - tree_postfix_expression& operator = (const tree_postfix_expression&) = delete; - - ~tree_postfix_expression (void) = default; - - bool rvalue_ok (void) const { return true; } + void accept (tree_walker& tw) + { + tw.visit_postfix_expression (*this); + } - tree_expression * dup (symbol_scope& scope) const; - - octave_value evaluate (tree_evaluator&, int nargout = 1); - - octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) - { - return ovl (evaluate (tw, nargout)); - } - - void accept (tree_walker& tw) - { - tw.visit_postfix_expression (*this); - } - - std::string profiler_name (void) const { return "postfix " + oper (); } - }; + std::string profiler_name (void) const { return "postfix " + oper (); } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-walk.cc --- a/libinterp/parse-tree/pt-walk.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-walk.cc Thu Dec 01 20:05:44 2022 -0800 @@ -31,759 +31,759 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void tree_walker::visit_anon_fcn_handle (tree_anon_fcn_handle& afh) - { - tree_parameter_list *parameter_list = afh.parameter_list (); +void tree_walker::visit_anon_fcn_handle (tree_anon_fcn_handle& afh) +{ + tree_parameter_list *parameter_list = afh.parameter_list (); - if (parameter_list) - parameter_list->accept (*this); + if (parameter_list) + parameter_list->accept (*this); - tree_expression *expression = afh.expression (); + tree_expression *expression = afh.expression (); - if (expression) - expression->accept (*this); - } + if (expression) + expression->accept (*this); +} - void tree_walker::visit_argument_list (tree_argument_list& lst) - { - auto p = lst.begin (); +void tree_walker::visit_argument_list (tree_argument_list& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_expression *elt = *p++; + while (p != lst.end ()) + { + tree_expression *elt = *p++; - if (elt) - elt->accept (*this); - } - } + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_arguments_block (tree_arguments_block& blk) - { - tree_args_block_attribute_list *attribute_list = blk.attribute_list (); +void tree_walker::visit_arguments_block (tree_arguments_block& blk) +{ + tree_args_block_attribute_list *attribute_list = blk.attribute_list (); - if (attribute_list) - attribute_list->accept (*this); + if (attribute_list) + attribute_list->accept (*this); - tree_args_block_validation_list *validation_list = blk.validation_list (); + tree_args_block_validation_list *validation_list = blk.validation_list (); - if (validation_list) - validation_list->accept (*this); - } + if (validation_list) + validation_list->accept (*this); +} - void tree_walker::visit_args_block_attribute_list (tree_args_block_attribute_list& lst) - { - tree_identifier *attribute = lst.attribute (); +void tree_walker::visit_args_block_attribute_list (tree_args_block_attribute_list& lst) +{ + tree_identifier *attribute = lst.attribute (); - if (attribute) - attribute->accept (*this); - } + if (attribute) + attribute->accept (*this); +} - void tree_walker::visit_args_block_validation_list (tree_args_block_validation_list& lst) - { - for (auto *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_args_block_validation_list (tree_args_block_validation_list& lst) +{ + for (auto *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_arg_validation (tree_arg_validation& val) - { - tree_expression *arg_name = val.identifier_expression (); +void tree_walker::visit_arg_validation (tree_arg_validation& val) +{ + tree_expression *arg_name = val.identifier_expression (); - if (arg_name) - arg_name->accept (*this); + if (arg_name) + arg_name->accept (*this); - tree_arg_size_spec *size_spec = val.size_spec (); + tree_arg_size_spec *size_spec = val.size_spec (); - if (size_spec) - size_spec->accept (*this); + if (size_spec) + size_spec->accept (*this); - tree_identifier *class_name = val.class_name (); + tree_identifier *class_name = val.class_name (); - if (class_name) - class_name->accept (*this); + if (class_name) + class_name->accept (*this); - tree_arg_validation_fcns *validation_fcns = val.validation_fcns (); + tree_arg_validation_fcns *validation_fcns = val.validation_fcns (); - if (validation_fcns) - validation_fcns->accept (*this); + if (validation_fcns) + validation_fcns->accept (*this); - tree_expression *default_value = val.initializer_expression (); + tree_expression *default_value = val.initializer_expression (); - if (default_value) - default_value->accept (*this); - } + if (default_value) + default_value->accept (*this); +} - void tree_walker::visit_arg_size_spec (tree_arg_size_spec& spec) - { - tree_argument_list *size_args = spec.size_args (); +void tree_walker::visit_arg_size_spec (tree_arg_size_spec& spec) +{ + tree_argument_list *size_args = spec.size_args (); - if (size_args) - size_args->accept (*this); - } + if (size_args) + size_args->accept (*this); +} - void tree_walker::visit_arg_validation_fcns (tree_arg_validation_fcns& spec) - { - tree_argument_list *fcn_args = spec.fcn_args (); +void tree_walker::visit_arg_validation_fcns (tree_arg_validation_fcns& spec) +{ + tree_argument_list *fcn_args = spec.fcn_args (); - if (fcn_args) - fcn_args->accept (*this); - } + if (fcn_args) + fcn_args->accept (*this); +} - void tree_walker::visit_binary_expression (tree_binary_expression& expr) - { - tree_expression *op1 = expr.lhs (); +void tree_walker::visit_binary_expression (tree_binary_expression& expr) +{ + tree_expression *op1 = expr.lhs (); - if (op1) - op1->accept (*this); + if (op1) + op1->accept (*this); - tree_expression *op2 = expr.rhs (); + tree_expression *op2 = expr.rhs (); - if (op2) - op2->accept (*this); - } + if (op2) + op2->accept (*this); +} - void tree_walker::visit_boolean_expression (tree_boolean_expression& expr) - { - visit_binary_expression (expr); - } +void tree_walker::visit_boolean_expression (tree_boolean_expression& expr) +{ + visit_binary_expression (expr); +} - void tree_walker::visit_compound_binary_expression (tree_compound_binary_expression& expr) - { - visit_binary_expression (expr); - } +void tree_walker::visit_compound_binary_expression (tree_compound_binary_expression& expr) +{ + visit_binary_expression (expr); +} - void tree_walker::visit_break_command (tree_break_command&) - { - // Nothing to do. - } +void tree_walker::visit_break_command (tree_break_command&) +{ + // Nothing to do. +} - void tree_walker::visit_colon_expression (tree_colon_expression& expr) - { - tree_expression *op1 = expr.base (); +void tree_walker::visit_colon_expression (tree_colon_expression& expr) +{ + tree_expression *op1 = expr.base (); - if (op1) - op1->accept (*this); + if (op1) + op1->accept (*this); - tree_expression *op3 = expr.increment (); + tree_expression *op3 = expr.increment (); - if (op3) - op3->accept (*this); + if (op3) + op3->accept (*this); - tree_expression *op2 = expr.limit (); + tree_expression *op2 = expr.limit (); - if (op2) - op2->accept (*this); - } + if (op2) + op2->accept (*this); +} - void tree_walker::visit_continue_command (tree_continue_command&) - { - // Nothing to do. - } +void tree_walker::visit_continue_command (tree_continue_command&) +{ + // Nothing to do. +} - void tree_walker::visit_decl_command (tree_decl_command& cmd) - { - tree_decl_init_list *init_list = cmd.initializer_list (); +void tree_walker::visit_decl_command (tree_decl_command& cmd) +{ + tree_decl_init_list *init_list = cmd.initializer_list (); - if (init_list) - init_list->accept (*this); - } + if (init_list) + init_list->accept (*this); +} - void tree_walker::visit_decl_elt (tree_decl_elt& cmd) - { - tree_identifier *id = cmd.ident (); +void tree_walker::visit_decl_elt (tree_decl_elt& cmd) +{ + tree_identifier *id = cmd.ident (); - if (id) - id->accept (*this); + if (id) + id->accept (*this); - tree_expression *expr = cmd.expression (); + tree_expression *expr = cmd.expression (); - if (expr) - expr->accept (*this); - } + if (expr) + expr->accept (*this); +} - void tree_walker::visit_decl_init_list (tree_decl_init_list& lst) - { - // FIXME: tree_decl_elt is not derived from tree, so should it - // really have an accept method? +void tree_walker::visit_decl_init_list (tree_decl_init_list& lst) +{ + // FIXME: tree_decl_elt is not derived from tree, so should it + // really have an accept method? - for (tree_decl_elt *elt : lst) - { - if (elt) - elt->accept (*this); - } - } + for (tree_decl_elt *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_simple_for_command (tree_simple_for_command& cmd) - { - tree_expression *lhs = cmd.left_hand_side (); +void tree_walker::visit_simple_for_command (tree_simple_for_command& cmd) +{ + tree_expression *lhs = cmd.left_hand_side (); - if (lhs) - lhs->accept (*this); + if (lhs) + lhs->accept (*this); - tree_expression *expr = cmd.control_expr (); + tree_expression *expr = cmd.control_expr (); - if (expr) - expr->accept (*this); + if (expr) + expr->accept (*this); - tree_expression *maxproc = cmd.maxproc_expr (); + tree_expression *maxproc = cmd.maxproc_expr (); - if (maxproc) - maxproc->accept (*this); + if (maxproc) + maxproc->accept (*this); - tree_statement_list *list = cmd.body (); + tree_statement_list *list = cmd.body (); - if (list) - list->accept (*this); - } + if (list) + list->accept (*this); +} - void tree_walker::visit_complex_for_command (tree_complex_for_command& cmd) - { - tree_argument_list *lhs = cmd.left_hand_side (); +void tree_walker::visit_complex_for_command (tree_complex_for_command& cmd) +{ + tree_argument_list *lhs = cmd.left_hand_side (); - if (lhs) - lhs->accept (*this); + if (lhs) + lhs->accept (*this); - tree_expression *expr = cmd.control_expr (); + tree_expression *expr = cmd.control_expr (); - if (expr) - expr->accept (*this); + if (expr) + expr->accept (*this); - tree_statement_list *list = cmd.body (); + tree_statement_list *list = cmd.body (); - if (list) - list->accept (*this); - } + if (list) + list->accept (*this); +} - void tree_walker::visit_spmd_command (tree_spmd_command& cmd) - { - tree_statement_list *body = cmd.body (); +void tree_walker::visit_spmd_command (tree_spmd_command& cmd) +{ + tree_statement_list *body = cmd.body (); - if (body) - body->accept (*this); - } + if (body) + body->accept (*this); +} - void tree_walker::visit_octave_user_script (octave_user_script& fcn) - { - tree_statement_list *cmd_list = fcn.body (); +void tree_walker::visit_octave_user_script (octave_user_script& fcn) +{ + tree_statement_list *cmd_list = fcn.body (); - if (cmd_list) - cmd_list->accept (*this); - } + if (cmd_list) + cmd_list->accept (*this); +} - void tree_walker::visit_octave_user_function (octave_user_function& fcn) - { - tree_statement_list *cmd_list = fcn.body (); +void tree_walker::visit_octave_user_function (octave_user_function& fcn) +{ + tree_statement_list *cmd_list = fcn.body (); - if (cmd_list) - cmd_list->accept (*this); - } + if (cmd_list) + cmd_list->accept (*this); +} - void tree_walker::visit_function_def (tree_function_def& fdef) - { - octave_value fcn = fdef.function (); +void tree_walker::visit_function_def (tree_function_def& fdef) +{ + octave_value fcn = fdef.function (); - octave_function *f = fcn.function_value (); + octave_function *f = fcn.function_value (); - if (f) - f->accept (*this); - } + if (f) + f->accept (*this); +} - void tree_walker::visit_identifier (tree_identifier&) - { - // Nothing to do. - } +void tree_walker::visit_identifier (tree_identifier&) +{ + // Nothing to do. +} - void tree_walker::visit_if_clause (tree_if_clause& cmd) - { - tree_expression *expr = cmd.condition (); +void tree_walker::visit_if_clause (tree_if_clause& cmd) +{ + tree_expression *expr = cmd.condition (); - if (expr) - expr->accept (*this); + if (expr) + expr->accept (*this); - tree_statement_list *list = cmd.commands (); + tree_statement_list *list = cmd.commands (); - if (list) - list->accept (*this); - } + if (list) + list->accept (*this); +} - void tree_walker::visit_if_command (tree_if_command& cmd) - { - tree_if_command_list *list = cmd.cmd_list (); +void tree_walker::visit_if_command (tree_if_command& cmd) +{ + tree_if_command_list *list = cmd.cmd_list (); - if (list) - list->accept (*this); - } + if (list) + list->accept (*this); +} - void tree_walker::visit_if_command_list (tree_if_command_list& lst) - { - auto p = lst.begin (); +void tree_walker::visit_if_command_list (tree_if_command_list& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_if_clause *elt = *p++; + while (p != lst.end ()) + { + tree_if_clause *elt = *p++; - if (elt) - elt->accept (*this); - } - } + if (elt) + elt->accept (*this); + } +} + +void tree_walker::visit_switch_case (tree_switch_case& cs) +{ + tree_expression *label = cs.case_label (); - void tree_walker::visit_switch_case (tree_switch_case& cs) - { - tree_expression *label = cs.case_label (); + if (label) + label->accept (*this); + + tree_statement_list *list = cs.commands (); - if (label) - label->accept (*this); + if (list) + list->accept (*this); +} - tree_statement_list *list = cs.commands (); - - if (list) - list->accept (*this); - } +void tree_walker::visit_switch_case_list (tree_switch_case_list& lst) +{ + auto p = lst.begin (); - void tree_walker::visit_switch_case_list (tree_switch_case_list& lst) - { - auto p = lst.begin (); + while (p != lst.end ()) + { + tree_switch_case *elt = *p++; - while (p != lst.end ()) - { - tree_switch_case *elt = *p++; + if (elt) + elt->accept (*this); + } +} - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_switch_command (tree_switch_command& cmd) +{ + tree_expression *expr = cmd.switch_value (); - void tree_walker::visit_switch_command (tree_switch_command& cmd) - { - tree_expression *expr = cmd.switch_value (); + if (expr) + expr->accept (*this); - if (expr) - expr->accept (*this); + tree_switch_case_list *list = cmd.case_list (); - tree_switch_case_list *list = cmd.case_list (); + if (list) + list->accept (*this); +} - if (list) - list->accept (*this); - } +void tree_walker::visit_index_expression (tree_index_expression& expr) +{ + tree_expression *e = expr.expression (); - void tree_walker::visit_index_expression (tree_index_expression& expr) - { - tree_expression *e = expr.expression (); + if (e) + e->accept (*this); - if (e) - e->accept (*this); + std::list arg_lists = expr.arg_lists (); + std::list arg_names = expr.arg_names (); + std::list dyn_fields = expr.dyn_fields (); - std::list arg_lists = expr.arg_lists (); - std::list arg_names = expr.arg_names (); - std::list dyn_fields = expr.dyn_fields (); + auto p_arg_lists = arg_lists.begin (); + auto p_arg_names = arg_names.begin (); + auto p_dyn_fields = dyn_fields.begin (); + + std::string type_tags = expr.type_tags (); + int n = type_tags.length (); - auto p_arg_lists = arg_lists.begin (); - auto p_arg_names = arg_names.begin (); - auto p_dyn_fields = dyn_fields.begin (); - - std::string type_tags = expr.type_tags (); - int n = type_tags.length (); - - for (int i = 0; i < n; i++) - { - switch (type_tags[i]) + for (int i = 0; i < n; i++) + { + switch (type_tags[i]) + { + case '(': + case '{': { - case '(': - case '{': - { - tree_argument_list *l = *p_arg_lists; - if (l) - l->accept (*this); - } - break; + tree_argument_list *l = *p_arg_lists; + if (l) + l->accept (*this); + } + break; - case '.': - { - std::string fn = (*p_arg_names)(0); - if (fn.empty ()) - { - tree_expression *df = *p_dyn_fields; - if (df) - df->accept (*this); - } - } - break; + case '.': + { + std::string fn = (*p_arg_names)(0); + if (fn.empty ()) + { + tree_expression *df = *p_dyn_fields; + if (df) + df->accept (*this); + } + } + break; - default: - panic_impossible (); - } + default: + panic_impossible (); + } - p_arg_lists++; - p_arg_names++; - p_dyn_fields++; - } - } + p_arg_lists++; + p_arg_names++; + p_dyn_fields++; + } +} - void tree_walker::visit_matrix (tree_matrix& lst) - { - auto p = lst.begin (); +void tree_walker::visit_matrix (tree_matrix& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_argument_list *elt = *p++; + while (p != lst.end ()) + { + tree_argument_list *elt = *p++; - if (elt) - elt->accept (*this); - } - } + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_cell (tree_cell& lst) - { - auto p = lst.begin (); +void tree_walker::visit_cell (tree_cell& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_argument_list *elt = *p++; + while (p != lst.end ()) + { + tree_argument_list *elt = *p++; - if (elt) - elt->accept (*this); - } - } + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_multi_assignment (tree_multi_assignment& expr) - { - tree_argument_list *lhs = expr.left_hand_side (); +void tree_walker::visit_multi_assignment (tree_multi_assignment& expr) +{ + tree_argument_list *lhs = expr.left_hand_side (); - if (lhs) - lhs->accept (*this); + if (lhs) + lhs->accept (*this); - tree_expression *rhs = expr.right_hand_side (); + tree_expression *rhs = expr.right_hand_side (); - if (rhs) - rhs->accept (*this); - } + if (rhs) + rhs->accept (*this); +} - void tree_walker::visit_no_op_command (tree_no_op_command&) - { - // Nothing to do. - } +void tree_walker::visit_no_op_command (tree_no_op_command&) +{ + // Nothing to do. +} - void tree_walker::visit_constant (tree_constant&) - { - // Nothing to do. - } +void tree_walker::visit_constant (tree_constant&) +{ + // Nothing to do. +} - void tree_walker::visit_fcn_handle (tree_fcn_handle&) - { - // Nothing to do. - } +void tree_walker::visit_fcn_handle (tree_fcn_handle&) +{ + // Nothing to do. +} - void tree_walker::visit_parameter_list (tree_parameter_list& lst) - { - auto p = lst.begin (); +void tree_walker::visit_parameter_list (tree_parameter_list& lst) +{ + auto p = lst.begin (); - while (p != lst.end ()) - { - tree_decl_elt *elt = *p++; + while (p != lst.end ()) + { + tree_decl_elt *elt = *p++; - if (elt) - elt->accept (*this); - } - } + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_postfix_expression (tree_postfix_expression& expr) - { - tree_expression *e = expr.operand (); +void tree_walker::visit_postfix_expression (tree_postfix_expression& expr) +{ + tree_expression *e = expr.operand (); - if (e) - e->accept (*this); - } + if (e) + e->accept (*this); +} - void tree_walker::visit_prefix_expression (tree_prefix_expression& expr) - { - tree_expression *e = expr.operand (); +void tree_walker::visit_prefix_expression (tree_prefix_expression& expr) +{ + tree_expression *e = expr.operand (); - if (e) - e->accept (*this); - } + if (e) + e->accept (*this); +} - void tree_walker::visit_return_command (tree_return_command&) - { - // Nothing to do. - } +void tree_walker::visit_return_command (tree_return_command&) +{ + // Nothing to do. +} - void tree_walker::visit_simple_assignment (tree_simple_assignment& expr) - { - tree_expression *lhs = expr.left_hand_side (); +void tree_walker::visit_simple_assignment (tree_simple_assignment& expr) +{ + tree_expression *lhs = expr.left_hand_side (); - if (lhs) - lhs->accept (*this); + if (lhs) + lhs->accept (*this); - tree_expression *rhs = expr.right_hand_side (); + tree_expression *rhs = expr.right_hand_side (); - if (rhs) - rhs->accept (*this); - } + if (rhs) + rhs->accept (*this); +} - void tree_walker::visit_statement (tree_statement& stmt) - { - tree_command *cmd = stmt.command (); +void tree_walker::visit_statement (tree_statement& stmt) +{ + tree_command *cmd = stmt.command (); + + if (cmd) + cmd->accept (*this); + else + { + tree_expression *expr = stmt.expression (); - if (cmd) - cmd->accept (*this); - else - { - tree_expression *expr = stmt.expression (); + if (expr) + expr->accept (*this); + } +} - if (expr) - expr->accept (*this); - } - } +void tree_walker::visit_statement_list (tree_statement_list& lst) +{ + for (tree_statement *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_statement_list (tree_statement_list& lst) - { - for (tree_statement *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_try_catch_command (tree_try_catch_command& cmd) +{ + tree_statement_list *try_code = cmd.body (); - void tree_walker::visit_try_catch_command (tree_try_catch_command& cmd) - { - tree_statement_list *try_code = cmd.body (); + if (try_code) + try_code->accept (*this); + + tree_identifier *expr_id = cmd.identifier (); + + if (expr_id) + expr_id->accept (*this); - if (try_code) - try_code->accept (*this); + tree_statement_list *catch_code = cmd.cleanup (); - tree_identifier *expr_id = cmd.identifier (); - - if (expr_id) - expr_id->accept (*this); + if (catch_code) + catch_code->accept (*this); +} - tree_statement_list *catch_code = cmd.cleanup (); +void tree_walker::visit_unwind_protect_command (tree_unwind_protect_command& cmd) +{ + tree_statement_list *unwind_protect_code = cmd.body (); - if (catch_code) - catch_code->accept (*this); - } - - void tree_walker::visit_unwind_protect_command (tree_unwind_protect_command& cmd) - { - tree_statement_list *unwind_protect_code = cmd.body (); + if (unwind_protect_code) + unwind_protect_code->accept (*this); - if (unwind_protect_code) - unwind_protect_code->accept (*this); + tree_statement_list *cleanup_code = cmd.cleanup (); - tree_statement_list *cleanup_code = cmd.cleanup (); - - if (cleanup_code) - cleanup_code->accept (*this); - } + if (cleanup_code) + cleanup_code->accept (*this); +} - void tree_walker::visit_while_command (tree_while_command& cmd) - { - tree_expression *expr = cmd.condition (); +void tree_walker::visit_while_command (tree_while_command& cmd) +{ + tree_expression *expr = cmd.condition (); - if (expr) - expr->accept (*this); + if (expr) + expr->accept (*this); - tree_statement_list *list = cmd.body (); + tree_statement_list *list = cmd.body (); + + if (list) + list->accept (*this); +} - if (list) - list->accept (*this); - } +void tree_walker::visit_do_until_command (tree_do_until_command& cmd) +{ + tree_statement_list *list = cmd.body (); - void tree_walker::visit_do_until_command (tree_do_until_command& cmd) - { - tree_statement_list *list = cmd.body (); + if (list) + list->accept (*this); - if (list) - list->accept (*this); + tree_expression *expr = cmd.condition (); - tree_expression *expr = cmd.condition (); + if (expr) + expr->accept (*this); +} - if (expr) - expr->accept (*this); - } +void tree_walker::visit_superclass_ref (tree_superclass_ref&) +{ + // Nothing to do. +} - void tree_walker::visit_superclass_ref (tree_superclass_ref&) - { - // Nothing to do. - } +void tree_walker::visit_metaclass_query (tree_metaclass_query&) +{ + // Nothing to do. +} - void tree_walker::visit_metaclass_query (tree_metaclass_query&) - { - // Nothing to do. - } - - void tree_walker::visit_classdef_attribute (tree_classdef_attribute& attr) - { - tree_identifier *id = attr.ident (); +void tree_walker::visit_classdef_attribute (tree_classdef_attribute& attr) +{ + tree_identifier *id = attr.ident (); - if (id) - id->accept (*this); + if (id) + id->accept (*this); - tree_expression *expr = attr.expression (); + tree_expression *expr = attr.expression (); - if (expr) - expr->accept (*this); - } + if (expr) + expr->accept (*this); +} - void tree_walker::visit_classdef_attribute_list (tree_classdef_attribute_list& lst) - { - for (auto *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_classdef_attribute_list (tree_classdef_attribute_list& lst) +{ + for (auto *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_classdef_superclass (tree_classdef_superclass&) - { - // Nothing to do. - } +void tree_walker::visit_classdef_superclass (tree_classdef_superclass&) +{ + // Nothing to do. +} - void tree_walker::visit_classdef_superclass_list (tree_classdef_superclass_list& lst) - { - for (auto *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_classdef_superclass_list (tree_classdef_superclass_list& lst) +{ + for (auto *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_classdef_property (tree_classdef_property&) - { - // FIXME: Should we operate on the tree_arg_validation object or the - // identifier and expression parts separately? - } +void tree_walker::visit_classdef_property (tree_classdef_property&) +{ + // FIXME: Should we operate on the tree_arg_validation object or the + // identifier and expression parts separately? +} - void tree_walker::visit_classdef_property_list (tree_classdef_property_list& lst) - { - for (auto *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_classdef_property_list (tree_classdef_property_list& lst) +{ + for (auto *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_classdef_properties_block (tree_classdef_properties_block& blk) - { - tree_classdef_property_list *property_list = blk.element_list (); +void tree_walker::visit_classdef_properties_block (tree_classdef_properties_block& blk) +{ + tree_classdef_property_list *property_list = blk.element_list (); - if (property_list) - property_list->accept (*this); - } + if (property_list) + property_list->accept (*this); +} - void tree_walker::visit_classdef_methods_list (tree_classdef_methods_list& lst) - { - for (auto ov_meth : lst) - { - octave_user_function *meth = ov_meth.user_function_value (); +void tree_walker::visit_classdef_methods_list (tree_classdef_methods_list& lst) +{ + for (auto ov_meth : lst) + { + octave_user_function *meth = ov_meth.user_function_value (); - if (meth) - meth->accept (*this); - } - } + if (meth) + meth->accept (*this); + } +} - void tree_walker::visit_classdef_methods_block (tree_classdef_methods_block& blk) - { - tree_classdef_methods_list *methods_list = blk.element_list (); +void tree_walker::visit_classdef_methods_block (tree_classdef_methods_block& blk) +{ + tree_classdef_methods_list *methods_list = blk.element_list (); - if (methods_list) - methods_list->accept (*this); - } + if (methods_list) + methods_list->accept (*this); +} - void tree_walker::visit_classdef_event (tree_classdef_event&) - { - // Nothing to do. - } +void tree_walker::visit_classdef_event (tree_classdef_event&) +{ + // Nothing to do. +} - void tree_walker::visit_classdef_events_list (tree_classdef_events_list& lst) - { - for (auto *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_classdef_events_list (tree_classdef_events_list& lst) +{ + for (auto *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_classdef_events_block (tree_classdef_events_block& blk) - { - tree_classdef_events_list *events_list = blk.element_list (); +void tree_walker::visit_classdef_events_block (tree_classdef_events_block& blk) +{ + tree_classdef_events_list *events_list = blk.element_list (); - if (events_list) - events_list->accept (*this); - } + if (events_list) + events_list->accept (*this); +} - void tree_walker::visit_classdef_enum (tree_classdef_enum&) - { - // Nothing to do. - } +void tree_walker::visit_classdef_enum (tree_classdef_enum&) +{ + // Nothing to do. +} - void tree_walker::visit_classdef_enum_list (tree_classdef_enum_list& lst) - { - for (auto *elt : lst) - { - if (elt) - elt->accept (*this); - } - } +void tree_walker::visit_classdef_enum_list (tree_classdef_enum_list& lst) +{ + for (auto *elt : lst) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_classdef_enum_block (tree_classdef_enum_block& blk) - { - tree_classdef_enum_list *enum_list = blk.element_list (); +void tree_walker::visit_classdef_enum_block (tree_classdef_enum_block& blk) +{ + tree_classdef_enum_list *enum_list = blk.element_list (); - if (enum_list) - enum_list->accept (*this); - } + if (enum_list) + enum_list->accept (*this); +} - void tree_walker::visit_classdef_body (tree_classdef_body& body) - { - for (auto *elt : body.properties_list ()) - { - if (elt) - elt->accept (*this); - } +void tree_walker::visit_classdef_body (tree_classdef_body& body) +{ + for (auto *elt : body.properties_list ()) + { + if (elt) + elt->accept (*this); + } - for (auto *elt : body.methods_list ()) - { - if (elt) - elt->accept (*this); - } + for (auto *elt : body.methods_list ()) + { + if (elt) + elt->accept (*this); + } - for (auto *elt : body.events_list ()) - { - if (elt) - elt->accept (*this); - } + for (auto *elt : body.events_list ()) + { + if (elt) + elt->accept (*this); + } - for (auto *elt : body.enum_list ()) - { - if (elt) - elt->accept (*this); - } - } + for (auto *elt : body.enum_list ()) + { + if (elt) + elt->accept (*this); + } +} - void tree_walker::visit_classdef (tree_classdef& cdef) - { - tree_classdef_attribute_list *attribute_list = cdef.attribute_list (); +void tree_walker::visit_classdef (tree_classdef& cdef) +{ + tree_classdef_attribute_list *attribute_list = cdef.attribute_list (); - if (attribute_list) - attribute_list->accept (*this); + if (attribute_list) + attribute_list->accept (*this); - tree_identifier *ident = cdef.ident (); + tree_identifier *ident = cdef.ident (); - if (ident) - ident->accept (*this); + if (ident) + ident->accept (*this); - tree_classdef_superclass_list *superclass_list = cdef.superclass_list (); + tree_classdef_superclass_list *superclass_list = cdef.superclass_list (); - if (superclass_list) - superclass_list->accept (*this); + if (superclass_list) + superclass_list->accept (*this); - tree_classdef_body *body = cdef.body (); + tree_classdef_body *body = cdef.body (); - if (body) - body->accept (*this); - } + if (body) + body->accept (*this); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt-walk.h --- a/libinterp/parse-tree/pt-walk.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt-walk.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,230 +33,230 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // No separate visitor needed - // Base classes only, so no need to include them. - // - // class tree_array_list - // class tree_unary_expression - // class tree_black_hole +// No separate visitor needed +// Base classes only, so no need to include them. +// +// class tree_array_list +// class tree_unary_expression +// class tree_black_hole - class tree_anon_fcn_handle; - class tree_arg_size_spec; - class tree_arg_validation; - class tree_arg_validation_fcns; - class tree_args_block_attribute_list; - class tree_args_block_validation_list; - class tree_argument_list; - class tree_arguments_block; - class tree_binary_expression; - class tree_boolean_expression; - class tree_compound_binary_expression; - class tree_break_command; - class tree_colon_expression; - class tree_continue_command; - class tree_decl_command; - class tree_decl_init_list; - 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; - class tree_if_command; - class tree_if_command_list; - class tree_switch_case; - class tree_switch_case_list; - class tree_switch_command; - class tree_index_expression; - class tree_matrix; - class tree_cell; - class tree_multi_assignment; - class tree_no_op_command; - class tree_constant; - class tree_fcn_handle; - class tree_parameter_list; - class tree_postfix_expression; - class tree_prefix_expression; - class tree_return_command; - class tree_simple_assignment; - class tree_statement; - class tree_statement_list; - class tree_try_catch_command; - class tree_unwind_protect_command; - class tree_while_command; - class tree_do_until_command; +class tree_anon_fcn_handle; +class tree_arg_size_spec; +class tree_arg_validation; +class tree_arg_validation_fcns; +class tree_args_block_attribute_list; +class tree_args_block_validation_list; +class tree_argument_list; +class tree_arguments_block; +class tree_binary_expression; +class tree_boolean_expression; +class tree_compound_binary_expression; +class tree_break_command; +class tree_colon_expression; +class tree_continue_command; +class tree_decl_command; +class tree_decl_init_list; +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; +class tree_if_command; +class tree_if_command_list; +class tree_switch_case; +class tree_switch_case_list; +class tree_switch_command; +class tree_index_expression; +class tree_matrix; +class tree_cell; +class tree_multi_assignment; +class tree_no_op_command; +class tree_constant; +class tree_fcn_handle; +class tree_parameter_list; +class tree_postfix_expression; +class tree_prefix_expression; +class tree_return_command; +class tree_simple_assignment; +class tree_statement; +class tree_statement_list; +class tree_try_catch_command; +class tree_unwind_protect_command; +class tree_while_command; +class tree_do_until_command; - class tree_superclass_ref; - class tree_metaclass_query; - class tree_classdef_attribute; - class tree_classdef_attribute_list; - class tree_classdef_superclass; - class tree_classdef_superclass_list; - class tree_classdef_property; - class tree_classdef_property_list; - class tree_classdef_properties_block; - class tree_classdef_methods_list; - class tree_classdef_methods_block; - class tree_classdef_event; - class tree_classdef_events_list; - class tree_classdef_events_block; - class tree_classdef_enum; - class tree_classdef_enum_list; - class tree_classdef_enum_block; - class tree_classdef_body; - class tree_classdef; +class tree_superclass_ref; +class tree_metaclass_query; +class tree_classdef_attribute; +class tree_classdef_attribute_list; +class tree_classdef_superclass; +class tree_classdef_superclass_list; +class tree_classdef_property; +class tree_classdef_property_list; +class tree_classdef_properties_block; +class tree_classdef_methods_list; +class tree_classdef_methods_block; +class tree_classdef_event; +class tree_classdef_events_list; +class tree_classdef_events_block; +class tree_classdef_enum; +class tree_classdef_enum_list; +class tree_classdef_enum_block; +class tree_classdef_body; +class tree_classdef; - class tree_walker - { - protected: +class tree_walker +{ +protected: - tree_walker (void) { } + tree_walker (void) { } - virtual ~tree_walker (void) = default; + virtual ~tree_walker (void) = default; - public: +public: - // No copying! + // No copying! - tree_walker (const tree_walker&) = delete; + tree_walker (const tree_walker&) = delete; - tree_walker& operator = (const tree_walker&) = delete; + tree_walker& operator = (const tree_walker&) = delete; - virtual void visit_anon_fcn_handle (tree_anon_fcn_handle&); + virtual void visit_anon_fcn_handle (tree_anon_fcn_handle&); - virtual void visit_argument_list (tree_argument_list&); + virtual void visit_argument_list (tree_argument_list&); - virtual void visit_arguments_block (tree_arguments_block&); + virtual void visit_arguments_block (tree_arguments_block&); - virtual void visit_args_block_attribute_list (tree_args_block_attribute_list&); + virtual void visit_args_block_attribute_list (tree_args_block_attribute_list&); - virtual void visit_args_block_validation_list (tree_args_block_validation_list&); + virtual void visit_args_block_validation_list (tree_args_block_validation_list&); - virtual void visit_arg_validation (tree_arg_validation&); + virtual void visit_arg_validation (tree_arg_validation&); - virtual void visit_arg_size_spec (tree_arg_size_spec&); + virtual void visit_arg_size_spec (tree_arg_size_spec&); - virtual void visit_arg_validation_fcns (tree_arg_validation_fcns&); + virtual void visit_arg_validation_fcns (tree_arg_validation_fcns&); - virtual void visit_binary_expression (tree_binary_expression&); + virtual void visit_binary_expression (tree_binary_expression&); - virtual void visit_boolean_expression (tree_boolean_expression&); + virtual void visit_boolean_expression (tree_boolean_expression&); - virtual void visit_compound_binary_expression (tree_compound_binary_expression&); + virtual void visit_compound_binary_expression (tree_compound_binary_expression&); - virtual void visit_break_command (tree_break_command&); + virtual void visit_break_command (tree_break_command&); - virtual void visit_colon_expression (tree_colon_expression&); + virtual void visit_colon_expression (tree_colon_expression&); - virtual void visit_continue_command (tree_continue_command&); + virtual void visit_continue_command (tree_continue_command&); - virtual void visit_decl_command (tree_decl_command&); + virtual void visit_decl_command (tree_decl_command&); - virtual void visit_decl_elt (tree_decl_elt&); + virtual void visit_decl_elt (tree_decl_elt&); - virtual void visit_decl_init_list (tree_decl_init_list&); + virtual void visit_decl_init_list (tree_decl_init_list&); - virtual void visit_simple_for_command (tree_simple_for_command&); + virtual void visit_simple_for_command (tree_simple_for_command&); - virtual void visit_complex_for_command (tree_complex_for_command&); + virtual void visit_complex_for_command (tree_complex_for_command&); - virtual void visit_spmd_command (tree_spmd_command&); + virtual void visit_spmd_command (tree_spmd_command&); - virtual void visit_octave_user_script (octave_user_script&); + virtual void visit_octave_user_script (octave_user_script&); - virtual void visit_octave_user_function (octave_user_function&); + virtual void visit_octave_user_function (octave_user_function&); - virtual void visit_function_def (tree_function_def&); + virtual void visit_function_def (tree_function_def&); - virtual void visit_identifier (tree_identifier&); + virtual void visit_identifier (tree_identifier&); - virtual void visit_if_clause (tree_if_clause&); + virtual void visit_if_clause (tree_if_clause&); - virtual void visit_if_command (tree_if_command&); + virtual void visit_if_command (tree_if_command&); - virtual void visit_if_command_list (tree_if_command_list&); + virtual void visit_if_command_list (tree_if_command_list&); - virtual void visit_switch_case (tree_switch_case&); + virtual void visit_switch_case (tree_switch_case&); - virtual void visit_switch_case_list (tree_switch_case_list&); + virtual void visit_switch_case_list (tree_switch_case_list&); - virtual void visit_switch_command (tree_switch_command&); + virtual void visit_switch_command (tree_switch_command&); - virtual void visit_index_expression (tree_index_expression&); + virtual void visit_index_expression (tree_index_expression&); - virtual void visit_matrix (tree_matrix&); + virtual void visit_matrix (tree_matrix&); - virtual void visit_cell (tree_cell&); + virtual void visit_cell (tree_cell&); - virtual void visit_multi_assignment (tree_multi_assignment&); + virtual void visit_multi_assignment (tree_multi_assignment&); - virtual void visit_no_op_command (tree_no_op_command&); + virtual void visit_no_op_command (tree_no_op_command&); - virtual void visit_constant (tree_constant&); + virtual void visit_constant (tree_constant&); - virtual void visit_fcn_handle (tree_fcn_handle&); + virtual void visit_fcn_handle (tree_fcn_handle&); - virtual void visit_parameter_list (tree_parameter_list&); + virtual void visit_parameter_list (tree_parameter_list&); - virtual void visit_postfix_expression (tree_postfix_expression&); + virtual void visit_postfix_expression (tree_postfix_expression&); - virtual void visit_prefix_expression (tree_prefix_expression&); + virtual void visit_prefix_expression (tree_prefix_expression&); - virtual void visit_return_command (tree_return_command&); + virtual void visit_return_command (tree_return_command&); - virtual void visit_simple_assignment (tree_simple_assignment&); + virtual void visit_simple_assignment (tree_simple_assignment&); - virtual void visit_statement (tree_statement&); + virtual void visit_statement (tree_statement&); - virtual void visit_statement_list (tree_statement_list&); + virtual void visit_statement_list (tree_statement_list&); - virtual void visit_try_catch_command (tree_try_catch_command&); + virtual void visit_try_catch_command (tree_try_catch_command&); - virtual void visit_unwind_protect_command (tree_unwind_protect_command&); + virtual void visit_unwind_protect_command (tree_unwind_protect_command&); - virtual void visit_while_command (tree_while_command&); + virtual void visit_while_command (tree_while_command&); - virtual void visit_do_until_command (tree_do_until_command&); + virtual void visit_do_until_command (tree_do_until_command&); - virtual void visit_superclass_ref (tree_superclass_ref&); + virtual void visit_superclass_ref (tree_superclass_ref&); - virtual void visit_metaclass_query (tree_metaclass_query&); + virtual void visit_metaclass_query (tree_metaclass_query&); - virtual void visit_classdef_attribute (tree_classdef_attribute&); + virtual void visit_classdef_attribute (tree_classdef_attribute&); - virtual void visit_classdef_attribute_list (tree_classdef_attribute_list&); + virtual void visit_classdef_attribute_list (tree_classdef_attribute_list&); - virtual void visit_classdef_superclass (tree_classdef_superclass&); + virtual void visit_classdef_superclass (tree_classdef_superclass&); - virtual void visit_classdef_superclass_list (tree_classdef_superclass_list&); + virtual void visit_classdef_superclass_list (tree_classdef_superclass_list&); - virtual void visit_classdef_property (tree_classdef_property&); + virtual void visit_classdef_property (tree_classdef_property&); - virtual void visit_classdef_property_list (tree_classdef_property_list&); + virtual void visit_classdef_property_list (tree_classdef_property_list&); - virtual void visit_classdef_properties_block (tree_classdef_properties_block&); + virtual void visit_classdef_properties_block (tree_classdef_properties_block&); - virtual void visit_classdef_methods_list (tree_classdef_methods_list&); + virtual void visit_classdef_methods_list (tree_classdef_methods_list&); - virtual void visit_classdef_methods_block (tree_classdef_methods_block&); + virtual void visit_classdef_methods_block (tree_classdef_methods_block&); - virtual void visit_classdef_event (tree_classdef_event&); + virtual void visit_classdef_event (tree_classdef_event&); - virtual void visit_classdef_events_list (tree_classdef_events_list&); + virtual void visit_classdef_events_list (tree_classdef_events_list&); - virtual void visit_classdef_events_block (tree_classdef_events_block&); + virtual void visit_classdef_events_block (tree_classdef_events_block&); - virtual void visit_classdef_enum (tree_classdef_enum&); + virtual void visit_classdef_enum (tree_classdef_enum&); - virtual void visit_classdef_enum_list (tree_classdef_enum_list&); + virtual void visit_classdef_enum_list (tree_classdef_enum_list&); - virtual void visit_classdef_enum_block (tree_classdef_enum_block&); + virtual void visit_classdef_enum_block (tree_classdef_enum_block&); - virtual void visit_classdef_body (tree_classdef_body&); + virtual void visit_classdef_body (tree_classdef_body&); - virtual void visit_classdef (tree_classdef&); - }; + virtual void visit_classdef (tree_classdef&); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt.cc --- a/libinterp/parse-tree/pt.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt.cc Thu Dec 01 20:05:44 2022 -0800 @@ -39,72 +39,72 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Hide the details of the string buffer so that we are less likely to - // create a memory leak. +// Hide the details of the string buffer so that we are less likely to +// create a memory leak. - std::string - tree::str_print_code (void) - { - std::ostringstream buf; +std::string +tree::str_print_code (void) +{ + std::ostringstream buf; - tree_print_code tpc (buf); + tree_print_code tpc (buf); - accept (tpc); + accept (tpc); - std::string retval = buf.str (); + std::string retval = buf.str (); - return retval; - } + return retval; +} - // Is the current breakpoint condition met? +// Is the current breakpoint condition met? - bool - tree::meets_bp_condition (tree_evaluator& tw) const - { - bool retval; - if (m_bp_cond == nullptr) - retval = false; - else if (m_bp_cond->empty ()) // empty condition always met - retval = true; - else - { - int parse_status = 0; +bool +tree::meets_bp_condition (tree_evaluator& tw) const +{ + bool retval; + if (m_bp_cond == nullptr) + retval = false; + else if (m_bp_cond->empty ()) // empty condition always met + retval = true; + else + { + int parse_status = 0; - unwind_protect frame; + unwind_protect frame; - octave::interpreter_try (frame); + octave::interpreter_try (frame); - retval = true; // default to stopping if any error - try - { - octave_value_list val - = tw.eval_string (*m_bp_cond, 1, parse_status, 1); + retval = true; // default to stopping if any error + try + { + octave_value_list val + = tw.eval_string (*m_bp_cond, 1, parse_status, 1); - if (parse_status == 0) - { - if (! val(0).is_scalar_type ()) - warning ("Breakpoint condition must be a scalar, not size %s", - val(0).dims ().str ('x').c_str ()); - else - retval = val(0).bool_value (); - } - else - warning ("Error parsing breakpoint condition"); - } - catch (const execution_exception& ee) - { - interpreter& interp = tw.get_interpreter (); + if (parse_status == 0) + { + if (! val(0).is_scalar_type ()) + warning ("Breakpoint condition must be a scalar, not size %s", + val(0).dims ().str ('x').c_str ()); + else + retval = val(0).bool_value (); + } + else + warning ("Error parsing breakpoint condition"); + } + catch (const execution_exception& ee) + { + interpreter& interp = tw.get_interpreter (); - interp.recover_from_exception (); + interp.recover_from_exception (); - std::string tmp = ee.message (); + std::string tmp = ee.message (); - warning ("Error evaluating breakpoint condition:\n %s", - tmp.c_str ()); - } - } + warning ("Error evaluating breakpoint condition:\n %s", + tmp.c_str ()); + } + } - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/pt.h --- a/libinterp/parse-tree/pt.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/pt.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,92 +36,92 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class tree_evaluator; - class tree_walker; +class tree_evaluator; +class tree_walker; - // Base class for the parse tree. +// Base class for the parse tree. - class tree - { - public: +class tree +{ +public: - tree (int l = -1, int c = -1) - : m_line_num (l), m_column_num (c), m_bp_cond (nullptr) - { } + tree (int l = -1, int c = -1) + : m_line_num (l), m_column_num (c), m_bp_cond (nullptr) + { } - // No copying! + // No copying! - tree (const tree&) = delete; + tree (const tree&) = delete; - tree& operator = (const tree&) = delete; + tree& operator = (const tree&) = delete; - virtual ~tree (void) = default; + virtual ~tree (void) = default; - virtual int line (void) const { return m_line_num; } + virtual int line (void) const { return m_line_num; } - virtual int column (void) const { return m_column_num; } + virtual int column (void) const { return m_column_num; } - void line (int l) { m_line_num = l; } + void line (int l) { m_line_num = l; } - void column (int c) { m_column_num = c; } + void column (int c) { m_column_num = c; } - void set_location (int l, int c) - { - m_line_num = l; - m_column_num = c; - } + void set_location (int l, int c) + { + m_line_num = l; + m_column_num = c; + } - virtual void set_breakpoint (const std::string& condition) - { - if (m_bp_cond) - *m_bp_cond = condition; - else - m_bp_cond = new std::string (condition); - } + virtual void set_breakpoint (const std::string& condition) + { + if (m_bp_cond) + *m_bp_cond = condition; + else + m_bp_cond = new std::string (condition); + } - virtual void delete_breakpoint (void) - { - if (m_bp_cond) - { - delete m_bp_cond; + virtual void delete_breakpoint (void) + { + if (m_bp_cond) + { + delete m_bp_cond; - m_bp_cond = nullptr; - } - } + m_bp_cond = nullptr; + } + } - bool meets_bp_condition (tree_evaluator& tw) const; + bool meets_bp_condition (tree_evaluator& tw) const; - bool is_breakpoint (void) const - { - return m_bp_cond; - } + bool is_breakpoint (void) const + { + return m_bp_cond; + } - bool is_active_breakpoint (tree_evaluator& tw) const - { - return m_bp_cond && meets_bp_condition (tw); - } + bool is_active_breakpoint (tree_evaluator& tw) const + { + return m_bp_cond && meets_bp_condition (tw); + } - // breakpoint condition, or "0" (i.e., "false") if no breakpoint. - // To distinguish "0" from a disabled breakpoint, test "is_breakpoint" too. - const std::string bp_cond (void) const - { - return m_bp_cond ? *m_bp_cond : "0"; - } + // breakpoint condition, or "0" (i.e., "false") if no breakpoint. + // To distinguish "0" from a disabled breakpoint, test "is_breakpoint" too. + const std::string bp_cond (void) const + { + return m_bp_cond ? *m_bp_cond : "0"; + } - std::string str_print_code (void); + std::string str_print_code (void); - virtual void accept (tree_walker& tw) = 0; + virtual void accept (tree_walker& tw) = 0; - private: +private: - // The input line and column where we found the text that was - // eventually converted to this tree node. - int m_line_num; - int m_column_num; + // The input line and column where we found the text that was + // eventually converted to this tree node. + int m_line_num; + int m_column_num; - // NULL if no breakpoint, or a breakpoint condition if there is one. - std::string *m_bp_cond; - }; + // NULL if no breakpoint, or a breakpoint condition if there is one. + std::string *m_bp_cond; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/token.cc --- a/libinterp/parse-tree/token.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/token.cc Thu Dec 01 20:05:44 2022 -0800 @@ -34,110 +34,110 @@ OCTAVE_BEGIN_NAMESPACE(octave) - token::token (int tv, const filepos& beg_pos, const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), m_type_tag (generic_token), - m_tok_info (), m_orig_text () - { } +token::token (int tv, const filepos& beg_pos, const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), m_type_tag (generic_token), + m_tok_info (), m_orig_text () +{ } - token::token (int tv, bool is_kw, const filepos& beg_pos, - const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), - m_type_tag (is_kw ? keyword_token : generic_token), m_tok_info (), - m_orig_text () - { } +token::token (int tv, bool is_kw, const filepos& beg_pos, + const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), + m_type_tag (is_kw ? keyword_token : generic_token), m_tok_info (), + m_orig_text () +{ } - token::token (int tv, const char *s, const filepos& beg_pos, - const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), m_type_tag (string_token), - m_tok_info (s), m_orig_text () - { } +token::token (int tv, const char *s, const filepos& beg_pos, + const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), m_type_tag (string_token), + m_tok_info (s), m_orig_text () +{ } - token::token (int tv, const std::string& s, const filepos& beg_pos, - const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), m_type_tag (string_token), - m_tok_info (s), m_orig_text () - { } +token::token (int tv, const std::string& s, const filepos& beg_pos, + const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), m_type_tag (string_token), + m_tok_info (s), m_orig_text () +{ } - token::token (int tv, const octave_value& val, const std::string& s, - const filepos& beg_pos, const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), m_type_tag (numeric_token), - m_tok_info (val), m_orig_text (s) - { } +token::token (int tv, const octave_value& val, const std::string& s, + const filepos& beg_pos, const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), m_type_tag (numeric_token), + m_tok_info (val), m_orig_text (s) +{ } - token::token (int tv, end_tok_type t, const filepos& beg_pos, - const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), m_type_tag (ettype_token), - m_tok_info (t), m_orig_text () - { } +token::token (int tv, end_tok_type t, const filepos& beg_pos, + const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), m_type_tag (ettype_token), + m_tok_info (t), m_orig_text () +{ } - token::token (int tv, const std::string& meth, const std::string& cls, - const filepos& beg_pos, const filepos& end_pos) - : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), - m_end_pos (end_pos), m_tok_val (tv), m_type_tag (scls_name_token), - m_tok_info (meth, cls), m_orig_text () - { } +token::token (int tv, const std::string& meth, const std::string& cls, + const filepos& beg_pos, const filepos& end_pos) + : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos), + m_end_pos (end_pos), m_tok_val (tv), m_type_tag (scls_name_token), + m_tok_info (meth, cls), m_orig_text () +{ } - token::~token (void) - { - if (m_type_tag == string_token) - delete m_tok_info.m_str; - else if (m_type_tag == numeric_token) - delete m_tok_info.m_num; - else if (m_type_tag == scls_name_token) - delete m_tok_info.m_superclass_info; - } +token::~token (void) +{ + if (m_type_tag == string_token) + delete m_tok_info.m_str; + else if (m_type_tag == numeric_token) + delete m_tok_info.m_num; + else if (m_type_tag == scls_name_token) + delete m_tok_info.m_superclass_info; +} - std::string - token::text (void) const - { - panic_if (m_type_tag != string_token); - return *m_tok_info.m_str; - } +std::string +token::text (void) const +{ + panic_if (m_type_tag != string_token); + return *m_tok_info.m_str; +} - octave_value - token::number (void) const - { - panic_if (m_type_tag != numeric_token); - return *m_tok_info.m_num; - } +octave_value +token::number (void) const +{ + panic_if (m_type_tag != numeric_token); + return *m_tok_info.m_num; +} - token::token_type - token::ttype (void) const - { - return m_type_tag; - } +token::token_type +token::ttype (void) const +{ + return m_type_tag; +} - token::end_tok_type - token::ettype (void) const - { - panic_if (m_type_tag != ettype_token); - return m_tok_info.m_et; - } +token::end_tok_type +token::ettype (void) const +{ + panic_if (m_type_tag != ettype_token); + return m_tok_info.m_et; +} - std::string - token::superclass_method_name (void) const - { - panic_if (m_type_tag != scls_name_token); - return m_tok_info.m_superclass_info->m_method_name; - } +std::string +token::superclass_method_name (void) const +{ + panic_if (m_type_tag != scls_name_token); + return m_tok_info.m_superclass_info->m_method_name; +} - std::string - token::superclass_class_name (void) const - { - panic_if (m_type_tag != scls_name_token); - return m_tok_info.m_superclass_info->m_class_name; - } +std::string +token::superclass_class_name (void) const +{ + panic_if (m_type_tag != scls_name_token); + return m_tok_info.m_superclass_info->m_class_name; +} - std::string - token::text_rep (void) const - { - return m_orig_text; - } +std::string +token::text_rep (void) const +{ + return m_orig_text; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 libinterp/parse-tree/token.h --- a/libinterp/parse-tree/token.h Thu Dec 01 14:28:07 2022 -0800 +++ b/libinterp/parse-tree/token.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,178 +35,178 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class token +class token +{ +public: + + enum token_type + { + generic_token, + keyword_token, + string_token, + numeric_token, + ettype_token, + scls_name_token, + }; + + enum end_tok_type { - public: + simple_end, + arguments_end, + classdef_end, + enumeration_end, + events_end, + for_end, + function_end, + if_end, + methods_end, + parfor_end, + properties_end, + switch_end, + try_catch_end, + unwind_protect_end, + spmd_end, + while_end, + }; + + token (int tv, const filepos& beg_pos, const filepos& end_pos); + + token (int tv, bool is_keyword, const filepos& beg_pos + , const filepos& end_pos); + + token (int tv, const char *s, const filepos& beg_pos, + const filepos& end_pos); + + token (int tv, const std::string& s, const filepos& beg_pos, + const filepos& end_pos); + + token (int tv, const octave_value& val, const std::string& s, + const filepos& beg_pos, const filepos& end_pos); + + token (int tv, end_tok_type t, const filepos& beg_pos, + const filepos& end_pos); + + token (int tv, const std::string& mth, const std::string& cls, + const filepos& beg_pos, const filepos& end_pos); + + // No copying! + + token (const token&) = delete; + + token& operator = (const token&) = delete; + + ~token (void); + + void mark_may_be_command (void) { m_maybe_cmd = true; } + bool may_be_command (void) const { return m_maybe_cmd; } + + void mark_trailing_space (void) { m_tspc = true; } + bool space_follows_token (void) const { return m_tspc; } - enum token_type - { - generic_token, - keyword_token, - string_token, - numeric_token, - ettype_token, - scls_name_token, - }; + int token_value (void) const { return m_tok_val; } + bool token_value_is (int tv) const { return tv == m_tok_val; } + + filepos beg_pos (void) const { return m_beg_pos; } + filepos end_pos (void) const { return m_end_pos; } + + void beg_pos (const filepos& pos) { m_beg_pos = pos; } + void end_pos (const filepos& pos) { m_end_pos = pos; } + + // These will probably be removed. + int line (void) const { return m_beg_pos.line (); } + int column (void) const { return m_beg_pos.column (); } + + bool iskeyword (void) const + { + return m_type_tag == keyword_token || m_type_tag == ettype_token; + } + + bool isstring (void) const { return m_type_tag == string_token; } + + std::string text (void) const; + octave_value number (void) const; + token_type ttype (void) const; + end_tok_type ettype (void) const; + + std::string superclass_method_name (void) const; + std::string superclass_class_name (void) const; + + std::string text_rep (void) const; + +private: + + bool m_maybe_cmd; + + bool m_tspc; - enum end_tok_type + filepos m_beg_pos; + filepos m_end_pos; + + int m_tok_val; + + token_type m_type_tag; + + union tok_info + { + tok_info (void) { } + + tok_info (const char *s) : m_str (new std::string (s)) { } + + tok_info (const std::string& str) : m_str (new std::string (str)) { } + + tok_info (const octave_value& num) : m_num (new octave_value (num)) { } + + tok_info (end_tok_type et) : m_et (et) { } + + tok_info (const std::string& meth, const std::string& cls) + : m_superclass_info (new superclass_info (meth, cls)) + { } + + tok_info (const tok_info&) = delete; + + tok_info& operator = (const tok_info&) = delete; + + ~tok_info (void) { } + + std::string *m_str; + + octave_value *m_num; + + end_tok_type m_et; + + struct superclass_info { - simple_end, - arguments_end, - classdef_end, - enumeration_end, - events_end, - for_end, - function_end, - if_end, - methods_end, - parfor_end, - properties_end, - switch_end, - try_catch_end, - unwind_protect_end, - spmd_end, - while_end, + public: + superclass_info (const std::string& meth, const std::string& cls) + : m_method_name (meth), m_class_name (cls) + { } + + superclass_info (void) = delete; + + superclass_info (const superclass_info&) = delete; + + superclass_info& operator = (const superclass_info&) = delete; + + ~superclass_info (void) = default; + + //-------- + + // The name of the method to call. This is the text before the + // "@" and may be of the form "object.method". + std::string m_method_name; + + // The name of the superclass. This is the text after the "@" + // and may be of the form "object.method". + std::string m_class_name; }; - token (int tv, const filepos& beg_pos, const filepos& end_pos); - - token (int tv, bool is_keyword, const filepos& beg_pos - , const filepos& end_pos); - - token (int tv, const char *s, const filepos& beg_pos, - const filepos& end_pos); - - token (int tv, const std::string& s, const filepos& beg_pos, - const filepos& end_pos); - - token (int tv, const octave_value& val, const std::string& s, - const filepos& beg_pos, const filepos& end_pos); - - token (int tv, end_tok_type t, const filepos& beg_pos, - const filepos& end_pos); - - token (int tv, const std::string& mth, const std::string& cls, - const filepos& beg_pos, const filepos& end_pos); - - // No copying! - - token (const token&) = delete; - - token& operator = (const token&) = delete; - - ~token (void); - - void mark_may_be_command (void) { m_maybe_cmd = true; } - bool may_be_command (void) const { return m_maybe_cmd; } - - void mark_trailing_space (void) { m_tspc = true; } - bool space_follows_token (void) const { return m_tspc; } - - int token_value (void) const { return m_tok_val; } - bool token_value_is (int tv) const { return tv == m_tok_val; } - - filepos beg_pos (void) const { return m_beg_pos; } - filepos end_pos (void) const { return m_end_pos; } - - void beg_pos (const filepos& pos) { m_beg_pos = pos; } - void end_pos (const filepos& pos) { m_end_pos = pos; } - - // These will probably be removed. - int line (void) const { return m_beg_pos.line (); } - int column (void) const { return m_beg_pos.column (); } - - bool iskeyword (void) const - { - return m_type_tag == keyword_token || m_type_tag == ettype_token; - } - - bool isstring (void) const { return m_type_tag == string_token; } - - std::string text (void) const; - octave_value number (void) const; - token_type ttype (void) const; - end_tok_type ettype (void) const; - - std::string superclass_method_name (void) const; - std::string superclass_class_name (void) const; - - std::string text_rep (void) const; - - private: - - bool m_maybe_cmd; + superclass_info *m_superclass_info; + }; - bool m_tspc; - - filepos m_beg_pos; - filepos m_end_pos; - - int m_tok_val; - - token_type m_type_tag; - - union tok_info - { - tok_info (void) { } - - tok_info (const char *s) : m_str (new std::string (s)) { } - - tok_info (const std::string& str) : m_str (new std::string (str)) { } - - tok_info (const octave_value& num) : m_num (new octave_value (num)) { } - - tok_info (end_tok_type et) : m_et (et) { } - - tok_info (const std::string& meth, const std::string& cls) - : m_superclass_info (new superclass_info (meth, cls)) - { } - - tok_info (const tok_info&) = delete; - - tok_info& operator = (const tok_info&) = delete; - - ~tok_info (void) { } - - std::string *m_str; - - octave_value *m_num; + tok_info m_tok_info; - end_tok_type m_et; - - struct superclass_info - { - public: - superclass_info (const std::string& meth, const std::string& cls) - : m_method_name (meth), m_class_name (cls) - { } - - superclass_info (void) = delete; - - superclass_info (const superclass_info&) = delete; - - superclass_info& operator = (const superclass_info&) = delete; - - ~superclass_info (void) = default; - - //-------- - - // The name of the method to call. This is the text before the - // "@" and may be of the form "object.method". - std::string m_method_name; - - // The name of the superclass. This is the text after the "@" - // and may be of the form "object.method". - std::string m_class_name; - }; - - superclass_info *m_superclass_info; - }; - - tok_info m_tok_info; - - std::string m_orig_text; - }; + std::string m_orig_text; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/array/Range.cc --- a/liboctave/array/Range.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/array/Range.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,415 +41,415 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template - T xtfloor (T x, T ct) - { - // C---------FLOOR(X) is the largest integer algebraically less than - // C or equal to X; that is, the unfuzzy FLOOR function. +template +T xtfloor (T x, T ct) +{ + // C---------FLOOR(X) is the largest integer algebraically less than + // C or equal to X; that is, the unfuzzy FLOOR function. - // DINT (X) = X - DMOD (X, 1.0); - // FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); + // DINT (X) = X - DMOD (X, 1.0); + // FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); - // C---------Hagerty's FL5 function follows... + // C---------Hagerty's FL5 function follows... - T q = 1; + T q = 1; - if (x < 0) - q = 1 - ct; + if (x < 0) + q = 1 - ct; - T rmax = q / (2 - ct); + T rmax = q / (2 - ct); - T t1 = 1 + std::floor (x); - t1 = (ct / q) * (t1 < 0 ? -t1 : t1); - t1 = (rmax < t1 ? rmax : t1); - t1 = (ct > t1 ? ct : t1); - t1 = std::floor (x + t1); + T t1 = 1 + std::floor (x); + t1 = (ct / q) * (t1 < 0 ? -t1 : t1); + t1 = (rmax < t1 ? rmax : t1); + t1 = (ct > t1 ? ct : t1); + t1 = std::floor (x + t1); - if (x <= 0 || (t1 - x) < rmax) - return t1; - else - return t1 - 1; - } + if (x <= 0 || (t1 - x) < rmax) + return t1; + else + return t1 - 1; +} - template - bool xteq (T u, T v, T ct = 3 * std::numeric_limits::epsilon ()) - { - T tu = std::abs (u); - T tv = std::abs (v); +template +bool xteq (T u, T v, T ct = 3 * std::numeric_limits::epsilon ()) +{ + T tu = std::abs (u); + T tv = std::abs (v); - return std::abs (u - v) < ((tu > tv ? tu : tv) * ct); - } + return std::abs (u - v) < ((tu > tv ? tu : tv) * ct); +} - template - octave_idx_type xnumel_internal (T base, T limit, T inc) - { - octave_idx_type retval = -1; - if (! math::isfinite (base) || ! math::isfinite (inc) - || math::isnan (limit)) - retval = -2; - else if (math::isinf (limit) - && ((inc > 0 && limit > 0) - || (inc < 0 && limit < 0))) - retval = std::numeric_limits::max () - 1; - else if (inc == 0 - || (limit > base && inc < 0) - || (limit < base && inc > 0)) - { - retval = 0; - } - else - { - T ct = 3 * std::numeric_limits::epsilon (); +template +octave_idx_type xnumel_internal (T base, T limit, T inc) +{ + octave_idx_type retval = -1; + if (! math::isfinite (base) || ! math::isfinite (inc) + || math::isnan (limit)) + retval = -2; + else if (math::isinf (limit) + && ((inc > 0 && limit > 0) + || (inc < 0 && limit < 0))) + retval = std::numeric_limits::max () - 1; + else if (inc == 0 + || (limit > base && inc < 0) + || (limit < base && inc > 0)) + { + retval = 0; + } + else + { + T ct = 3 * std::numeric_limits::epsilon (); - T tmp = xtfloor ((limit - base + inc) / inc, ct); + T tmp = xtfloor ((limit - base + inc) / inc, ct); - octave_idx_type n_elt - = (tmp > 0 ? static_cast (tmp) : 0); + octave_idx_type n_elt + = (tmp > 0 ? static_cast (tmp) : 0); - // If the final element that we would compute for the range is - // equal to the limit of the range, or is an adjacent floating - // point number, accept it. Otherwise, try a range with one - // fewer element. If that fails, try again with one more - // element. - // - // I'm not sure this is very good, but it seems to work better - // than just 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 the final element that we would compute for the range is + // equal to the limit of the range, or is an adjacent floating + // point number, accept it. Otherwise, try a range with one + // fewer element. If that fails, try again with one more + // element. + // + // I'm not sure this is very good, but it seems to work better + // than just 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 (! xteq (base + (n_elt - 1) * inc, limit)) - { - if (xteq (base + (n_elt - 2) * inc, limit)) - n_elt--; - else if (xteq (base + n_elt * inc, limit)) - n_elt++; - } + if (! xteq (base + (n_elt - 1) * inc, limit)) + { + if (xteq (base + (n_elt - 2) * inc, limit)) + n_elt--; + else if (xteq (base + n_elt * inc, limit)) + n_elt++; + } - retval = (n_elt < std::numeric_limits::max () - 1 - ? n_elt : -1); - } + retval = (n_elt < std::numeric_limits::max () - 1 + ? n_elt : -1); + } - return retval; - } + return retval; +} - template - bool xall_elements_are_ints (T base, T inc, T final_val, octave_idx_type nel) - { - // If the range is empty or NaN then there are no elements so there - // can be no int elements. - if (nel == 0 || math::isnan (final_val)) - return false; +template +bool xall_elements_are_ints (T base, T inc, T final_val, octave_idx_type nel) +{ + // If the range is empty or NaN then there are no elements so there + // can be no int elements. + if (nel == 0 || math::isnan (final_val)) + return false; - // If the base and increment are ints, all elements will be - // integers. - if (math::nint_big (base) == base && math::nint_big (inc) == inc) - return true; + // If the base and increment are ints, all elements will be + // integers. + if (math::nint_big (base) == base && math::nint_big (inc) == inc) + return true; - // If the range has only one element, then the base needs to be an - // integer. - if (nel == 1 && math::nint_big (base)) - return true; + // If the range has only one element, then the base needs to be an + // integer. + if (nel == 1 && math::nint_big (base)) + return true; - return false; - } + return false; +} - template - T - xfinal_value (T base, T limit, T inc, octave_idx_type nel) - { - T retval = T (0); +template +T +xfinal_value (T base, T limit, T inc, octave_idx_type nel) +{ + T retval = T (0); - if (nel <= 1) - return base; + if (nel <= 1) + return base; - // If increment is 0, then numel should also be zero. + // If increment is 0, then numel should also be zero. - retval = base + (nel - 1) * inc; + retval = base + (nel - 1) * 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. + // 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. - // NOTE: The test also includes equality (>= limit) to have - // expressions such as -5:1:-0 result in a -0 endpoint. + // NOTE: The test also includes equality (>= limit) to have + // expressions such as -5:1:-0 result in a -0 endpoint. - if ((inc > T (0) && retval >= limit) || (inc < T (0) && retval <= limit)) - retval = limit; + if ((inc > T (0) && retval >= limit) || (inc < T (0) && retval <= limit)) + retval = limit; - // If all elements are integers, then ensure the final value is. - // Note that we pass the preliminary computed final value to - // xall_elements_are_ints, but it only checks whether that value is - // NaN. + // If all elements are integers, then ensure the final value is. + // Note that we pass the preliminary computed final value to + // xall_elements_are_ints, but it only checks whether that value is + // NaN. - if (xall_elements_are_ints (base, inc, retval, nel)) - retval = std::round (retval); + if (xall_elements_are_ints (base, inc, retval, nel)) + retval = std::round (retval); - return retval; - } + return retval; +} - template - void - xinit (T base, T limit, T inc, bool reverse, T& final_val, - octave_idx_type& nel) - { - // Catch obvious NaN ranges. - if (math::isnan (base) || math::isnan (limit) || math::isnan (inc)) - { - final_val = numeric_limits::NaN (); - nel = 1; - return; - } +template +void +xinit (T base, T limit, T inc, bool reverse, T& final_val, + octave_idx_type& nel) +{ + // Catch obvious NaN ranges. + if (math::isnan (base) || math::isnan (limit) || math::isnan (inc)) + { + final_val = numeric_limits::NaN (); + nel = 1; + return; + } - // Floating point numbers are always signed - if (reverse) - inc = -inc; + // Floating point numbers are always signed + if (reverse) + inc = -inc; - // Catch empty ranges. - if (inc == 0 - || (limit < base && inc > 0) - || (limit > base && inc < 0)) - { - nel = 0; - return; - } + // Catch empty ranges. + if (inc == 0 + || (limit < base && inc > 0) + || (limit > base && inc < 0)) + { + nel = 0; + return; + } - // The following case also catches Inf values for increment when - // there will be only one element. + // The following case also catches Inf values for increment when + // there will be only one element. - if ((limit <= base && base + inc < limit) - || (limit >= base && base + inc > limit)) - { - final_val = base; - nel = 1; - return; - } + if ((limit <= base && base + inc < limit) + || (limit >= base && base + inc > limit)) + { + final_val = base; + nel = 1; + return; + } - // Any other calculations with Inf will give us either a NaN range - // or an infinite nember of elements. + // Any other calculations with Inf will give us either a NaN range + // or an infinite nember of elements. - T dnel = (limit - base) / inc; - if (math::isnan (dnel)) - { - nel = 1; - final_val = numeric_limits::NaN (); - return; - } + T dnel = (limit - base) / inc; + if (math::isnan (dnel)) + { + nel = 1; + final_val = numeric_limits::NaN (); + return; + } - if (dnel > 0 && math::isinf (dnel)) - { - // FIXME: Should this be an immediate error? - nel = std::numeric_limits::max (); + if (dnel > 0 && math::isinf (dnel)) + { + // FIXME: Should this be an immediate error? + nel = std::numeric_limits::max (); - // FIXME: Will this do the right thing in all cases? - final_val = xfinal_value (base, limit, inc, nel); + // FIXME: Will this do the right thing in all cases? + final_val = xfinal_value (base, limit, inc, nel); - return; - } + return; + } - // Now that we have handled all the special cases, we can compute - // the number of elements and the final value in a way that attempts - // to avoid rounding errors as much as possible. + // Now that we have handled all the special cases, we can compute + // the number of elements and the final value in a way that attempts + // to avoid rounding errors as much as possible. - nel = xnumel_internal (base, limit, inc); - final_val = xfinal_value (base, limit, inc, nel); - } + nel = xnumel_internal (base, limit, inc); + final_val = xfinal_value (base, limit, inc, nel); +} - template - void - xinit (const octave_int& base, const octave_int& limit, - const octave_int& inc, bool reverse, - octave_int& final_val, octave_idx_type& nel) - { - // We need an integer division that is truncating decimals instead - // of rounding. So, use underlying C++ types instead of - // octave_int. +template +void +xinit (const octave_int& base, const octave_int& limit, + const octave_int& inc, bool reverse, + octave_int& final_val, octave_idx_type& nel) +{ + // We need an integer division that is truncating decimals instead + // of rounding. So, use underlying C++ types instead of + // octave_int. - // FIXME: The numerator might underflow or overflow. Add checks for - // that. - if (reverse) - { - nel = ((inc == octave_int (0) - || (limit > base && inc > octave_int (0)) - || (limit < base && inc < octave_int (0))) - ? 0 - : (base.value () - limit.value () + inc.value ()) - / inc.value ()); + // FIXME: The numerator might underflow or overflow. Add checks for + // that. + if (reverse) + { + nel = ((inc == octave_int (0) + || (limit > base && inc > octave_int (0)) + || (limit < base && inc < octave_int (0))) + ? 0 + : (base.value () - limit.value () + inc.value ()) + / inc.value ()); - final_val = base - (nel - 1) * inc; - } - else - { - nel = ((inc == octave_int (0) - || (limit > base && inc < octave_int (0)) - || (limit < base && inc > octave_int (0))) - ? 0 - : (limit.value () - base.value () + inc.value ()) - / inc.value ()); + final_val = base - (nel - 1) * inc; + } + else + { + nel = ((inc == octave_int (0) + || (limit > base && inc < octave_int (0)) + || (limit < base && inc > octave_int (0))) + ? 0 + : (limit.value () - base.value () + inc.value ()) + / inc.value ()); - final_val = base + (nel - 1) * inc; - } - } + final_val = base + (nel - 1) * inc; + } +} - template - bool - xis_storable (T base, T limit, octave_idx_type nel) - { - return ! (nel > 1 && (math::isinf (base) || math::isinf (limit))); - } +template +bool +xis_storable (T base, T limit, octave_idx_type nel) +{ + return ! (nel > 1 && (math::isinf (base) || math::isinf (limit))); +} - template <> - bool - range::all_elements_are_ints (void) const - { - return xall_elements_are_ints (m_base, m_increment, m_final, m_numel); - } +template <> +bool +range::all_elements_are_ints (void) const +{ + return xall_elements_are_ints (m_base, m_increment, m_final, m_numel); +} - template <> - bool - range::all_elements_are_ints (void) const - { - return xall_elements_are_ints (m_base, m_increment, m_final, m_numel); - } +template <> +bool +range::all_elements_are_ints (void) const +{ + return xall_elements_are_ints (m_base, m_increment, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - // For now, only define for float and double. +// For now, only define for float and double. #if 0 - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} - template <> - void - range::init (void) - { - xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); - } +template <> +void +range::init (void) +{ + xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); +} #endif - template <> - bool - range::is_storable (void) const - { - return xis_storable (m_base, m_limit, m_numel); - } +template <> +bool +range::is_storable (void) const +{ + return xis_storable (m_base, m_limit, m_numel); +} - template <> - bool - range::is_storable (void) const - { - return xis_storable (m_base, m_limit, m_numel); - } +template <> +bool +range::is_storable (void) const +{ + return xis_storable (m_base, m_limit, m_numel); +} - template - octave_idx_type - xnnz (T base, T limit, T inc, T final_val, octave_idx_type nel) - { - // Note that the order of the following checks matters. +template +octave_idx_type +xnnz (T base, T limit, T inc, T final_val, octave_idx_type nel) +{ + // Note that the order of the following checks matters. - // If there are no elements, there can be no non-zero elements. - if (nel == 0) - return 0; + // If there are no elements, there can be no non-zero elements. + if (nel == 0) + return 0; - // All elements have the same sign, hence there are no zeros. - if ((base > 0 && limit > 0) || (base < 0 && limit < 0)) - return nel; + // All elements have the same sign, hence there are no zeros. + if ((base > 0 && limit > 0) || (base < 0 && limit < 0)) + return nel; - // All elements are equal (inc = 0) but we know from the previous - // condition that they are not positive or negative, therefore all - // elements are zero. - if (inc == 0) - return 0; + // All elements are equal (inc = 0) but we know from the previous + // condition that they are not positive or negative, therefore all + // elements are zero. + if (inc == 0) + return 0; - // Exactly one zero at beginning or end of range. - if (base == 0 || final_val == 0) - return nel - 1; + // Exactly one zero at beginning or end of range. + if (base == 0 || final_val == 0) + return nel - 1; - // Range crosses negative/positive without hitting zero. - // FIXME: Is this test sufficiently tolerant or do we need to be - // more careful? - if (math::mod (-base, inc) != 0) - return nel; + // Range crosses negative/positive without hitting zero. + // FIXME: Is this test sufficiently tolerant or do we need to be + // more careful? + if (math::mod (-base, inc) != 0) + return nel; - // Range crosses negative/positive and hits zero. - return nel - 1; - } + // Range crosses negative/positive and hits zero. + return nel - 1; +} - template <> - octave_idx_type - range::nnz (void) const - { - return xnnz (m_base, m_limit, m_increment, m_final, m_numel); - } +template <> +octave_idx_type +range::nnz (void) const +{ + return xnnz (m_base, m_limit, m_increment, m_final, m_numel); +} - template <> - octave_idx_type - range::nnz (void) const - { - return xnnz (m_base, m_limit, m_increment, m_final, m_numel); - } +template <> +octave_idx_type +range::nnz (void) const +{ + return xnnz (m_base, m_limit, m_increment, m_final, m_numel); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/array/Range.h diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/array/idx-vector.cc --- a/liboctave/array/idx-vector.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/array/idx-vector.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,1237 +44,1237 @@ OCTAVE_BEGIN_NAMESPACE(octave) - OCTAVE_NORETURN static void err_invalid_range (void) - { - (*current_liboctave_error_handler) ("invalid range used as index"); - } - - OCTAVE_NORETURN static void err_index_out_of_range (void) - { - (*current_liboctave_error_handler) - ("internal error: idx_vector index out of range"); - } +OCTAVE_NORETURN static void err_invalid_range (void) +{ + (*current_liboctave_error_handler) ("invalid range used as index"); +} - idx_vector::idx_vector_rep * idx_vector::nil_rep (void) - { - static idx_vector_rep ivr; - return &ivr; - } - - Array idx_vector::idx_base_rep::as_array (void) - { - (*current_liboctave_error_handler) - ("internal error: as_array not allowed for this index class"); +OCTAVE_NORETURN static void err_index_out_of_range (void) +{ + (*current_liboctave_error_handler) + ("internal error: idx_vector index out of range"); +} - // Never actually executed, but required to silence compiler warning - return Array (); - } - - idx_vector::idx_colon_rep::idx_colon_rep (char c) - : idx_base_rep () - { - if (c != ':') - (*current_liboctave_error_handler) - ("internal error: invalid character converted to idx_vector; must be ':'"); - } +idx_vector::idx_vector_rep *idx_vector::nil_rep (void) +{ + static idx_vector_rep ivr; + return &ivr; +} - octave_idx_type - idx_vector::idx_colon_rep::checkelem (octave_idx_type i) const - { - if (i < 0) - err_index_out_of_range (); +Array idx_vector::idx_base_rep::as_array (void) +{ + (*current_liboctave_error_handler) + ("internal error: as_array not allowed for this index class"); - return i; - } + // Never actually executed, but required to silence compiler warning + return Array (); +} - idx_vector::idx_base_rep * - idx_vector::idx_colon_rep::sort_idx (Array&) - { +idx_vector::idx_colon_rep::idx_colon_rep (char c) + : idx_base_rep () +{ + if (c != ':') (*current_liboctave_error_handler) - ("internal error: idx_colon_rep::sort_idx"); - } + ("internal error: invalid character converted to idx_vector; must be ':'"); +} + +octave_idx_type +idx_vector::idx_colon_rep::checkelem (octave_idx_type i) const +{ + if (i < 0) + err_index_out_of_range (); + + return i; +} + +idx_vector::idx_base_rep * +idx_vector::idx_colon_rep::sort_idx (Array&) +{ + (*current_liboctave_error_handler) + ("internal error: idx_colon_rep::sort_idx"); +} + +std::ostream& idx_vector::idx_colon_rep::print (std::ostream& os) const +{ + return os << ':'; +} + +idx_vector::idx_range_rep::idx_range_rep (octave_idx_type start, + octave_idx_type limit, + octave_idx_type step) + : idx_base_rep (), m_start(start), + // Round length away from zero to catch incomplete intervals + m_len (step + ? std::max ((limit - start + step - (step > 0 ? 1 : -1)) / step, + static_cast (0)) + : -1), + m_step (step) +{ + if (m_len < 0) + err_invalid_range (); + if (m_start < 0) + err_invalid_index (m_start); + if (m_step < 0 && m_start + (m_len-1)*m_step < 0) + err_invalid_index (m_start + (m_len-1)*m_step); +} + +idx_vector::idx_range_rep::idx_range_rep (const range& r) + : idx_base_rep (), m_start (0), m_len (r.numel ()), m_step (1) +{ + if (m_len < 0) + err_invalid_range (); + + if (m_len > 0) + { + if (r.all_elements_are_ints ()) + { + m_start = static_cast (r.base ()) - 1; + m_step = static_cast (r.increment ()); + if (m_start < 0) + err_invalid_index (m_start); + if (m_step < 0 && m_start + (m_len - 1)*m_step < 0) + err_invalid_index (m_start + (m_len - 1)*m_step); + } + else + { + // find first non-integer, then gripe about it + double b = r.base (); + double inc = r.increment (); + err_invalid_index (b != std::trunc (b) ? b : b + inc); + } + } +} + +octave_idx_type +idx_vector::idx_range_rep::checkelem (octave_idx_type i) const +{ + if (i < 0 || i >= m_len) + err_index_out_of_range (); + + return m_start + i*m_step; +} + +idx_vector::idx_base_rep *idx_vector::idx_range_rep::sort_uniq_clone (bool) +{ + if (m_step < 0) + return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT); + else + { + m_count++; + return this; + } +} + +idx_vector::idx_base_rep * +idx_vector::idx_range_rep::sort_idx (Array& idx) +{ + if (m_step < 0 && m_len > 0) + { + idx.clear (1, m_len); + for (octave_idx_type i = 0; i < m_len; i++) + idx.xelem (i) = m_len - 1 - i; + return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT); + } + else + { + idx.clear (1, m_len); + for (octave_idx_type i = 0; i < m_len; i++) + idx.xelem (i) = i; + m_count++; + return this; + } +} + +std::ostream& idx_vector::idx_range_rep::print (std::ostream& os) const +{ + os << m_start << ':' << m_step << ':' << m_start + m_len *m_step; + return os; +} + +range idx_vector::idx_range_rep::unconvert (void) const +{ + return range::make_n_element_range + (static_cast (m_start+1), static_cast (m_step), m_len); +} + +Array idx_vector::idx_range_rep::as_array (void) +{ + Array retval (dim_vector (1, m_len)); + for (octave_idx_type i = 0; i < m_len; i++) + retval.xelem (i) = m_start + i*m_step; + + return retval; +} + +inline octave_idx_type convert_index (octave_idx_type i, octave_idx_type& ext) +{ + if (i <= 0) + err_invalid_index (i-1); + + if (ext < i) + ext = i; + + return i - 1; +} + +inline octave_idx_type convert_index (double x, octave_idx_type& ext) +{ + octave_idx_type i = static_cast (x); + + if (static_cast (i) != x) + err_invalid_index (x-1); + + return convert_index (i, ext); +} + +inline octave_idx_type convert_index (float x, octave_idx_type& ext) +{ + return convert_index (static_cast (x), ext); +} + +template +inline octave_idx_type convert_index (octave_int x, octave_idx_type& ext) +{ + octave_idx_type i = octave_int (x).value (); + + return convert_index (i, ext); +} + +template +idx_vector::idx_scalar_rep::idx_scalar_rep (T x) + : idx_base_rep (), m_data (0) +{ + octave_idx_type dummy = 0; + + m_data = convert_index (x, dummy); +} + +idx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i) + : idx_base_rep (), m_data (i) +{ + if (m_data < 0) + err_invalid_index (m_data); +} + +octave_idx_type +idx_vector::idx_scalar_rep::checkelem (octave_idx_type i) const +{ + if (i != 0) + err_index_out_of_range (); + + return m_data; +} + +idx_vector::idx_base_rep * +idx_vector::idx_scalar_rep::sort_idx (Array& idx) +{ + idx.clear (1, 1); + idx.fill (0); + m_count++; + return this; +} + +std::ostream& idx_vector::idx_scalar_rep::print (std::ostream& os) const +{ + return os << m_data; +} + +double idx_vector::idx_scalar_rep::unconvert (void) const +{ + return m_data + 1; +} - std::ostream& idx_vector::idx_colon_rep::print (std::ostream& os) const - { - return os << ':'; - } +Array idx_vector::idx_scalar_rep::as_array (void) +{ + return Array (dim_vector (1, 1), m_data); +} + +template +idx_vector::idx_vector_rep::idx_vector_rep (const Array& nda) + : idx_base_rep (), m_data (nullptr), m_len (nda.numel ()), m_ext (0), + m_aowner (nullptr), m_orig_dims (nda.dims ()) +{ + if (m_len != 0) + { + std::unique_ptr d (new octave_idx_type [m_len]); + + for (octave_idx_type i = 0; i < m_len; i++) + d[i] = convert_index (nda.xelem (i), m_ext); + + m_data = d.release (); + } +} + +// Note that this makes a shallow copy of the index array. + +idx_vector::idx_vector_rep::idx_vector_rep (const Array& inda) + : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()), m_ext (0), + m_aowner (new Array (inda)), m_orig_dims (inda.dims ()) +{ + if (m_len != 0) + { + octave_idx_type max = -1; + for (octave_idx_type i = 0; i < m_len; i++) + { + octave_idx_type k = inda.xelem (i); + if (k < 0) + err_invalid_index (k); + else if (k > max) + max = k; + } + + m_ext = max + 1; + } +} + +idx_vector::idx_vector_rep::idx_vector_rep (const Array& inda, + octave_idx_type ext, direct) + : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()), + m_ext (ext), m_aowner (new Array (inda)), + m_orig_dims (inda.dims ()) +{ + // No checking. + if (m_ext < 0) + { + octave_idx_type max = -1; + for (octave_idx_type i = 0; i < m_len; i++) + if (m_data[i] > max) + max = m_data[i]; + + m_ext = max + 1; + } +} + +idx_vector::idx_vector_rep::idx_vector_rep (bool b) + : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0), + m_aowner (nullptr), m_orig_dims (m_len, m_len) +{ + if (m_len != 0) + { + octave_idx_type *d = new octave_idx_type [1]; + d[0] = 0; + m_data = d; + m_ext = 1; + } +} + +idx_vector::idx_vector_rep::idx_vector_rep (const Array& bnda, + octave_idx_type nnz) + : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (0), + m_aowner (nullptr), m_orig_dims () +{ + if (nnz < 0) + m_len = bnda.nnz (); + + const dim_vector dv = bnda.dims (); + + m_orig_dims = dv.make_nd_vector (m_len); + + if (m_len != 0) + { + octave_idx_type *d = new octave_idx_type [m_len]; + + octave_idx_type ntot = bnda.numel (); + + octave_idx_type k = 0; + for (octave_idx_type i = 0; i < ntot; i++) + if (bnda.xelem (i)) + d[k++] = i; + + m_data = d; + + m_ext = d[k-1] + 1; + } +} + +idx_vector::idx_vector_rep::idx_vector_rep (const Sparse& bnda) + : idx_base_rep (), m_data (nullptr), m_len (bnda.nnz ()), m_ext (0), + m_aowner (nullptr), m_orig_dims () +{ + const dim_vector dv = bnda.dims (); + + m_orig_dims = dv.make_nd_vector (m_len); + + if (m_len != 0) + { + octave_idx_type *d = new octave_idx_type [m_len]; + + octave_idx_type k = 0; + octave_idx_type nc = bnda.cols (); + octave_idx_type nr = bnda.rows (); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = bnda.cidx (j); i < bnda.cidx (j+1); i++) + if (bnda.data (i)) + d[k++] = j * nr + bnda.ridx (i); + + m_data = d; + + m_ext = d[k-1] + 1; + } +} + +idx_vector::idx_vector_rep::~idx_vector_rep (void) +{ + if (m_aowner) + delete m_aowner; + else + delete [] m_data; +} + +octave_idx_type +idx_vector::idx_vector_rep::checkelem (octave_idx_type n) const +{ + if (n < 0 || n >= m_len) + err_invalid_index (n); + + return xelem (n); +} + +idx_vector::idx_base_rep * +idx_vector::idx_vector_rep::sort_uniq_clone (bool uniq) +{ + if (m_len == 0) + { + m_count++; + return this; + } + + // This is wrapped in unique_ptr so that we don't leak on out-of-memory. + std::unique_ptr new_rep + (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT)); + + if (m_ext > m_len*math::log2 (1.0 + m_len)) + { + // Use standard sort via octave_sort. + octave_idx_type *new_data = new octave_idx_type [m_len]; + new_rep->m_data = new_data; + + std::copy_n (m_data, m_len, new_data); + octave_sort lsort; + lsort.set_compare (ASCENDING); + lsort.sort (new_data, m_len); + + if (uniq) + { + octave_idx_type new_len = std::unique (new_data, new_data + m_len) + - new_data; + new_rep->m_len = new_len; + if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1) + new_rep->m_orig_dims = dim_vector (1, new_len); + else + new_rep->m_orig_dims = dim_vector (new_len, 1); + } + } + else if (uniq) + { + // Use two-pass bucket sort (only a mask array needed). + OCTAVE_LOCAL_BUFFER_INIT (bool, has, m_ext, false); + for (octave_idx_type i = 0; i < m_len; i++) + has[m_data[i]] = true; + + octave_idx_type new_len = 0; + for (octave_idx_type i = 0; i < m_ext; i++) + new_len += has[i]; + + new_rep->m_len = new_len; + if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1) + new_rep->m_orig_dims = dim_vector (1, new_len); + else + new_rep->m_orig_dims = dim_vector (new_len, 1); + + octave_idx_type *new_data = new octave_idx_type [new_len]; + new_rep->m_data = new_data; + + for (octave_idx_type i = 0, j = 0; i < m_ext; i++) + if (has[i]) + new_data[j++] = i; + } + else + { + // Use two-pass bucket sort. + OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, cnt, m_ext, 0); + for (octave_idx_type i = 0; i < m_len; i++) + cnt[m_data[i]]++; + + octave_idx_type *new_data = new octave_idx_type [m_len]; + new_rep->m_data = new_data; - idx_vector::idx_range_rep::idx_range_rep (octave_idx_type start, - octave_idx_type limit, - octave_idx_type step) - : idx_base_rep (), m_start(start), - // Round length away from zero to catch incomplete intervals - m_len (step - ? std::max ((limit - start + step - (step > 0 ? 1 : -1)) / step, - static_cast (0)) - : -1), - m_step (step) - { - if (m_len < 0) - err_invalid_range (); - if (m_start < 0) - err_invalid_index (m_start); - if (m_step < 0 && m_start + (m_len-1)*m_step < 0) - err_invalid_index (m_start + (m_len-1)*m_step); - } + for (octave_idx_type i = 0, j = 0; i < m_ext; i++) + { + for (octave_idx_type k = 0; k < cnt[i]; k++) + new_data[j++] = i; + } + } + + return new_rep.release (); +} + +idx_vector::idx_base_rep * +idx_vector::idx_vector_rep::sort_idx (Array& idx) +{ + // This is wrapped in unique_ptr so that we don't leak on out-of-memory. + std::unique_ptr new_rep + (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT)); + + if (m_ext > m_len*math::log2 (1.0 + m_len)) + { + // Use standard sort via octave_sort. + idx.clear (m_orig_dims); + octave_idx_type *idx_data = idx.fortran_vec (); + for (octave_idx_type i = 0; i < m_len; i++) + idx_data[i] = i; + + octave_idx_type *new_data = new octave_idx_type [m_len]; + new_rep->m_data = new_data; + std::copy_n (m_data, m_len, new_data); + + octave_sort lsort; + lsort.set_compare (ASCENDING); + lsort.sort (new_data, idx_data, m_len); + } + else + { + // Use two-pass bucket sort. + OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, cnt, m_ext, 0); + + for (octave_idx_type i = 0; i < m_len; i++) + cnt[m_data[i]]++; + + idx.clear (m_orig_dims); + octave_idx_type *idx_data = idx.fortran_vec (); + + octave_idx_type *new_data = new octave_idx_type [m_len]; + new_rep->m_data = new_data; + + for (octave_idx_type i = 0, k = 0; i < m_ext; i++) + { + octave_idx_type j = cnt[i]; + cnt[i] = k; + k += j; + } + + for (octave_idx_type i = 0; i < m_len; i++) + { + octave_idx_type j = m_data[i]; + octave_idx_type k = cnt[j]++; + new_data[k] = j; + idx_data[k] = i; + } + } + + return new_rep.release (); +} + +std::ostream& idx_vector::idx_vector_rep::print (std::ostream& os) const +{ + os << '['; + + for (octave_idx_type i = 0; i < m_len - 1; i++) + os << m_data[i] << ',' << ' '; + + if (m_len > 0) + os << m_data[m_len-1]; + + os << ']'; + + return os; +} + +Array idx_vector::idx_vector_rep::unconvert (void) const +{ + Array retval (m_orig_dims); + for (octave_idx_type i = 0; i < m_len; i++) + retval.xelem (i) = m_data[i] + 1; + return retval; +} + +Array idx_vector::idx_vector_rep::as_array (void) +{ + if (m_aowner) + return *m_aowner; + else + { + Array retval (m_orig_dims); + + if (m_data) + { + std::memcpy (retval.fortran_vec (), m_data, m_len* sizeof (octave_idx_type)); + // Delete the old copy and share the m_data instead to save memory. + delete [] m_data; + } + + m_data = retval.fortran_vec (); + m_aowner = new Array (retval); + + return retval; + } +} + +idx_vector::idx_mask_rep::idx_mask_rep (bool b) + : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0), + m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (m_len, m_len) +{ + if (m_len != 0) + { + bool *d = new bool [1]; + d[0] = true; + m_data = d; + m_ext = 1; + } +} + +idx_vector::idx_mask_rep::idx_mask_rep (const Array& bnda, + octave_idx_type nnz) + : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (bnda.numel ()), + m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims () +{ + if (nnz < 0) + m_len = bnda.nnz (); + + // We truncate the extent as much as possible. For Matlab + // compatibility, but maybe it's not a bad idea anyway. + while (m_ext > 0 && ! bnda(m_ext-1)) + m_ext--; + + const dim_vector dv = bnda.dims (); + + m_orig_dims = dv.make_nd_vector (m_len); + + m_aowner = new Array (bnda); + m_data = bnda.data (); +} + +idx_vector::idx_mask_rep::~idx_mask_rep (void) +{ + if (m_aowner) + delete m_aowner; + else + delete [] m_data; +} + +octave_idx_type idx_vector::idx_mask_rep::xelem (octave_idx_type n) const +{ + if (n == m_lsti + 1) + { + m_lsti = n; + while (! m_data[++m_lste]) ; + } + else + { + m_lsti = n++; + m_lste = -1; + while (n > 0) + if (m_data[++m_lste]) --n; + } + return m_lste; +} + +octave_idx_type idx_vector::idx_mask_rep::checkelem (octave_idx_type n) const +{ + if (n < 0 || n >= m_len) + err_invalid_index (n); + + return xelem (n); +} + +std::ostream& idx_vector::idx_mask_rep::print (std::ostream& os) const +{ + os << '['; + + for (octave_idx_type i = 0; i < m_ext - 1; i++) + os << m_data[i] << ',' << ' '; + + if (m_ext > 0) + os << m_data[m_ext-1]; + + os << ']'; + + return os; +} + +Array idx_vector::idx_mask_rep::unconvert (void) const +{ + if (m_aowner) + return *m_aowner; + else + { + Array retval (dim_vector (m_ext, 1)); + for (octave_idx_type i = 0; i < m_ext; i++) + retval.xelem (i) = m_data[i]; + return retval; + } +} + +Array idx_vector::idx_mask_rep::as_array (void) +{ + if (m_aowner) + return m_aowner->find ().reshape (m_orig_dims); + else + { + Array retval (m_orig_dims); + for (octave_idx_type i = 0, j = 0; i < m_ext; i++) + if (m_data[i]) + retval.xelem (j++) = i; - idx_vector::idx_range_rep::idx_range_rep (const range& r) - : idx_base_rep (), m_start (0), m_len (r.numel ()), m_step (1) - { - if (m_len < 0) - err_invalid_range (); + return retval; + } +} + +idx_vector::idx_base_rep * +idx_vector::idx_mask_rep::sort_idx (Array& idx) +{ + idx.clear (m_len, 1); + for (octave_idx_type i = 0; i < m_len; i++) + idx.xelem (i) = i; + + m_count++; + return this; +} + +const idx_vector idx_vector::colon (new idx_vector::idx_colon_rep ()); + +idx_vector::idx_vector (const Array& bnda) + : m_rep (nullptr) +{ + // Convert only if it means saving at least half the memory. + static const int factor = (2 * sizeof (octave_idx_type)); + octave_idx_type nnz = bnda.nnz (); + if (nnz <= bnda.numel () / factor) + m_rep = new idx_vector_rep (bnda, nnz); + else + m_rep = new idx_mask_rep (bnda, nnz); +} + +bool idx_vector::maybe_reduce (octave_idx_type n, const idx_vector& j, + octave_idx_type nj) +{ + bool reduced = false; + + // Empty index always reduces. + if (m_rep->length (n) == 0) + { + *this = idx_vector (); + return true; + } + + // Possibly skip singleton dims. + if (n == 1 && m_rep->is_colon_equiv (n)) + { + *this = j; + return true; + } - if (m_len > 0) - { - if (r.all_elements_are_ints ()) + if (nj == 1 && j.is_colon_equiv (nj)) + return true; + + switch (j.idx_class ()) + { + case class_colon: + switch (m_rep->idx_class ()) + { + case class_colon: + // (:,:) reduces to (:) + reduced = true; + break; + + case class_scalar: + { + // (i,:) reduces to a range. + idx_scalar_rep *r = dynamic_cast (m_rep); + octave_idx_type k = r->get_data (); + *this = new idx_range_rep (k, nj, n, DIRECT); + reduced = true; + } + break; + + case class_range: + { + // (i:k:end,:) reduces to a range if i <= k and k divides n. + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type s = r->get_start (); + octave_idx_type l = r->length (n); + octave_idx_type t = r->get_step (); + if (l*t == n) + { + *this = new idx_range_rep (s, l * nj, t, DIRECT); + reduced = true; + } + } + break; + + default: + break; + } + break; + + case class_range: + switch (m_rep->idx_class ()) + { + case class_colon: { - m_start = static_cast (r.base ()) - 1; - m_step = static_cast (r.increment ()); - if (m_start < 0) - err_invalid_index (m_start); - if (m_step < 0 && m_start + (m_len - 1)*m_step < 0) - err_invalid_index (m_start + (m_len - 1)*m_step); + // (:,i:j) reduces to a range (the m_step must be 1) + idx_range_rep *rj = dynamic_cast (j.m_rep); + if (rj->get_step () == 1) + { + octave_idx_type sj = rj->get_start (); + octave_idx_type lj = rj->length (nj); + *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT); + reduced = true; + } + } + break; + + case class_scalar: + { + // (k,i:d:j) reduces to a range. + idx_scalar_rep *r = dynamic_cast (m_rep); + idx_range_rep *rj = dynamic_cast (j.m_rep); + octave_idx_type k = r->get_data (); + octave_idx_type sj = rj->get_start (); + octave_idx_type lj = rj->length (nj); + octave_idx_type tj = rj->get_step (); + *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT); + reduced = true; + } + break; + + case class_range: + { + // (i:k:end,p:q) reduces to a range if i <= k and k divides n. + // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n)) + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type s = r->get_start (); + octave_idx_type l = r->length (n); + octave_idx_type t = r->get_step (); + idx_range_rep *rj = dynamic_cast (j.m_rep); + octave_idx_type sj = rj->get_start (); + octave_idx_type lj = rj->length (nj); + octave_idx_type tj = rj->get_step (); + if ((l*t == n && tj == 1) || (t == 0 && tj == 0)) + { + *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT); + reduced = true; + } } - else + break; + + default: + break; + } + break; + + case class_scalar: + switch (m_rep->idx_class ()) + { + case class_scalar: + { + // (i,j) reduces to a single index. + idx_scalar_rep *r = dynamic_cast (m_rep); + idx_scalar_rep *rj = dynamic_cast (j.m_rep); + octave_idx_type k = r->get_data () + n * rj->get_data (); + *this = new idx_scalar_rep (k, DIRECT); + reduced = true; + } + break; + + case class_range: + { + // (i:d:j,k) reduces to a range. + idx_range_rep *r = dynamic_cast (m_rep); + idx_scalar_rep *rj = dynamic_cast (j.m_rep); + octave_idx_type s = r->get_start (); + octave_idx_type l = r->length (nj); + octave_idx_type t = r->get_step (); + octave_idx_type k = rj->get_data (); + *this = new idx_range_rep (n * k + s, l, t, DIRECT); + reduced = true; + } + break; + + case class_colon: { - // find first non-integer, then gripe about it - double b = r.base (); - double inc = r.increment (); - err_invalid_index (b != std::trunc (b) ? b : b + inc); + // (:,k) reduces to a range. + idx_scalar_rep *rj = dynamic_cast (j.m_rep); + octave_idx_type k = rj->get_data (); + *this = new idx_range_rep (n * k, n, 1, DIRECT); + reduced = true; + } + break; + + default: + break; + } + break; + + default: + break; + } + + return reduced; +} + +bool idx_vector::is_cont_range (octave_idx_type n, octave_idx_type& l, + octave_idx_type& u) const +{ + bool res = false; + + switch (m_rep->idx_class ()) + { + case class_colon: + l = 0; u = n; + res = true; + break; + + case class_range: + { + idx_range_rep *r = dynamic_cast (m_rep); + if (r->get_step () == 1) + { + l = r->get_start (); + u = l + r->length (n); + res = true; } } - } - - octave_idx_type - idx_vector::idx_range_rep::checkelem (octave_idx_type i) const - { - if (i < 0 || i >= m_len) - err_index_out_of_range (); - - return m_start + i*m_step; - } - - idx_vector::idx_base_rep * idx_vector::idx_range_rep::sort_uniq_clone (bool) - { - if (m_step < 0) - return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT); - else - { - m_count++; - return this; - } - } - - idx_vector::idx_base_rep * - idx_vector::idx_range_rep::sort_idx (Array& idx) - { - if (m_step < 0 && m_len > 0) - { - idx.clear (1, m_len); - for (octave_idx_type i = 0; i < m_len; i++) - idx.xelem (i) = m_len - 1 - i; - return new idx_range_rep (m_start + (m_len - 1)*m_step, m_len, -m_step, DIRECT); - } - else - { - idx.clear (1, m_len); - for (octave_idx_type i = 0; i < m_len; i++) - idx.xelem (i) = i; - m_count++; - return this; - } - } - - std::ostream& idx_vector::idx_range_rep::print (std::ostream& os) const - { - os << m_start << ':' << m_step << ':' << m_start + m_len*m_step; - return os; - } - - range idx_vector::idx_range_rep::unconvert (void) const - { - return range::make_n_element_range - (static_cast (m_start+1), static_cast (m_step), m_len); - } - - Array idx_vector::idx_range_rep::as_array (void) - { - Array retval (dim_vector (1, m_len)); - for (octave_idx_type i = 0; i < m_len; i++) - retval.xelem (i) = m_start + i*m_step; - - return retval; - } - - inline octave_idx_type convert_index (octave_idx_type i, octave_idx_type& ext) - { - if (i <= 0) - err_invalid_index (i-1); - - if (ext < i) - ext = i; - - return i - 1; - } - - inline octave_idx_type convert_index (double x, octave_idx_type& ext) - { - octave_idx_type i = static_cast (x); - - if (static_cast (i) != x) - err_invalid_index (x-1); - - return convert_index (i, ext); - } - - inline octave_idx_type convert_index (float x, octave_idx_type& ext) - { - return convert_index (static_cast (x), ext); - } - - template - inline octave_idx_type convert_index (octave_int x, octave_idx_type& ext) - { - octave_idx_type i = octave_int (x).value (); - - return convert_index (i, ext); - } - - template - idx_vector::idx_scalar_rep::idx_scalar_rep (T x) - : idx_base_rep (), m_data (0) - { - octave_idx_type dummy = 0; + break; - m_data = convert_index (x, dummy); - } - - idx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i) - : idx_base_rep (), m_data (i) - { - if (m_data < 0) - err_invalid_index (m_data); - } - - octave_idx_type - idx_vector::idx_scalar_rep::checkelem (octave_idx_type i) const - { - if (i != 0) - err_index_out_of_range (); - - return m_data; - } - - idx_vector::idx_base_rep * - idx_vector::idx_scalar_rep::sort_idx (Array& idx) - { - idx.clear (1, 1); - idx.fill (0); - m_count++; - return this; - } - - std::ostream& idx_vector::idx_scalar_rep::print (std::ostream& os) const - { - return os << m_data; - } - - double idx_vector::idx_scalar_rep::unconvert (void) const - { - return m_data + 1; - } - - Array idx_vector::idx_scalar_rep::as_array (void) - { - return Array (dim_vector (1, 1), m_data); - } - - template - idx_vector::idx_vector_rep::idx_vector_rep (const Array& nda) - : idx_base_rep (), m_data (nullptr), m_len (nda.numel ()), m_ext (0), - m_aowner (nullptr), m_orig_dims (nda.dims ()) - { - if (m_len != 0) - { - std::unique_ptr d (new octave_idx_type [m_len]); - - for (octave_idx_type i = 0; i < m_len; i++) - d[i] = convert_index (nda.xelem (i), m_ext); - - m_data = d.release (); - } - } - - // Note that this makes a shallow copy of the index array. - - idx_vector::idx_vector_rep::idx_vector_rep (const Array& inda) - : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()), m_ext (0), - m_aowner (new Array (inda)), m_orig_dims (inda.dims ()) - { - if (m_len != 0) - { - octave_idx_type max = -1; - for (octave_idx_type i = 0; i < m_len; i++) - { - octave_idx_type k = inda.xelem (i); - if (k < 0) - err_invalid_index (k); - else if (k > max) - max = k; - } - - m_ext = max + 1; - } - } - - idx_vector::idx_vector_rep::idx_vector_rep (const Array& inda, - octave_idx_type ext, direct) - : idx_base_rep (), m_data (inda.data ()), m_len (inda.numel ()), - m_ext (ext), m_aowner (new Array (inda)), - m_orig_dims (inda.dims ()) - { - // No checking. - if (m_ext < 0) - { - octave_idx_type max = -1; - for (octave_idx_type i = 0; i < m_len; i++) - if (m_data[i] > max) - max = m_data[i]; - - m_ext = max + 1; - } - } - - idx_vector::idx_vector_rep::idx_vector_rep (bool b) - : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0), - m_aowner (nullptr), m_orig_dims (m_len, m_len) - { - if (m_len != 0) + case class_scalar: { - octave_idx_type *d = new octave_idx_type [1]; - d[0] = 0; - m_data = d; - m_ext = 1; - } - } - - idx_vector::idx_vector_rep::idx_vector_rep (const Array& bnda, - octave_idx_type nnz) - : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (0), - m_aowner (nullptr), m_orig_dims () - { - if (nnz < 0) - m_len = bnda.nnz (); - - const dim_vector dv = bnda.dims (); - - m_orig_dims = dv.make_nd_vector (m_len); - - if (m_len != 0) - { - octave_idx_type *d = new octave_idx_type [m_len]; - - octave_idx_type ntot = bnda.numel (); - - octave_idx_type k = 0; - for (octave_idx_type i = 0; i < ntot; i++) - if (bnda.xelem (i)) - d[k++] = i; - - m_data = d; - - m_ext = d[k-1] + 1; + idx_scalar_rep *r = dynamic_cast (m_rep); + l = r->get_data (); + u = l + 1; + res = true; } - } - - idx_vector::idx_vector_rep::idx_vector_rep (const Sparse& bnda) - : idx_base_rep (), m_data (nullptr), m_len (bnda.nnz ()), m_ext (0), - m_aowner (nullptr), m_orig_dims () - { - const dim_vector dv = bnda.dims (); - - m_orig_dims = dv.make_nd_vector (m_len); - - if (m_len != 0) - { - octave_idx_type *d = new octave_idx_type [m_len]; - - octave_idx_type k = 0; - octave_idx_type nc = bnda.cols (); - octave_idx_type nr = bnda.rows (); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = bnda.cidx (j); i < bnda.cidx (j+1); i++) - if (bnda.data (i)) - d[k++] = j * nr + bnda.ridx (i); - - m_data = d; - - m_ext = d[k-1] + 1; - } - } - - idx_vector::idx_vector_rep::~idx_vector_rep (void) - { - if (m_aowner) - delete m_aowner; - else - delete [] m_data; - } - - octave_idx_type - idx_vector::idx_vector_rep::checkelem (octave_idx_type n) const - { - if (n < 0 || n >= m_len) - err_invalid_index (n); - - return xelem (n); - } - - idx_vector::idx_base_rep * - idx_vector::idx_vector_rep::sort_uniq_clone (bool uniq) - { - if (m_len == 0) - { - m_count++; - return this; - } - - // This is wrapped in unique_ptr so that we don't leak on out-of-memory. - std::unique_ptr new_rep - (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT)); - - if (m_ext > m_len*math::log2 (1.0 + m_len)) - { - // Use standard sort via octave_sort. - octave_idx_type *new_data = new octave_idx_type [m_len]; - new_rep->m_data = new_data; - - std::copy_n (m_data, m_len, new_data); - octave_sort lsort; - lsort.set_compare (ASCENDING); - lsort.sort (new_data, m_len); + break; - if (uniq) - { - octave_idx_type new_len = std::unique (new_data, new_data + m_len) - - new_data; - new_rep->m_len = new_len; - if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1) - new_rep->m_orig_dims = dim_vector (1, new_len); - else - new_rep->m_orig_dims = dim_vector (new_len, 1); - } - } - else if (uniq) + case class_mask: { - // Use two-pass bucket sort (only a mask array needed). - OCTAVE_LOCAL_BUFFER_INIT (bool, has, m_ext, false); - for (octave_idx_type i = 0; i < m_len; i++) - has[m_data[i]] = true; - - octave_idx_type new_len = 0; - for (octave_idx_type i = 0; i < m_ext; i++) - new_len += has[i]; - - new_rep->m_len = new_len; - if (new_rep->m_orig_dims.ndims () == 2 && new_rep->m_orig_dims(0) == 1) - new_rep->m_orig_dims = dim_vector (1, new_len); - else - new_rep->m_orig_dims = dim_vector (new_len, 1); - - octave_idx_type *new_data = new octave_idx_type [new_len]; - new_rep->m_data = new_data; - - for (octave_idx_type i = 0, j = 0; i < m_ext; i++) - if (has[i]) - new_data[j++] = i; - } - else - { - // Use two-pass bucket sort. - OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, cnt, m_ext, 0); - for (octave_idx_type i = 0; i < m_len; i++) - cnt[m_data[i]]++; - - octave_idx_type *new_data = new octave_idx_type [m_len]; - new_rep->m_data = new_data; - - for (octave_idx_type i = 0, j = 0; i < m_ext; i++) + idx_mask_rep *r = dynamic_cast (m_rep); + octave_idx_type m_ext = r->extent (0); + octave_idx_type m_len = r->length (0); + if (m_ext == m_len) { - for (octave_idx_type k = 0; k < cnt[i]; k++) - new_data[j++] = i; - } - } - - return new_rep.release (); - } - - idx_vector::idx_base_rep * - idx_vector::idx_vector_rep::sort_idx (Array& idx) - { - // This is wrapped in unique_ptr so that we don't leak on out-of-memory. - std::unique_ptr new_rep - (new idx_vector_rep (nullptr, m_len, m_ext, m_orig_dims, DIRECT)); - - if (m_ext > m_len*math::log2 (1.0 + m_len)) - { - // Use standard sort via octave_sort. - idx.clear (m_orig_dims); - octave_idx_type *idx_data = idx.fortran_vec (); - for (octave_idx_type i = 0; i < m_len; i++) - idx_data[i] = i; - - octave_idx_type *new_data = new octave_idx_type [m_len]; - new_rep->m_data = new_data; - std::copy_n (m_data, m_len, new_data); - - octave_sort lsort; - lsort.set_compare (ASCENDING); - lsort.sort (new_data, idx_data, m_len); - } - else - { - // Use two-pass bucket sort. - OCTAVE_LOCAL_BUFFER_INIT (octave_idx_type, cnt, m_ext, 0); - - for (octave_idx_type i = 0; i < m_len; i++) - cnt[m_data[i]]++; - - idx.clear (m_orig_dims); - octave_idx_type *idx_data = idx.fortran_vec (); - - octave_idx_type *new_data = new octave_idx_type [m_len]; - new_rep->m_data = new_data; - - for (octave_idx_type i = 0, k = 0; i < m_ext; i++) - { - octave_idx_type j = cnt[i]; - cnt[i] = k; - k += j; - } - - for (octave_idx_type i = 0; i < m_len; i++) - { - octave_idx_type j = m_data[i]; - octave_idx_type k = cnt[j]++; - new_data[k] = j; - idx_data[k] = i; + l = 0; + u = m_len; + res = true; } } - return new_rep.release (); - } - - std::ostream& idx_vector::idx_vector_rep::print (std::ostream& os) const - { - os << '['; + default: + break; + } - for (octave_idx_type i = 0; i < m_len - 1; i++) - os << m_data[i] << ',' << ' '; - - if (m_len > 0) - os << m_data[m_len-1]; - - os << ']'; - - return os; - } + return res; +} - Array idx_vector::idx_vector_rep::unconvert (void) const - { - Array retval (m_orig_dims); - for (octave_idx_type i = 0; i < m_len; i++) - retval.xelem (i) = m_data[i] + 1; - return retval; - } +octave_idx_type idx_vector::increment (void) const +{ + octave_idx_type retval = 0; - Array idx_vector::idx_vector_rep::as_array (void) - { - if (m_aowner) - return *m_aowner; - else - { - Array retval (m_orig_dims); + switch (m_rep->idx_class ()) + { + case class_colon: + retval = 1; + break; - if (m_data) - { - std::memcpy (retval.fortran_vec (), m_data, m_len*sizeof (octave_idx_type)); - // Delete the old copy and share the m_data instead to save memory. - delete [] m_data; - } + case class_range: + retval = dynamic_cast (m_rep) -> get_step (); + break; - m_data = retval.fortran_vec (); - m_aowner = new Array (retval); - - return retval; + case class_vector: + case class_mask: + { + if (length (0) > 1) + retval = elem (1) - elem (0); } - } - - idx_vector::idx_mask_rep::idx_mask_rep (bool b) - : idx_base_rep (), m_data (nullptr), m_len (b ? 1 : 0), m_ext (0), - m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (m_len, m_len) - { - if (m_len != 0) - { - bool *d = new bool [1]; - d[0] = true; - m_data = d; - m_ext = 1; - } - } + break; - idx_vector::idx_mask_rep::idx_mask_rep (const Array& bnda, - octave_idx_type nnz) - : idx_base_rep (), m_data (nullptr), m_len (nnz), m_ext (bnda.numel ()), - m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims () - { - if (nnz < 0) - m_len = bnda.nnz (); + default: + break; + } + + return retval; +} - // We truncate the extent as much as possible. For Matlab - // compatibility, but maybe it's not a bad idea anyway. - while (m_ext > 0 && ! bnda(m_ext-1)) - m_ext--; +const octave_idx_type *idx_vector::raw (void) +{ + if (m_rep->idx_class () != class_vector) + *this = idx_vector (as_array (), extent (0)); - const dim_vector dv = bnda.dims (); - - m_orig_dims = dv.make_nd_vector (m_len); - - m_aowner = new Array (bnda); - m_data = bnda.data (); - } + idx_vector_rep *r = dynamic_cast (m_rep); - idx_vector::idx_mask_rep::~idx_mask_rep (void) - { - if (m_aowner) - delete m_aowner; - else - delete [] m_data; - } + assert (r != nullptr); + + return r->get_data (); +} - octave_idx_type idx_vector::idx_mask_rep::xelem (octave_idx_type n) const - { - if (n == m_lsti + 1) - { - m_lsti = n; - while (! m_data[++m_lste]) ; - } - else - { - m_lsti = n++; - m_lste = -1; - while (n > 0) - if (m_data[++m_lste]) --n; - } - return m_lste; - } +void idx_vector::copy_data (octave_idx_type *m_data) const +{ + octave_idx_type m_len = m_rep->length (0); - octave_idx_type idx_vector::idx_mask_rep::checkelem (octave_idx_type n) const - { - if (n < 0 || n >= m_len) - err_invalid_index (n); - - return xelem (n); - } - - std::ostream& idx_vector::idx_mask_rep::print (std::ostream& os) const - { - os << '['; - - for (octave_idx_type i = 0; i < m_ext - 1; i++) - os << m_data[i] << ',' << ' '; - - if (m_ext > 0) - os << m_data[m_ext-1]; + switch (m_rep->idx_class ()) + { + case class_colon: + (*current_liboctave_error_handler) ("colon not allowed"); + break; - os << ']'; - - return os; - } - - Array idx_vector::idx_mask_rep::unconvert (void) const - { - if (m_aowner) - return *m_aowner; - else + case class_range: { - Array retval (dim_vector (m_ext, 1)); - for (octave_idx_type i = 0; i < m_ext; i++) - retval.xelem (i) = m_data[i]; - return retval; + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type m_start = r->get_start (); + octave_idx_type m_step = r->get_step (); + octave_idx_type i, j; + if (m_step == 1) + for (i = m_start, j = m_start + m_len; i < j; i++) *m_data++ = i; + else if (m_step == -1) + for (i = m_start, j = m_start - m_len; i > j; i--) *m_data++ = i; + else + for (i = 0, j = m_start; i < m_len; i++, j += m_step) *m_data++ = j; } - } + break; - Array idx_vector::idx_mask_rep::as_array (void) - { - if (m_aowner) - return m_aowner->find ().reshape (m_orig_dims); - else + case class_scalar: { - Array retval (m_orig_dims); - for (octave_idx_type i = 0, j = 0; i < m_ext; i++) - if (m_data[i]) - retval.xelem (j++) = i; - - return retval; + idx_scalar_rep *r = dynamic_cast (m_rep); + *m_data = r->get_data (); } - } + break; - idx_vector::idx_base_rep * - idx_vector::idx_mask_rep::sort_idx (Array& idx) - { - idx.clear (m_len, 1); - for (octave_idx_type i = 0; i < m_len; i++) - idx.xelem (i) = i; - - m_count++; - return this; - } - - const idx_vector idx_vector::colon (new idx_vector::idx_colon_rep ()); + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *rdata = r->get_data (); + std::copy_n (rdata, m_len, m_data); + } + break; - idx_vector::idx_vector (const Array& bnda) - : m_rep (nullptr) - { - // Convert only if it means saving at least half the memory. - static const int factor = (2 * sizeof (octave_idx_type)); - octave_idx_type nnz = bnda.nnz (); - if (nnz <= bnda.numel () / factor) - m_rep = new idx_vector_rep (bnda, nnz); - else - m_rep = new idx_mask_rep (bnda, nnz); - } - - bool idx_vector::maybe_reduce (octave_idx_type n, const idx_vector& j, - octave_idx_type nj) - { - bool reduced = false; - - // Empty index always reduces. - if (m_rep->length (n) == 0) - { - *this = idx_vector (); - return true; - } - - // Possibly skip singleton dims. - if (n == 1 && m_rep->is_colon_equiv (n)) - { - *this = j; - return true; - } - - if (nj == 1 && j.is_colon_equiv (nj)) - return true; - - switch (j.idx_class ()) + case class_mask: { - case class_colon: - switch (m_rep->idx_class ()) - { - case class_colon: - // (:,:) reduces to (:) - reduced = true; - break; + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *mask = r->get_data (); + octave_idx_type m_ext = r->extent (0); + for (octave_idx_type i = 0, j = 0; i < m_ext; i++) + if (mask[i]) + m_data[j++] = i; + } + break; - case class_scalar: - { - // (i,:) reduces to a range. - idx_scalar_rep *r = dynamic_cast (m_rep); - octave_idx_type k = r->get_data (); - *this = new idx_range_rep (k, nj, n, DIRECT); - reduced = true; - } - break; + default: + assert (false); + break; + } +} + +idx_vector idx_vector::complement (octave_idx_type n) const +{ + idx_vector retval; + if (extent (n) > n) + (*current_liboctave_error_handler) + ("internal error: out of range complement index requested"); - case class_range: - { - // (i:k:end,:) reduces to a range if i <= k and k divides n. - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type s = r->get_start (); - octave_idx_type l = r->length (n); - octave_idx_type t = r->get_step (); - if (l*t == n) - { - *this = new idx_range_rep (s, l * nj, t, DIRECT); - reduced = true; - } - } - break; + if (idx_class () == class_mask) + { + idx_mask_rep *r = dynamic_cast (m_rep); + octave_idx_type nz = r->length (0); + octave_idx_type m_ext = r->extent (0); + Array mask (dim_vector (n, 1)); + const bool *m_data = r->get_data (); + bool *ndata = mask.fortran_vec (); + for (octave_idx_type i = 0; i < m_ext; i++) + ndata[i] = ! m_data[i]; + std::fill_n (ndata + m_ext, n - m_ext, true); + retval = new idx_mask_rep (mask, n - nz); + } + else + { + Array mask (dim_vector (n, 1), true); + fill (false, length (n), mask.fortran_vec ()); + retval = idx_vector (mask); + } - default: - break; - } - break; + return retval; +} + +bool idx_vector::is_permutation (octave_idx_type n) const +{ + bool retval = false; - case class_range: - switch (m_rep->idx_class ()) - { - case class_colon: + if (is_colon_equiv (n)) + retval = true; + else if (length(n) == n && extent(n) == n) + { + OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true); + + retval = true; + + for (octave_idx_type i = 0, m_len = length (); i < m_len; i++) + { + octave_idx_type k = xelem (i); + if (left[k]) + left[k] = false; + else { - // (:,i:j) reduces to a range (the m_step must be 1) - idx_range_rep *rj = dynamic_cast (j.m_rep); - if (rj->get_step () == 1) - { - octave_idx_type sj = rj->get_start (); - octave_idx_type lj = rj->length (nj); - *this = new idx_range_rep (sj * n, lj * n, 1, DIRECT); - reduced = true; - } + retval = false; + break; } - break; + } + } - case class_scalar: - { - // (k,i:d:j) reduces to a range. - idx_scalar_rep *r = dynamic_cast (m_rep); - idx_range_rep *rj = dynamic_cast (j.m_rep); - octave_idx_type k = r->get_data (); - octave_idx_type sj = rj->get_start (); - octave_idx_type lj = rj->length (nj); - octave_idx_type tj = rj->get_step (); - *this = new idx_range_rep (n * sj + k, lj, n * tj, DIRECT); - reduced = true; - } - break; - - case class_range: - { - // (i:k:end,p:q) reduces to a range if i <= k and k divides n. - // (ones (1, m), ones (1, n)) reduces to (ones (1, m*n)) - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type s = r->get_start (); - octave_idx_type l = r->length (n); - octave_idx_type t = r->get_step (); - idx_range_rep *rj = dynamic_cast (j.m_rep); - octave_idx_type sj = rj->get_start (); - octave_idx_type lj = rj->length (nj); - octave_idx_type tj = rj->get_step (); - if ((l*t == n && tj == 1) || (t == 0 && tj == 0)) - { - *this = new idx_range_rep (s + n * sj, l * lj, t, DIRECT); - reduced = true; - } - } - break; + return retval; +} - default: - break; - } - break; +idx_vector idx_vector::inverse_permutation (octave_idx_type n) const +{ + assert (n == length (n)); - case class_scalar: - switch (m_rep->idx_class ()) - { - case class_scalar: - { - // (i,j) reduces to a single index. - idx_scalar_rep *r = dynamic_cast (m_rep); - idx_scalar_rep *rj = dynamic_cast (j.m_rep); - octave_idx_type k = r->get_data () + n * rj->get_data (); - *this = new idx_scalar_rep (k, DIRECT); - reduced = true; - } - break; + idx_vector retval; - case class_range: - { - // (i:d:j,k) reduces to a range. - idx_range_rep *r = dynamic_cast (m_rep); - idx_scalar_rep *rj = dynamic_cast (j.m_rep); - octave_idx_type s = r->get_start (); - octave_idx_type l = r->length (nj); - octave_idx_type t = r->get_step (); - octave_idx_type k = rj->get_data (); - *this = new idx_range_rep (n * k + s, l, t, DIRECT); - reduced = true; - } - break; - - case class_colon: - { - // (:,k) reduces to a range. - idx_scalar_rep *rj = dynamic_cast (j.m_rep); - octave_idx_type k = rj->get_data (); - *this = new idx_range_rep (n * k, n, 1, DIRECT); - reduced = true; - } - break; - - default: - break; - } - break; - - default: + switch (idx_class ()) + { + case class_range: + { + if (increment () == -1) + retval = sorted (); + else + retval = *this; break; } - - return reduced; - } - - bool idx_vector::is_cont_range (octave_idx_type n, octave_idx_type& l, - octave_idx_type& u) const - { - bool res = false; - - switch (m_rep->idx_class ()) + case class_vector: { - case class_colon: - l = 0; u = n; - res = true; - break; - - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - if (r->get_step () == 1) - { - l = r->get_start (); - u = l + r->length (n); - res = true; - } - } - break; - - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - l = r->get_data (); - u = l + 1; - res = true; - } - break; - - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - octave_idx_type m_ext = r->extent (0); - octave_idx_type m_len = r->length (0); - if (m_ext == m_len) - { - l = 0; - u = m_len; - res = true; - } - } - - default: - break; - } - - return res; - } - - octave_idx_type idx_vector::increment (void) const - { - octave_idx_type retval = 0; - - switch (m_rep->idx_class ()) - { - case class_colon: - retval = 1; - break; - - case class_range: - retval = dynamic_cast (m_rep) -> get_step (); - break; - - case class_vector: - case class_mask: - { - if (length (0) > 1) - retval = elem (1) - elem (0); - } - break; - - default: + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *ri = r->get_data (); + Array idx (orig_dimensions ()); + for (octave_idx_type i = 0; i < n; i++) + idx.xelem (ri[i]) = i; + retval = new idx_vector_rep (idx, r->extent (0), DIRECT); break; } - - return retval; - } - - const octave_idx_type * idx_vector::raw (void) - { - if (m_rep->idx_class () != class_vector) - *this = idx_vector (as_array (), extent (0)); + default: + retval = *this; + break; + } - idx_vector_rep *r = dynamic_cast (m_rep); - - assert (r != nullptr); - - return r->get_data (); - } - - void idx_vector::copy_data (octave_idx_type *m_data) const - { - octave_idx_type m_len = m_rep->length (0); + return retval; +} - switch (m_rep->idx_class ()) - { - case class_colon: - (*current_liboctave_error_handler) ("colon not allowed"); - break; +idx_vector idx_vector::unmask (void) const +{ + if (idx_class () == class_mask) + { + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *m_data = r->get_data (); + octave_idx_type m_ext = r->extent (0); + octave_idx_type m_len = r->length (0); + octave_idx_type *idata = new octave_idx_type [m_len]; - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type m_start = r->get_start (); - octave_idx_type m_step = r->get_step (); - octave_idx_type i, j; - if (m_step == 1) - for (i = m_start, j = m_start + m_len; i < j; i++) *m_data++ = i; - else if (m_step == -1) - for (i = m_start, j = m_start - m_len; i > j; i--) *m_data++ = i; - else - for (i = 0, j = m_start; i < m_len; i++, j += m_step) *m_data++ = j; - } - break; + for (octave_idx_type i = 0, j = 0; i < m_ext; i++) + if (m_data[i]) + idata[j++] = i; + + m_ext = (m_len > 0 ? idata[m_len - 1] + 1 : 0); + + return new idx_vector_rep (idata, m_len, m_ext, r->orig_dimensions (), + DIRECT); + } + else + return *this; +} - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - *m_data = r->get_data (); - } - break; - - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *rdata = r->get_data (); - std::copy_n (rdata, m_len, m_data); - } - break; +void idx_vector::unconvert (idx_class_type& iclass, + double& scalar, range& range, + Array& array, Array& mask) const +{ + iclass = idx_class (); + switch (iclass) + { + case class_colon: + break; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *mask = r->get_data (); - octave_idx_type m_ext = r->extent (0); - for (octave_idx_type i = 0, j = 0; i < m_ext; i++) - if (mask[i]) - m_data[j++] = i; - } - break; + case class_range: + { + idx_range_rep *r = dynamic_cast (m_rep); + range = r->unconvert (); + } + break; - default: - assert (false); - break; + case class_scalar: + { + idx_scalar_rep *r = dynamic_cast (m_rep); + scalar = r->unconvert (); } - } + break; - idx_vector idx_vector::complement (octave_idx_type n) const - { - idx_vector retval; - if (extent (n) > n) - (*current_liboctave_error_handler) - ("internal error: out of range complement index requested"); + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + array = r->unconvert (); + } + break; - if (idx_class () == class_mask) + case class_mask: { idx_mask_rep *r = dynamic_cast (m_rep); - octave_idx_type nz = r->length (0); - octave_idx_type m_ext = r->extent (0); - Array mask (dim_vector (n, 1)); - const bool *m_data = r->get_data (); - bool *ndata = mask.fortran_vec (); - for (octave_idx_type i = 0; i < m_ext; i++) - ndata[i] = ! m_data[i]; - std::fill_n (ndata + m_ext, n - m_ext, true); - retval = new idx_mask_rep (mask, n - nz); + mask = r->unconvert (); } - else - { - Array mask (dim_vector (n, 1), true); - fill (false, length (n), mask.fortran_vec ()); - retval = idx_vector (mask); - } - - return retval; - } + break; - bool idx_vector::is_permutation (octave_idx_type n) const - { - bool retval = false; - - if (is_colon_equiv (n)) - retval = true; - else if (length(n) == n && extent(n) == n) - { - OCTAVE_LOCAL_BUFFER_INIT (bool, left, n, true); - - retval = true; - - for (octave_idx_type i = 0, m_len = length (); i < m_len; i++) - { - octave_idx_type k = xelem (i); - if (left[k]) - left[k] = false; - else - { - retval = false; - break; - } - } - } + default: + assert (false); + break; + } +} - return retval; - } - - idx_vector idx_vector::inverse_permutation (octave_idx_type n) const - { - assert (n == length (n)); - - idx_vector retval; +Array idx_vector::as_array (void) const +{ + return m_rep->as_array (); +} - switch (idx_class ()) - { - case class_range: - { - if (increment () == -1) - retval = sorted (); - else - retval = *this; - break; - } - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *ri = r->get_data (); - Array idx (orig_dimensions ()); - for (octave_idx_type i = 0; i < n; i++) - idx.xelem (ri[i]) = i; - retval = new idx_vector_rep (idx, r->extent (0), DIRECT); - break; - } - default: - retval = *this; - break; - } - - return retval; - } - - idx_vector idx_vector::unmask (void) const - { - if (idx_class () == class_mask) - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *m_data = r->get_data (); - octave_idx_type m_ext = r->extent (0); - octave_idx_type m_len = r->length (0); - octave_idx_type *idata = new octave_idx_type [m_len]; +bool idx_vector::isvector (void) const +{ + return idx_class () != class_vector || orig_dimensions ().isvector (); +} - for (octave_idx_type i = 0, j = 0; i < m_ext; i++) - if (m_data[i]) - idata[j++] = i; - - m_ext = (m_len > 0 ? idata[m_len - 1] + 1 : 0); - - return new idx_vector_rep (idata, m_len, m_ext, r->orig_dimensions (), - DIRECT); - } - else - return *this; - } +octave_idx_type +idx_vector::freeze (octave_idx_type z_len, const char *, bool resize_ok) +{ + if (! resize_ok && extent (z_len) > z_len) + (*current_liboctave_error_handler) + ("invalid matrix index = %" OCTAVE_IDX_TYPE_FORMAT, extent (z_len)); - void idx_vector::unconvert (idx_class_type& iclass, - double& scalar, range& range, - Array& array, Array& mask) const - { - iclass = idx_class (); - switch (iclass) - { - case class_colon: - break; + return length (z_len); +} - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - range = r->unconvert (); - } - break; - - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - scalar = r->unconvert (); - } - break; - - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - array = r->unconvert (); - } - break; +octave_idx_type idx_vector::ones_count () const +{ + octave_idx_type n = 0; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - mask = r->unconvert (); - } - break; - - default: - assert (false); - break; - } - } - - Array idx_vector::as_array (void) const - { - return m_rep->as_array (); - } - - bool idx_vector::isvector (void) const - { - return idx_class () != class_vector || orig_dimensions ().isvector (); - } + if (is_colon ()) + n = 1; + else + { + for (octave_idx_type i = 0; i < length (1); i++) + if (xelem (i) == 0) + n++; + } - octave_idx_type - idx_vector::freeze (octave_idx_type z_len, const char *, bool resize_ok) - { - if (! resize_ok && extent (z_len) > z_len) - (*current_liboctave_error_handler) - ("invalid matrix index = %" OCTAVE_IDX_TYPE_FORMAT, extent (z_len)); - - return length (z_len); - } - - octave_idx_type idx_vector::ones_count () const - { - octave_idx_type n = 0; + return n; +} - if (is_colon ()) - n = 1; - else - { - for (octave_idx_type i = 0; i < length (1); i++) - if (xelem (i) == 0) - n++; - } - - return n; - } - - // Instantiate the octave_int constructors we want. +// Instantiate the octave_int constructors we want. #define INSTANTIATE_SCALAR_VECTOR_REP_CONST(T) \ template OCTAVE_API idx_vector::idx_scalar_rep::idx_scalar_rep (T); \ template OCTAVE_API idx_vector::idx_vector_rep::idx_vector_rep (const Array&); - INSTANTIATE_SCALAR_VECTOR_REP_CONST (float) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (double) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int8) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int16) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int32) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int64) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint8) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint16) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint32) - INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint64) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (float) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (double) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int8) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int16) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int32) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_int64) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint8) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint16) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint32) +INSTANTIATE_SCALAR_VECTOR_REP_CONST (octave_uint64) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/array/idx-vector.h --- a/liboctave/array/idx-vector.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/array/idx-vector.h Thu Dec 01 20:05:44 2022 -0800 @@ -44,992 +44,992 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Design rationale: - // - // idx_vector is a reference-counting, polymorphic pointer, that can - // contain 4 types of index objects: a magic colon, a range, a scalar, - // or an index vector. - // - // Polymorphic methods for single element access are provided, as well - // as templates implementing "early dispatch", i.e., hoisting the checks - // for index type out of loops. +// Design rationale: +// +// idx_vector is a reference-counting, polymorphic pointer, that can +// contain 4 types of index objects: a magic colon, a range, a scalar, +// or an index vector. +// +// Polymorphic methods for single element access are provided, as well +// as templates implementing "early dispatch", i.e., hoisting the checks +// for index type out of loops. + +class +OCTAVE_API +idx_vector +{ +public: + + enum idx_class_type + { + class_invalid = -1, + class_colon = 0, + class_range, + class_scalar, + class_vector, + class_mask + }; + + template friend class std::unique_ptr; + +private: + + class OCTAVE_API idx_base_rep + { + public: + + idx_base_rep (void) : m_count (1) { } + + // No copying! + + idx_base_rep (const idx_base_rep&) = delete; - class - OCTAVE_API - idx_vector + idx_base_rep& operator = (const idx_base_rep&) = delete; + + virtual ~idx_base_rep (void) = default; + + // Non-range-checking element query. + virtual octave_idx_type xelem (octave_idx_type i) const = 0; + + // Range-checking element query. + virtual octave_idx_type checkelem (octave_idx_type i) const = 0; + + // Length of the index vector. + virtual octave_idx_type length (octave_idx_type n) const = 0; + + // The maximum index + 1. The actual dimension is passed in. + virtual octave_idx_type extent (octave_idx_type n) const = 0; + + // Index class. + virtual idx_class_type idx_class (void) const { return class_invalid; } + + // Sorts, maybe uniqifies, and returns a clone object pointer. + virtual idx_base_rep * sort_uniq_clone (bool uniq = false) = 0; + // Sorts, and returns a sorting permutation (aka Array::sort). + virtual idx_base_rep * sort_idx (Array&) = 0; + + // Checks whether the index is colon or a range equivalent to colon. + virtual bool is_colon_equiv (octave_idx_type) const { return false; } + + // The original dimensions of object (used when subscribing by matrices). + virtual dim_vector orig_dimensions (void) const { return dim_vector (); } + + // i/o + virtual std::ostream& print (std::ostream& os) const = 0; + + virtual Array as_array (void); + + refcount m_count; + }; + + // The magic colon index. + class OCTAVE_API idx_colon_rep : public idx_base_rep { public: - enum idx_class_type + idx_colon_rep (void) = default; + + OCTAVE_API idx_colon_rep (char c); + + // No copying! + + idx_colon_rep (const idx_colon_rep& idx) = delete; + + idx_colon_rep& operator = (const idx_colon_rep& idx) = delete; + + octave_idx_type xelem (octave_idx_type i) const { return i; } + + OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const; + + octave_idx_type length (octave_idx_type n) const { return n; } + + octave_idx_type extent (octave_idx_type n) const { return n; } + + idx_class_type idx_class (void) const { return class_colon; } + + idx_base_rep * sort_uniq_clone (bool = false) + { m_count++; return this; } + + OCTAVE_NORETURN idx_base_rep * sort_idx (Array&); + + bool is_colon_equiv (octave_idx_type) const { return true; } + + OCTAVE_API std::ostream& print (std::ostream& os) const; + }; + + // To distinguish the "direct" constructors that blindly trust the data. + enum direct { DIRECT }; + + // The integer range index. + class OCTAVE_API idx_range_rep : public idx_base_rep + { + public: + + idx_range_rep (void) = delete; + + idx_range_rep (octave_idx_type start, octave_idx_type len, + octave_idx_type step, direct) + : idx_base_rep (), m_start (start), m_len (len), m_step (step) { } + + // Zero-based constructor for index range starting at `start` (inclusive) + // and ending at `limit` (exclusive) in steps of `step`. + idx_range_rep (octave_idx_type start, octave_idx_type limit, + octave_idx_type step); + + OCTAVE_API idx_range_rep (const range&); + + // No copying! + + idx_range_rep (const idx_range_rep& idx) = delete; + + idx_range_rep& operator = (const idx_range_rep& idx) = delete; + + octave_idx_type xelem (octave_idx_type i) const + { return m_start + i * m_step; } + + octave_idx_type checkelem (octave_idx_type i) const; + + octave_idx_type length (octave_idx_type) const { return m_len; } + + octave_idx_type extent (octave_idx_type n) const { - class_invalid = -1, - class_colon = 0, - class_range, - class_scalar, - class_vector, - class_mask - }; + return m_len ? std::max (n, m_start + 1 + (m_step < 0 ? 0 : m_step * (m_len - 1))) : n; + } + + idx_class_type idx_class (void) const { return class_range; } + + OCTAVE_API idx_base_rep * sort_uniq_clone (bool uniq = false); + + OCTAVE_API idx_base_rep * sort_idx (Array&); + + bool is_colon_equiv (octave_idx_type n) const + { return m_start == 0 && m_step == 1 && m_len == n; } - template friend class std::unique_ptr; + dim_vector orig_dimensions (void) const + { return dim_vector (1, m_len); } + + octave_idx_type get_start (void) const { return m_start; } + + octave_idx_type get_step (void) const { return m_step; } + + OCTAVE_API std::ostream& print (std::ostream& os) const; + + OCTAVE_API range unconvert (void) const; + + OCTAVE_API Array as_array (void); private: - class OCTAVE_API idx_base_rep - { - public: - - idx_base_rep (void) : m_count (1) { } - - // No copying! - - idx_base_rep (const idx_base_rep&) = delete; - - idx_base_rep& operator = (const idx_base_rep&) = delete; - - virtual ~idx_base_rep (void) = default; - - // Non-range-checking element query. - virtual octave_idx_type xelem (octave_idx_type i) const = 0; - - // Range-checking element query. - virtual octave_idx_type checkelem (octave_idx_type i) const = 0; - - // Length of the index vector. - virtual octave_idx_type length (octave_idx_type n) const = 0; - - // The maximum index + 1. The actual dimension is passed in. - virtual octave_idx_type extent (octave_idx_type n) const = 0; - - // Index class. - virtual idx_class_type idx_class (void) const { return class_invalid; } - - // Sorts, maybe uniqifies, and returns a clone object pointer. - virtual idx_base_rep * sort_uniq_clone (bool uniq = false) = 0; - // Sorts, and returns a sorting permutation (aka Array::sort). - virtual idx_base_rep * sort_idx (Array&) = 0; - - // Checks whether the index is colon or a range equivalent to colon. - virtual bool is_colon_equiv (octave_idx_type) const { return false; } - - // The original dimensions of object (used when subscribing by matrices). - virtual dim_vector orig_dimensions (void) const { return dim_vector (); } - - // i/o - virtual std::ostream& print (std::ostream& os) const = 0; - - virtual Array as_array (void); + octave_idx_type m_start, m_len, m_step; + }; - refcount m_count; - }; - - // The magic colon index. - class OCTAVE_API idx_colon_rep : public idx_base_rep - { - public: - - idx_colon_rep (void) = default; - - OCTAVE_API idx_colon_rep (char c); - - // No copying! - - idx_colon_rep (const idx_colon_rep& idx) = delete; - - idx_colon_rep& operator = (const idx_colon_rep& idx) = delete; - - octave_idx_type xelem (octave_idx_type i) const { return i; } - - OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const; + // The integer scalar index. + class OCTAVE_API idx_scalar_rep : public idx_base_rep + { + public: - octave_idx_type length (octave_idx_type n) const { return n; } - - octave_idx_type extent (octave_idx_type n) const { return n; } - - idx_class_type idx_class (void) const { return class_colon; } - - idx_base_rep * sort_uniq_clone (bool = false) - { m_count++; return this; } - - OCTAVE_NORETURN idx_base_rep * sort_idx (Array&); + idx_scalar_rep (void) = delete; - bool is_colon_equiv (octave_idx_type) const { return true; } - - OCTAVE_API std::ostream& print (std::ostream& os) const; - }; + idx_scalar_rep (octave_idx_type i, direct) : idx_base_rep (), m_data (i) { } - // To distinguish the "direct" constructors that blindly trust the data. - enum direct { DIRECT }; - - // The integer range index. - class OCTAVE_API idx_range_rep : public idx_base_rep - { - public: + // No copying! - idx_range_rep (void) = delete; - - idx_range_rep (octave_idx_type start, octave_idx_type len, - octave_idx_type step, direct) - : idx_base_rep (), m_start (start), m_len (len), m_step (step) { } - - // Zero-based constructor for index range starting at `start` (inclusive) - // and ending at `limit` (exclusive) in steps of `step`. - idx_range_rep (octave_idx_type start, octave_idx_type limit, - octave_idx_type step); - - OCTAVE_API idx_range_rep (const range&); - - // No copying! - - idx_range_rep (const idx_range_rep& idx) = delete; - - idx_range_rep& operator = (const idx_range_rep& idx) = delete; - - octave_idx_type xelem (octave_idx_type i) const - { return m_start + i * m_step; } + idx_scalar_rep (const idx_scalar_rep& idx) = delete; - octave_idx_type checkelem (octave_idx_type i) const; - - octave_idx_type length (octave_idx_type) const { return m_len; } - - octave_idx_type extent (octave_idx_type n) const - { - return m_len ? std::max (n, m_start + 1 + (m_step < 0 ? 0 : m_step * (m_len - 1))) : n; - } - - idx_class_type idx_class (void) const { return class_range; } + idx_scalar_rep& operator = (const idx_scalar_rep& idx) = delete; - OCTAVE_API idx_base_rep * sort_uniq_clone (bool uniq = false); - - OCTAVE_API idx_base_rep * sort_idx (Array&); - - bool is_colon_equiv (octave_idx_type n) const - { return m_start == 0 && m_step == 1 && m_len == n; } - - dim_vector orig_dimensions (void) const - { return dim_vector (1, m_len); } - - octave_idx_type get_start (void) const { return m_start; } + // Zero-based constructor. + OCTAVE_API idx_scalar_rep (octave_idx_type i); - octave_idx_type get_step (void) const { return m_step; } - - OCTAVE_API std::ostream& print (std::ostream& os) const; - - OCTAVE_API range unconvert (void) const; - - OCTAVE_API Array as_array (void); - - private: - - octave_idx_type m_start, m_len, m_step; - }; - - // The integer scalar index. - class OCTAVE_API idx_scalar_rep : public idx_base_rep - { - public: - - idx_scalar_rep (void) = delete; - - idx_scalar_rep (octave_idx_type i, direct) : idx_base_rep (), m_data (i) { } - - // No copying! + template + idx_scalar_rep (T x); - idx_scalar_rep (const idx_scalar_rep& idx) = delete; - - idx_scalar_rep& operator = (const idx_scalar_rep& idx) = delete; - - // Zero-based constructor. - OCTAVE_API idx_scalar_rep (octave_idx_type i); - - template - idx_scalar_rep (T x); - - octave_idx_type xelem (octave_idx_type) const { return m_data; } + octave_idx_type xelem (octave_idx_type) const { return m_data; } - OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const; - - octave_idx_type length (octave_idx_type) const { return 1; } + OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const; - octave_idx_type extent (octave_idx_type n) const - { return std::max (n, m_data + 1); } - - idx_class_type idx_class (void) const { return class_scalar; } - - idx_base_rep * sort_uniq_clone (bool = false) - { m_count++; return this; } + octave_idx_type length (octave_idx_type) const { return 1; } - OCTAVE_API idx_base_rep * sort_idx (Array&); - - bool is_colon_equiv (octave_idx_type n) const - { return n == 1 && m_data == 0; } - - dim_vector orig_dimensions (void) const { return dim_vector (1, 1); } - - octave_idx_type get_data (void) const { return m_data; } - - OCTAVE_API std::ostream& print (std::ostream& os) const; - - OCTAVE_API double unconvert (void) const; - - OCTAVE_API Array as_array (void); - - private: - - octave_idx_type m_data; - }; + octave_idx_type extent (octave_idx_type n) const + { return std::max (n, m_data + 1); } - // The integer vector index. - class OCTAVE_API idx_vector_rep : public idx_base_rep - { - public: - - idx_vector_rep (void) - : m_data (nullptr), m_len (0), m_ext (0), m_aowner (nullptr), m_orig_dims () { } - - // Direct constructor. - idx_vector_rep (octave_idx_type *data, octave_idx_type len, - octave_idx_type ext, const dim_vector& od, direct) - : idx_base_rep (), m_data (data), m_len (len), m_ext (ext), - m_aowner (nullptr), m_orig_dims (od) - { } - - // Zero-based constructor. - OCTAVE_API idx_vector_rep (const Array& inda); - - OCTAVE_API idx_vector_rep (const Array& inda, - octave_idx_type ext, direct); - - template - idx_vector_rep (const Array&); + idx_class_type idx_class (void) const { return class_scalar; } - OCTAVE_API idx_vector_rep (bool); - - OCTAVE_API idx_vector_rep (const Array&, octave_idx_type = -1); - - OCTAVE_API idx_vector_rep (const Sparse&); - - // No copying! - - idx_vector_rep (const idx_vector_rep& idx) = delete; + idx_base_rep * sort_uniq_clone (bool = false) + { m_count++; return this; } - idx_vector_rep& operator = (const idx_vector_rep& idx) = delete; - - ~idx_vector_rep (void); - - octave_idx_type xelem (octave_idx_type i) const { return m_data[i]; } - - OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const; - - octave_idx_type length (octave_idx_type) const { return m_len; } + OCTAVE_API idx_base_rep * sort_idx (Array&); - octave_idx_type extent (octave_idx_type n) const - { return std::max (n, m_ext); } - - idx_class_type idx_class (void) const { return class_vector; } - - idx_base_rep * sort_uniq_clone (bool uniq = false); - - OCTAVE_API idx_base_rep * sort_idx (Array&); - - dim_vector orig_dimensions (void) const { return m_orig_dims; } + bool is_colon_equiv (octave_idx_type n) const + { return n == 1 && m_data == 0; } - const octave_idx_type * get_data (void) const { return m_data; } - - OCTAVE_API std::ostream& print (std::ostream& os) const; - - OCTAVE_API Array unconvert (void) const; - - OCTAVE_API Array as_array (void); - - private: - - const octave_idx_type *m_data; - octave_idx_type m_len; - octave_idx_type m_ext; + dim_vector orig_dimensions (void) const { return dim_vector (1, 1); } - // This is a trick to allow user-given zero-based arrays to be used - // as indices without copying. If the following pointer is nonzero, - // we do not own the data, but rather have an Array - // object that provides us the data. Note that we need a pointer - // because we deferred the Array declaration and we do not want - // it yet to be defined. - - Array *m_aowner; + octave_idx_type get_data (void) const { return m_data; } - dim_vector m_orig_dims; - }; - - // The logical mask index. - class OCTAVE_API idx_mask_rep : public idx_base_rep - { - public: - - idx_mask_rep (void) = delete; + OCTAVE_API std::ostream& print (std::ostream& os) const; - // Direct constructor. - idx_mask_rep (bool *data, octave_idx_type len, - octave_idx_type ext, const dim_vector& od, direct) - : idx_base_rep (), m_data (data), m_len (len), m_ext (ext), - m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (od) - { } - - OCTAVE_API idx_mask_rep (bool); - - OCTAVE_API idx_mask_rep (const Array&, octave_idx_type = -1); - - // No copying! + OCTAVE_API double unconvert (void) const; - idx_mask_rep (const idx_mask_rep& idx) = delete; - - idx_mask_rep& operator = (const idx_mask_rep& idx) = delete; - - OCTAVE_API ~idx_mask_rep (void); - - octave_idx_type xelem (octave_idx_type i) const; - - octave_idx_type checkelem (octave_idx_type i) const; - - octave_idx_type length (octave_idx_type) const { return m_len; } - - octave_idx_type extent (octave_idx_type n) const - { return std::max (n, m_ext); } + OCTAVE_API Array as_array (void); - idx_class_type idx_class (void) const { return class_mask; } - - idx_base_rep * sort_uniq_clone (bool = false) - { m_count++; return this; } - - OCTAVE_API idx_base_rep * sort_idx (Array&); - - dim_vector orig_dimensions (void) const { return m_orig_dims; } - - bool is_colon_equiv (octave_idx_type n) const - { return m_len == n && m_ext == n; } - - const bool * get_data (void) const { return m_data; } - - OCTAVE_API std::ostream& print (std::ostream& os) const; - - OCTAVE_API Array unconvert (void) const; - - OCTAVE_API Array as_array (void); - - private: + private: - const bool *m_data; - octave_idx_type m_len; - octave_idx_type m_ext; - - // FIXME: I'm not sure if this is a good design. Maybe it would be - // better to employ some sort of generalized iteration scheme. - mutable octave_idx_type m_lsti; - mutable octave_idx_type m_lste; + octave_idx_type m_data; + }; - // This is a trick to allow user-given mask arrays to be used as - // indices without copying. If the following pointer is nonzero, we - // do not own the data, but rather have an Array object that - // provides us the data. Note that we need a pointer because we - // deferred the Array declaration and we do not want it yet to be - // defined. - - Array *m_aowner; - - dim_vector m_orig_dims; - }; - - idx_vector (idx_base_rep *r) : m_rep (r) { } - - // The shared empty vector representation (for fast default - // constructor). - static OCTAVE_API idx_vector_rep * nil_rep (void); - + // The integer vector index. + class OCTAVE_API idx_vector_rep : public idx_base_rep + { public: - // Fast empty constructor. - idx_vector (void) : m_rep (nil_rep ()) { m_rep->m_count++; } + idx_vector_rep (void) + : m_data (nullptr), m_len (0), m_ext (0), m_aowner (nullptr), m_orig_dims () { } + + // Direct constructor. + idx_vector_rep (octave_idx_type *data, octave_idx_type len, + octave_idx_type ext, const dim_vector& od, direct) + : idx_base_rep (), m_data (data), m_len (len), m_ext (ext), + m_aowner (nullptr), m_orig_dims (od) + { } + + // Zero-based constructor. + OCTAVE_API idx_vector_rep (const Array& inda); + + OCTAVE_API idx_vector_rep (const Array& inda, + octave_idx_type ext, direct); + + template + idx_vector_rep (const Array&); + + OCTAVE_API idx_vector_rep (bool); + + OCTAVE_API idx_vector_rep (const Array&, octave_idx_type = -1); + + OCTAVE_API idx_vector_rep (const Sparse&); + + // No copying! + + idx_vector_rep (const idx_vector_rep& idx) = delete; + + idx_vector_rep& operator = (const idx_vector_rep& idx) = delete; + + ~idx_vector_rep (void); + + octave_idx_type xelem (octave_idx_type i) const { return m_data[i]; } + + OCTAVE_API octave_idx_type checkelem (octave_idx_type i) const; + + octave_idx_type length (octave_idx_type) const { return m_len; } + + octave_idx_type extent (octave_idx_type n) const + { return std::max (n, m_ext); } + + idx_class_type idx_class (void) const { return class_vector; } + + idx_base_rep * sort_uniq_clone (bool uniq = false); + + OCTAVE_API idx_base_rep * sort_idx (Array&); + + dim_vector orig_dimensions (void) const { return m_orig_dims; } + + const octave_idx_type * get_data (void) const { return m_data; } + + OCTAVE_API std::ostream& print (std::ostream& os) const; + + OCTAVE_API Array unconvert (void) const; + + OCTAVE_API Array as_array (void); + + private: + + const octave_idx_type *m_data; + octave_idx_type m_len; + octave_idx_type m_ext; + + // This is a trick to allow user-given zero-based arrays to be used + // as indices without copying. If the following pointer is nonzero, + // we do not own the data, but rather have an Array + // object that provides us the data. Note that we need a pointer + // because we deferred the Array declaration and we do not want + // it yet to be defined. + + Array *m_aowner; + + dim_vector m_orig_dims; + }; + + // The logical mask index. + class OCTAVE_API idx_mask_rep : public idx_base_rep + { + public: + + idx_mask_rep (void) = delete; - // Zero-based constructors (for use from C++). - idx_vector (octave_idx_type i) : m_rep (new idx_scalar_rep (i)) { } + // Direct constructor. + idx_mask_rep (bool *data, octave_idx_type len, + octave_idx_type ext, const dim_vector& od, direct) + : idx_base_rep (), m_data (data), m_len (len), m_ext (ext), + m_lsti (-1), m_lste (-1), m_aowner (nullptr), m_orig_dims (od) + { } + + OCTAVE_API idx_mask_rep (bool); + + OCTAVE_API idx_mask_rep (const Array&, octave_idx_type = -1); + + // No copying! + + idx_mask_rep (const idx_mask_rep& idx) = delete; + + idx_mask_rep& operator = (const idx_mask_rep& idx) = delete; + + OCTAVE_API ~idx_mask_rep (void); + + octave_idx_type xelem (octave_idx_type i) const; + + octave_idx_type checkelem (octave_idx_type i) const; + + octave_idx_type length (octave_idx_type) const { return m_len; } + + octave_idx_type extent (octave_idx_type n) const + { return std::max (n, m_ext); } + + idx_class_type idx_class (void) const { return class_mask; } + + idx_base_rep * sort_uniq_clone (bool = false) + { m_count++; return this; } + + OCTAVE_API idx_base_rep * sort_idx (Array&); + + dim_vector orig_dimensions (void) const { return m_orig_dims; } + + bool is_colon_equiv (octave_idx_type n) const + { return m_len == n && m_ext == n; } + + const bool * get_data (void) const { return m_data; } + + OCTAVE_API std::ostream& print (std::ostream& os) const; + + OCTAVE_API Array unconvert (void) const; + + OCTAVE_API Array as_array (void); + + private: + + const bool *m_data; + octave_idx_type m_len; + octave_idx_type m_ext; + + // FIXME: I'm not sure if this is a good design. Maybe it would be + // better to employ some sort of generalized iteration scheme. + mutable octave_idx_type m_lsti; + mutable octave_idx_type m_lste; + + // This is a trick to allow user-given mask arrays to be used as + // indices without copying. If the following pointer is nonzero, we + // do not own the data, but rather have an Array object that + // provides us the data. Note that we need a pointer because we + // deferred the Array declaration and we do not want it yet to be + // defined. + + Array *m_aowner; + + dim_vector m_orig_dims; + }; + + idx_vector (idx_base_rep *r) : m_rep (r) { } + + // The shared empty vector representation (for fast default + // constructor). + static OCTAVE_API idx_vector_rep * nil_rep (void); + +public: + + // Fast empty constructor. + idx_vector (void) : m_rep (nil_rep ()) { m_rep->m_count++; } + + // Zero-based constructors (for use from C++). + idx_vector (octave_idx_type i) : m_rep (new idx_scalar_rep (i)) { } #if OCTAVE_SIZEOF_INT != OCTAVE_SIZEOF_IDX_TYPE - idx_vector (int i) - : m_rep (new idx_scalar_rep (static_cast (i))) { } + idx_vector (int i) + : m_rep (new idx_scalar_rep (static_cast (i))) { } #endif #if (OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_IDX_TYPE \ && OCTAVE_SIZEOF_F77_INT_TYPE != OCTAVE_SIZEOF_INT) - idx_vector (octave_f77_int_type i) - : m_rep (new idx_scalar_rep (static_cast (i))) { } + idx_vector (octave_f77_int_type i) + : m_rep (new idx_scalar_rep (static_cast (i))) { } #endif - idx_vector (octave_idx_type start, octave_idx_type limit, - octave_idx_type step = 1) - : m_rep (new idx_range_rep (start, limit, step)) { } + idx_vector (octave_idx_type start, octave_idx_type limit, + octave_idx_type step = 1) + : m_rep (new idx_range_rep (start, limit, step)) { } - static idx_vector - make_range (octave_idx_type start, octave_idx_type step, - octave_idx_type len) - { - return idx_vector (new idx_range_rep (start, len, step, DIRECT)); - } + static idx_vector + make_range (octave_idx_type start, octave_idx_type step, + octave_idx_type len) + { + return idx_vector (new idx_range_rep (start, len, step, DIRECT)); + } - idx_vector (const Array& inda) - : m_rep (new idx_vector_rep (inda)) { } + idx_vector (const Array& inda) + : m_rep (new idx_vector_rep (inda)) { } - // Directly pass extent, no checking. - idx_vector (const Array& inda, octave_idx_type ext) - : m_rep (new idx_vector_rep (inda, ext, DIRECT)) { } + // Directly pass extent, no checking. + idx_vector (const Array& inda, octave_idx_type ext) + : m_rep (new idx_vector_rep (inda, ext, DIRECT)) { } - // Colon is best constructed by simply copying (or referencing) this member. - static const idx_vector colon; + // Colon is best constructed by simply copying (or referencing) this member. + static const idx_vector colon; - // or passing ':' here - idx_vector (char c) : m_rep (new idx_colon_rep (c)) { } + // or passing ':' here + idx_vector (char c) : m_rep (new idx_colon_rep (c)) { } - // Conversion constructors (used by interpreter). + // Conversion constructors (used by interpreter). - template - idx_vector (octave_int x) : m_rep (new idx_scalar_rep (x)) { } + template + idx_vector (octave_int x) : m_rep (new idx_scalar_rep (x)) { } - idx_vector (double x) : m_rep (new idx_scalar_rep (x)) { } + idx_vector (double x) : m_rep (new idx_scalar_rep (x)) { } - idx_vector (float x) : m_rep (new idx_scalar_rep (x)) { } + idx_vector (float x) : m_rep (new idx_scalar_rep (x)) { } - // A scalar bool does not necessarily map to scalar index. - idx_vector (bool x) : m_rep (new idx_mask_rep (x)) { } + // A scalar bool does not necessarily map to scalar index. + idx_vector (bool x) : m_rep (new idx_mask_rep (x)) { } - template - idx_vector (const Array>& nda) - : m_rep (new idx_vector_rep (nda)) { } + template + idx_vector (const Array>& nda) + : m_rep (new idx_vector_rep (nda)) { } - idx_vector (const Array& nda) : m_rep (new idx_vector_rep (nda)) { } + idx_vector (const Array& nda) : m_rep (new idx_vector_rep (nda)) { } - idx_vector (const Array& nda) : m_rep (new idx_vector_rep (nda)) { } + idx_vector (const Array& nda) : m_rep (new idx_vector_rep (nda)) { } - OCTAVE_API idx_vector (const Array& nda); + OCTAVE_API idx_vector (const Array& nda); - idx_vector (const range& r) : m_rep (new idx_range_rep (r)) { } + idx_vector (const range& r) : m_rep (new idx_range_rep (r)) { } - idx_vector (const Sparse& nda) : m_rep (new idx_vector_rep (nda)) { } + idx_vector (const Sparse& nda) : m_rep (new idx_vector_rep (nda)) { } - idx_vector (const idx_vector& a) : m_rep (a.m_rep) { m_rep->m_count++; } + idx_vector (const idx_vector& a) : m_rep (a.m_rep) { m_rep->m_count++; } - ~idx_vector (void) - { - if (--m_rep->m_count == 0 && m_rep != nil_rep ()) - delete m_rep; - } + ~idx_vector (void) + { + if (--m_rep->m_count == 0 && m_rep != nil_rep ()) + delete m_rep; + } - idx_vector& operator = (const idx_vector& a) - { - if (this != &a) - { - if (--m_rep->m_count == 0 && m_rep != nil_rep ()) - delete m_rep; + idx_vector& operator = (const idx_vector& a) + { + if (this != &a) + { + if (--m_rep->m_count == 0 && m_rep != nil_rep ()) + delete m_rep; - m_rep = a.m_rep; - m_rep->m_count++; - } - return *this; - } + m_rep = a.m_rep; + m_rep->m_count++; + } + return *this; + } - idx_class_type idx_class (void) const { return m_rep->idx_class (); } + idx_class_type idx_class (void) const { return m_rep->idx_class (); } - octave_idx_type length (octave_idx_type n = 0) const - { return m_rep->length (n); } + octave_idx_type length (octave_idx_type n = 0) const + { return m_rep->length (n); } - octave_idx_type extent (octave_idx_type n) const - { return m_rep->extent (n); } + octave_idx_type extent (octave_idx_type n) const + { return m_rep->extent (n); } - octave_idx_type xelem (octave_idx_type n) const - { return m_rep->xelem (n); } + octave_idx_type xelem (octave_idx_type n) const + { return m_rep->xelem (n); } - octave_idx_type checkelem (octave_idx_type n) const - { return m_rep->xelem (n); } + octave_idx_type checkelem (octave_idx_type n) const + { return m_rep->xelem (n); } - octave_idx_type operator () (octave_idx_type n) const - { return m_rep->xelem (n); } + octave_idx_type operator () (octave_idx_type n) const + { return m_rep->xelem (n); } - // FIXME: idx_vector objects are either created successfully or an - // error is thrown, so this method no longer makes sense. - operator bool (void) const { return true; } + // FIXME: idx_vector objects are either created successfully or an + // error is thrown, so this method no longer makes sense. + operator bool (void) const { return true; } - bool is_colon (void) const - { return m_rep->idx_class () == class_colon; } + bool is_colon (void) const + { return m_rep->idx_class () == class_colon; } - bool is_scalar (void) const - { return m_rep->idx_class () == class_scalar; } + bool is_scalar (void) const + { return m_rep->idx_class () == class_scalar; } - bool is_range (void) const - { return m_rep->idx_class () == class_range; } + bool is_range (void) const + { return m_rep->idx_class () == class_range; } - bool is_colon_equiv (octave_idx_type n) const - { return m_rep->is_colon_equiv (n); } + bool is_colon_equiv (octave_idx_type n) const + { return m_rep->is_colon_equiv (n); } - idx_vector sorted (bool uniq = false) const - { return idx_vector (m_rep->sort_uniq_clone (uniq)); } + idx_vector sorted (bool uniq = false) const + { return idx_vector (m_rep->sort_uniq_clone (uniq)); } - idx_vector sorted (Array& sidx) const - { return idx_vector (m_rep->sort_idx (sidx)); } + idx_vector sorted (Array& sidx) const + { return idx_vector (m_rep->sort_idx (sidx)); } - dim_vector orig_dimensions (void) const { return m_rep->orig_dimensions (); } + dim_vector orig_dimensions (void) const { return m_rep->orig_dimensions (); } - octave_idx_type orig_rows (void) const - { return orig_dimensions () (0); } + octave_idx_type orig_rows (void) const + { return orig_dimensions () (0); } - octave_idx_type orig_columns (void) const - { return orig_dimensions () (1); } + octave_idx_type orig_columns (void) const + { return orig_dimensions () (1); } - int orig_empty (void) const - { return (! is_colon () && orig_dimensions ().any_zero ()); } + int orig_empty (void) const + { return (! is_colon () && orig_dimensions ().any_zero ()); } - // i/o + // i/o - std::ostream& print (std::ostream& os) const { return m_rep->print (os); } + std::ostream& print (std::ostream& os) const { return m_rep->print (os); } - friend std::ostream& operator << (std::ostream& os, const idx_vector& a) - { return a.print (os); } + friend std::ostream& operator << (std::ostream& os, const idx_vector& a) + { return a.print (os); } - // Slice with specializations. No checking of bounds! - // - // This is equivalent to the following loop (but much faster): - // - // for (octave_idx_type i = 0; i < idx->length (n); i++) - // dest[i] = src[idx(i)]; - // return i; - // - template - octave_idx_type - index (const T *src, octave_idx_type n, T *dest) const - { - octave_idx_type len = m_rep->length (n); + // Slice with specializations. No checking of bounds! + // + // This is equivalent to the following loop (but much faster): + // + // for (octave_idx_type i = 0; i < idx->length (n); i++) + // dest[i] = src[idx(i)]; + // return i; + // + template + octave_idx_type + index (const T *src, octave_idx_type n, T *dest) const + { + octave_idx_type len = m_rep->length (n); - switch (m_rep->idx_class ()) - { - case class_colon: - std::copy_n (src, len, dest); - break; + switch (m_rep->idx_class ()) + { + case class_colon: + std::copy_n (src, len, dest); + break; - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type start = r->get_start (); - octave_idx_type step = r->get_step (); - const T *ssrc = src + start; - if (step == 1) - std::copy_n (ssrc, len, dest); - else if (step == -1) - std::reverse_copy (ssrc - len + 1, ssrc + 1, dest); - else if (step == 0) - std::fill_n (dest, len, *ssrc); - else - { - for (octave_idx_type i = 0, j = 0; i < len; i++, j += step) - dest[i] = ssrc[j]; - } - } - break; + case class_range: + { + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type start = r->get_start (); + octave_idx_type step = r->get_step (); + const T *ssrc = src + start; + if (step == 1) + std::copy_n (ssrc, len, dest); + else if (step == -1) + std::reverse_copy (ssrc - len + 1, ssrc + 1, dest); + else if (step == 0) + std::fill_n (dest, len, *ssrc); + else + { + for (octave_idx_type i = 0, j = 0; i < len; i++, j += step) + dest[i] = ssrc[j]; + } + } + break; - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - dest[0] = src[r->get_data ()]; - } - break; + case class_scalar: + { + idx_scalar_rep *r = dynamic_cast (m_rep); + dest[0] = src[r->get_data ()]; + } + break; - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *data = r->get_data (); - for (octave_idx_type i = 0; i < len; i++) - dest[i] = src[data[i]]; - } - break; + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *data = r->get_data (); + for (octave_idx_type i = 0; i < len; i++) + dest[i] = src[data[i]]; + } + break; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *data = r->get_data (); - octave_idx_type ext = r->extent (0); - for (octave_idx_type i = 0; i < ext; i++) - if (data[i]) *dest++ = src[i]; - } - break; + case class_mask: + { + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *data = r->get_data (); + octave_idx_type ext = r->extent (0); + for (octave_idx_type i = 0; i < ext; i++) + if (data[i]) *dest++ = src[i]; + } + break; - default: - assert (false); - break; - } + default: + assert (false); + break; + } - return len; - } + return len; + } - // Slice assignment with specializations. No checking of bounds! - // - // This is equivalent to the following loop (but much faster): - // - // for (octave_idx_type i = 0; i < idx->length (n); i++) - // dest[idx(i)] = src[i]; - // return i; - // - template - octave_idx_type - assign (const T *src, octave_idx_type n, T *dest) const - { - octave_idx_type len = m_rep->length (n); + // Slice assignment with specializations. No checking of bounds! + // + // This is equivalent to the following loop (but much faster): + // + // for (octave_idx_type i = 0; i < idx->length (n); i++) + // dest[idx(i)] = src[i]; + // return i; + // + template + octave_idx_type + assign (const T *src, octave_idx_type n, T *dest) const + { + octave_idx_type len = m_rep->length (n); - switch (m_rep->idx_class ()) - { - case class_colon: - std::copy_n (src, len, dest); - break; + switch (m_rep->idx_class ()) + { + case class_colon: + std::copy_n (src, len, dest); + break; - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type start = r->get_start (); - octave_idx_type step = r->get_step (); - T *sdest = dest + start; - if (step == 1) - std::copy_n (src, len, sdest); - else if (step == -1) - std::reverse_copy (src, src + len, sdest - len + 1); - else - { - for (octave_idx_type i = 0, j = 0; i < len; i++, j += step) - sdest[j] = src[i]; - } - } - break; + case class_range: + { + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type start = r->get_start (); + octave_idx_type step = r->get_step (); + T *sdest = dest + start; + if (step == 1) + std::copy_n (src, len, sdest); + else if (step == -1) + std::reverse_copy (src, src + len, sdest - len + 1); + else + { + for (octave_idx_type i = 0, j = 0; i < len; i++, j += step) + sdest[j] = src[i]; + } + } + break; - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - dest[r->get_data ()] = src[0]; - } - break; + case class_scalar: + { + idx_scalar_rep *r = dynamic_cast (m_rep); + dest[r->get_data ()] = src[0]; + } + break; - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *data = r->get_data (); - for (octave_idx_type i = 0; i < len; i++) - dest[data[i]] = src[i]; - } - break; + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *data = r->get_data (); + for (octave_idx_type i = 0; i < len; i++) + dest[data[i]] = src[i]; + } + break; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *data = r->get_data (); - octave_idx_type ext = r->extent (0); - for (octave_idx_type i = 0; i < ext; i++) - if (data[i]) dest[i] = *src++; - } - break; + case class_mask: + { + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *data = r->get_data (); + octave_idx_type ext = r->extent (0); + for (octave_idx_type i = 0; i < ext; i++) + if (data[i]) dest[i] = *src++; + } + break; - default: - assert (false); - break; - } + default: + assert (false); + break; + } - return len; - } + return len; + } - // Slice fill with specializations. No checking of bounds! - // - // This is equivalent to the following loop (but much faster): - // - // for (octave_idx_type i = 0; i < idx->length (n); i++) - // dest[idx(i)] = val; - // return i; - // - template - octave_idx_type - fill (const T& val, octave_idx_type n, T *dest) const - { - octave_idx_type len = m_rep->length (n); + // Slice fill with specializations. No checking of bounds! + // + // This is equivalent to the following loop (but much faster): + // + // for (octave_idx_type i = 0; i < idx->length (n); i++) + // dest[idx(i)] = val; + // return i; + // + template + octave_idx_type + fill (const T& val, octave_idx_type n, T *dest) const + { + octave_idx_type len = m_rep->length (n); - switch (m_rep->idx_class ()) - { - case class_colon: - std::fill_n (dest, len, val); - break; + switch (m_rep->idx_class ()) + { + case class_colon: + std::fill_n (dest, len, val); + break; - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type start = r->get_start (); - octave_idx_type step = r->get_step (); - T *sdest = dest + start; - if (step == 1) - std::fill_n (sdest, len, val); - else if (step == -1) - std::fill (sdest - len + 1, sdest + 1, val); - else - { - for (octave_idx_type i = 0, j = 0; i < len; i++, j += step) - sdest[j] = val; - } - } - break; + case class_range: + { + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type start = r->get_start (); + octave_idx_type step = r->get_step (); + T *sdest = dest + start; + if (step == 1) + std::fill_n (sdest, len, val); + else if (step == -1) + std::fill (sdest - len + 1, sdest + 1, val); + else + { + for (octave_idx_type i = 0, j = 0; i < len; i++, j += step) + sdest[j] = val; + } + } + break; - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - dest[r->get_data ()] = val; - } - break; + case class_scalar: + { + idx_scalar_rep *r = dynamic_cast (m_rep); + dest[r->get_data ()] = val; + } + break; - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *data = r->get_data (); - for (octave_idx_type i = 0; i < len; i++) - dest[data[i]] = val; - } - break; + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *data = r->get_data (); + for (octave_idx_type i = 0; i < len; i++) + dest[data[i]] = val; + } + break; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *data = r->get_data (); - octave_idx_type ext = r->extent (0); - for (octave_idx_type i = 0; i < ext; i++) - if (data[i]) dest[i] = val; - } - break; + case class_mask: + { + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *data = r->get_data (); + octave_idx_type ext = r->extent (0); + for (octave_idx_type i = 0; i < ext; i++) + if (data[i]) dest[i] = val; + } + break; - default: - assert (false); - break; - } + default: + assert (false); + break; + } - return len; - } + return len; + } - // Generic non-breakable indexed loop. The loop body should be - // encapsulated in a single functor body. This is equivalent to the - // following loop (but faster, at least for simple inlined bodies): - // - // for (octave_idx_type i = 0; i < idx->length (n); i++) body (idx(i)); + // Generic non-breakable indexed loop. The loop body should be + // encapsulated in a single functor body. This is equivalent to the + // following loop (but faster, at least for simple inlined bodies): + // + // for (octave_idx_type i = 0; i < idx->length (n); i++) body (idx(i)); - template - void - loop (octave_idx_type n, Functor body) const - { - octave_idx_type len = m_rep->length (n); + template + void + loop (octave_idx_type n, Functor body) const + { + octave_idx_type len = m_rep->length (n); - switch (m_rep->idx_class ()) + switch (m_rep->idx_class ()) + { + case class_colon: + for (octave_idx_type i = 0; i < len; i++) body (i); + break; + + case class_range: { - case class_colon: - for (octave_idx_type i = 0; i < len; i++) body (i); - break; - - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type start = r->get_start (); - octave_idx_type step = r->get_step (); - octave_idx_type i, j; - if (step == 1) - for (i = start, j = start + len; i < j; i++) body (i); - else if (step == -1) - for (i = start, j = start - len; i > j; i--) body (i); - else - for (i = 0, j = start; i < len; i++, j += step) body (j); - } - break; + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type start = r->get_start (); + octave_idx_type step = r->get_step (); + octave_idx_type i, j; + if (step == 1) + for (i = start, j = start + len; i < j; i++) body (i); + else if (step == -1) + for (i = start, j = start - len; i > j; i--) body (i); + else + for (i = 0, j = start; i < len; i++, j += step) body (j); + } + break; - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - body (r->get_data ()); - } - break; + case class_scalar: + { + idx_scalar_rep *r = dynamic_cast (m_rep); + body (r->get_data ()); + } + break; - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *data = r->get_data (); - for (octave_idx_type i = 0; i < len; i++) body (data[i]); - } - break; + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *data = r->get_data (); + for (octave_idx_type i = 0; i < len; i++) body (data[i]); + } + break; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *data = r->get_data (); - octave_idx_type ext = r->extent (0); - for (octave_idx_type i = 0; i < ext; i++) - if (data[i]) body (i); - } - break; + case class_mask: + { + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *data = r->get_data (); + octave_idx_type ext = r->extent (0); + for (octave_idx_type i = 0; i < ext; i++) + if (data[i]) body (i); + } + break; - default: - assert (false); - break; - } + default: + assert (false); + break; + } - } + } - // Generic breakable indexed loop. The loop body should be - // encapsulated in a single functor body. This is equivalent to the - // following loop (but faster, at least for simple inlined bodies): - // - // for (octave_idx_type i = 0; i < idx->length (n); i++) - // if (body (idx(i))) break; - // return i; - // + // Generic breakable indexed loop. The loop body should be + // encapsulated in a single functor body. This is equivalent to the + // following loop (but faster, at least for simple inlined bodies): + // + // for (octave_idx_type i = 0; i < idx->length (n); i++) + // if (body (idx(i))) break; + // return i; + // - template - octave_idx_type - bloop (octave_idx_type n, Functor body) const - { - octave_idx_type len = m_rep->length (n), ret; + template + octave_idx_type + bloop (octave_idx_type n, Functor body) const + { + octave_idx_type len = m_rep->length (n), ret; - switch (m_rep->idx_class ()) + switch (m_rep->idx_class ()) + { + case class_colon: { - case class_colon: - { - octave_idx_type i; - for (i = 0; i < len && body (i); i++) ; - ret = i; - } - break; + octave_idx_type i; + for (i = 0; i < len && body (i); i++) ; + ret = i; + } + break; - case class_range: - { - idx_range_rep *r = dynamic_cast (m_rep); - octave_idx_type start = r->get_start (); - octave_idx_type step = r->get_step (); - octave_idx_type i, j; - if (step == 1) - for (i = start, j = start + len; i < j && body (i); i++) ; - else if (step == -1) - for (i = start, j = start - len; i > j && body (i); i--) ; - else - for (i = 0, j = start; i < len && body (j); i++, j += step) ; - ret = i; - } - break; + case class_range: + { + idx_range_rep *r = dynamic_cast (m_rep); + octave_idx_type start = r->get_start (); + octave_idx_type step = r->get_step (); + octave_idx_type i, j; + if (step == 1) + for (i = start, j = start + len; i < j && body (i); i++) ; + else if (step == -1) + for (i = start, j = start - len; i > j && body (i); i--) ; + else + for (i = 0, j = start; i < len && body (j); i++, j += step) ; + ret = i; + } + break; - case class_scalar: - { - idx_scalar_rep *r = dynamic_cast (m_rep); - ret = (body (r->get_data ()) ? 1 : 0); - } - break; + case class_scalar: + { + idx_scalar_rep *r = dynamic_cast (m_rep); + ret = (body (r->get_data ()) ? 1 : 0); + } + break; - case class_vector: - { - idx_vector_rep *r = dynamic_cast (m_rep); - const octave_idx_type *data = r->get_data (); - octave_idx_type i; - for (i = 0; i < len && body (data[i]); i++) ; - ret = i; - } - break; + case class_vector: + { + idx_vector_rep *r = dynamic_cast (m_rep); + const octave_idx_type *data = r->get_data (); + octave_idx_type i; + for (i = 0; i < len && body (data[i]); i++) ; + ret = i; + } + break; - case class_mask: - { - idx_mask_rep *r = dynamic_cast (m_rep); - const bool *data = r->get_data (); - octave_idx_type ext = r->extent (0); - octave_idx_type j = 0; - for (octave_idx_type i = 0; i < ext; i++) - { - if (data[i]) - { - if (body (i)) - break; - else - j++; - } - } + case class_mask: + { + idx_mask_rep *r = dynamic_cast (m_rep); + const bool *data = r->get_data (); + octave_idx_type ext = r->extent (0); + octave_idx_type j = 0; + for (octave_idx_type i = 0; i < ext; i++) + { + if (data[i]) + { + if (body (i)) + break; + else + j++; + } + } - ret = j; - } - break; - - default: - assert (false); - break; + ret = j; } + break; - return ret; - } + default: + assert (false); + break; + } + + return ret; + } - // Rationale: - // This method is the key to "smart indexing". When indexing cartesian - // arrays, sometimes consecutive index vectors can be reduced into a - // single index. If rows (A) = k and i.maybe_reduce (j) gives k, then - // A(i,j)(:) is equal to A(k)(:). + // Rationale: + // This method is the key to "smart indexing". When indexing cartesian + // arrays, sometimes consecutive index vectors can be reduced into a + // single index. If rows (A) = k and i.maybe_reduce (j) gives k, then + // A(i,j)(:) is equal to A(k)(:). - // If the next index can be reduced, returns true and updates this. - OCTAVE_API bool - maybe_reduce (octave_idx_type n, const idx_vector& j, octave_idx_type nj); - - OCTAVE_API bool - is_cont_range (octave_idx_type n, octave_idx_type& l, - octave_idx_type& u) const; + // If the next index can be reduced, returns true and updates this. + OCTAVE_API bool + maybe_reduce (octave_idx_type n, const idx_vector& j, octave_idx_type nj); - // Returns the increment for ranges and colon, 0 for scalars and empty - // vectors, 1st difference otherwise. - OCTAVE_API octave_idx_type increment (void) const; + OCTAVE_API bool + is_cont_range (octave_idx_type n, octave_idx_type& l, + octave_idx_type& u) const; - OCTAVE_API idx_vector - complement (octave_idx_type n) const; - - OCTAVE_API bool is_permutation (octave_idx_type n) const; + // Returns the increment for ranges and colon, 0 for scalars and empty + // vectors, 1st difference otherwise. + OCTAVE_API octave_idx_type increment (void) const; - // Returns the inverse permutation. If this is not a permutation on 1:n, the - // result is undefined (but no error unless extent () != n). - OCTAVE_API idx_vector inverse_permutation (octave_idx_type n) const; + OCTAVE_API idx_vector + complement (octave_idx_type n) const; + + OCTAVE_API bool is_permutation (octave_idx_type n) const; - // Copies all the indices to a given array. Not allowed for colons. - OCTAVE_API void copy_data (octave_idx_type *data) const; + // Returns the inverse permutation. If this is not a permutation on 1:n, the + // result is undefined (but no error unless extent () != n). + OCTAVE_API idx_vector inverse_permutation (octave_idx_type n) const; - // If the index is a mask, convert it to index vector. - OCTAVE_API idx_vector unmask (void) const; + // Copies all the indices to a given array. Not allowed for colons. + OCTAVE_API void copy_data (octave_idx_type *data) const; - // Unconverts the index to a scalar, Range, double array or a mask. - OCTAVE_API void - unconvert (idx_class_type& iclass, double& scalar, range& range, - Array& array, Array& mask) const; + // If the index is a mask, convert it to index vector. + OCTAVE_API idx_vector unmask (void) const; - OCTAVE_API Array as_array (void) const; + // Unconverts the index to a scalar, Range, double array or a mask. + OCTAVE_API void + unconvert (idx_class_type& iclass, double& scalar, range& range, + Array& array, Array& mask) const; - // Raw pointer to index array. This is non-const because it may be - // necessary to mutate the index. - const OCTAVE_API octave_idx_type * raw (void); - - OCTAVE_API bool isvector (void) const; + OCTAVE_API Array as_array (void) const; - // FIXME: these are here for compatibility. They should be removed - // when no longer in use. + // Raw pointer to index array. This is non-const because it may be + // necessary to mutate the index. + const OCTAVE_API octave_idx_type * raw (void); - octave_idx_type elem (octave_idx_type n) const - { return (*this) (n); } + OCTAVE_API bool isvector (void) const; + + // FIXME: these are here for compatibility. They should be removed + // when no longer in use. - bool is_colon_equiv (octave_idx_type n, int) const - { return is_colon_equiv (n); } + octave_idx_type elem (octave_idx_type n) const + { return (*this) (n); } - OCTAVE_API octave_idx_type - freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false); + bool is_colon_equiv (octave_idx_type n, int) const + { return is_colon_equiv (n); } - void sort (bool uniq = false) - { *this = sorted (uniq); } + OCTAVE_API octave_idx_type + freeze (octave_idx_type z_len, const char *tag, bool resize_ok = false); - OCTAVE_API octave_idx_type ones_count (void) const; + void sort (bool uniq = false) + { *this = sorted (uniq); } - octave_idx_type max (void) const { return extent (1) - 1; } + OCTAVE_API octave_idx_type ones_count (void) const; - private: + octave_idx_type max (void) const { return extent (1) - 1; } + +private: - idx_base_rep *m_rep; + idx_base_rep *m_rep; - }; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/array/range-fwd.h --- a/liboctave/array/range-fwd.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/array/range-fwd.h Thu Dec 01 20:05:44 2022 -0800 @@ -30,7 +30,7 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template class OCTAVE_API range; +template class OCTAVE_API range; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/CollocWt.cc --- a/liboctave/numeric/CollocWt.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/CollocWt.cc Thu Dec 01 20:05:44 2022 -0800 @@ -47,459 +47,459 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Compute the first three derivatives of the node polynomial. - // - // n0 (alpha,beta) n1 - // p (x) = (x) * p (x) * (1 - x) - // nt n - // - // at the interpolation points. Each of the parameters n0 and n1 - // may be given the value 0 or 1. The total number of points - // nt = n + n0 + n1 - // - // The values of root must be known before a call to dif is possible. - // They may be computed using jcobi. +// Compute the first three derivatives of the node polynomial. +// +// n0 (alpha,beta) n1 +// p (x) = (x) * p (x) * (1 - x) +// nt n +// +// at the interpolation points. Each of the parameters n0 and n1 +// may be given the value 0 or 1. The total number of points +// nt = n + n0 + n1 +// +// The values of root must be known before a call to dif is possible. +// They may be computed using jcobi. - static void dif (octave_idx_type nt, double *root, double *dif1, - double *dif2, double *dif3) - { - // Evaluate derivatives of node polynomial using recursion formulas. +static void dif (octave_idx_type nt, double *root, double *dif1, + double *dif2, double *dif3) +{ + // Evaluate derivatives of node polynomial using recursion formulas. - for (octave_idx_type i = 0; i < nt; i++) - { - double x = root[i]; + for (octave_idx_type i = 0; i < nt; i++) + { + double x = root[i]; - dif1[i] = 1.0; - dif2[i] = 0.0; - dif3[i] = 0.0; + dif1[i] = 1.0; + dif2[i] = 0.0; + dif3[i] = 0.0; - for (octave_idx_type j = 0; j < nt; j++) - { - if (j != i) - { - double y = x - root[j]; + for (octave_idx_type j = 0; j < nt; j++) + { + if (j != i) + { + double y = x - root[j]; - dif3[i] = y * dif3[i] + 3.0 * dif2[i]; - dif2[i] = y * dif2[i] + 2.0 * dif1[i]; - dif1[i] = y * dif1[i]; - } - } - } - } + dif3[i] = y * dif3[i] + 3.0 * dif2[i]; + dif2[i] = y * dif2[i] + 2.0 * dif1[i]; + dif1[i] = y * dif1[i]; + } + } + } +} - // Compute the zeros of the Jacobi polynomial. - // - // (alpha,beta) - // p (x) - // n - // - // Use dif to compute the derivatives of the node - // polynomial - // - // n0 (alpha,beta) n1 - // p (x) = (x) * p (x) * (1 - x) - // nt n - // - // at the interpolation points. - // - // See Villadsen and Michelsen, pages 131-132 and 418. - // - // Input parameters: - // - // nd : the dimension of the vectors dif1, dif2, dif3, and root - // - // n : the degree of the jacobi polynomial, (i.e., the number - // of interior interpolation points) - // - // n0 : determines whether x = 0 is included as an - // interpolation point - // - // n0 = 0 ==> x = 0 is not included - // n0 = 1 ==> x = 0 is included - // - // n1 : determines whether x = 1 is included as an - // interpolation point - // - // n1 = 0 ==> x = 1 is not included - // n1 = 1 ==> x = 1 is included - // - // alpha : the value of alpha in the description of the jacobi - // polynomial - // - // beta : the value of beta in the description of the jacobi - // polynomial - // - // For a more complete explanation of alpha an beta, see Villadsen - // and Michelsen, pages 57 to 59. - // - // Output parameters: - // - // root : one dimensional vector containing on exit the - // n + n0 + n1 zeros of the node polynomial used in the - // interpolation routine - // - // dif1 : one dimensional vector containing the first derivative - // of the node polynomial at the zeros - // - // dif2 : one dimensional vector containing the second derivative - // of the node polynomial at the zeros - // - // dif3 : one dimensional vector containing the third derivative - // of the node polynomial at the zeros +// Compute the zeros of the Jacobi polynomial. +// +// (alpha,beta) +// p (x) +// n +// +// Use dif to compute the derivatives of the node +// polynomial +// +// n0 (alpha,beta) n1 +// p (x) = (x) * p (x) * (1 - x) +// nt n +// +// at the interpolation points. +// +// See Villadsen and Michelsen, pages 131-132 and 418. +// +// Input parameters: +// +// nd : the dimension of the vectors dif1, dif2, dif3, and root +// +// n : the degree of the jacobi polynomial, (i.e., the number +// of interior interpolation points) +// +// n0 : determines whether x = 0 is included as an +// interpolation point +// +// n0 = 0 ==> x = 0 is not included +// n0 = 1 ==> x = 0 is included +// +// n1 : determines whether x = 1 is included as an +// interpolation point +// +// n1 = 0 ==> x = 1 is not included +// n1 = 1 ==> x = 1 is included +// +// alpha : the value of alpha in the description of the jacobi +// polynomial +// +// beta : the value of beta in the description of the jacobi +// polynomial +// +// For a more complete explanation of alpha an beta, see Villadsen +// and Michelsen, pages 57 to 59. +// +// Output parameters: +// +// root : one dimensional vector containing on exit the +// n + n0 + n1 zeros of the node polynomial used in the +// interpolation routine +// +// dif1 : one dimensional vector containing the first derivative +// of the node polynomial at the zeros +// +// dif2 : one dimensional vector containing the second derivative +// of the node polynomial at the zeros +// +// dif3 : one dimensional vector containing the third derivative +// of the node polynomial at the zeros - static bool jcobi (octave_idx_type n, octave_idx_type n0, octave_idx_type n1, - double alpha, double beta, double *dif1, double *dif2, - double *dif3, double *root) - { - assert (n0 == 0 || n0 == 1); - assert (n1 == 0 || n1 == 1); +static bool jcobi (octave_idx_type n, octave_idx_type n0, octave_idx_type n1, + double alpha, double beta, double *dif1, double *dif2, + double *dif3, double *root) +{ + assert (n0 == 0 || n0 == 1); + assert (n1 == 0 || n1 == 1); - octave_idx_type nt = n + n0 + n1; + octave_idx_type nt = n + n0 + n1; - assert (nt >= 1); + assert (nt >= 1); - // -- first evaluation of coefficients in recursion formulas. - // -- recursion coefficients are stored in dif1 and dif2. + // -- first evaluation of coefficients in recursion formulas. + // -- recursion coefficients are stored in dif1 and dif2. - double ab = alpha + beta; - double ad = beta - alpha; - double ap = beta * alpha; + double ab = alpha + beta; + double ad = beta - alpha; + double ap = beta * alpha; - dif1[0] = (ad / (ab + 2.0) + 1.0) / 2.0; - dif2[0] = 0.0; + dif1[0] = (ad / (ab + 2.0) + 1.0) / 2.0; + dif2[0] = 0.0; - if (n >= 2) - { - for (octave_idx_type i = 1; i < n; i++) - { - double z1 = i; - double z = ab + 2 * z1; + if (n >= 2) + { + for (octave_idx_type i = 1; i < n; i++) + { + double z1 = i; + double z = ab + 2 * z1; - dif1[i] = (ab * ad / z / (z + 2.0) + 1.0) / 2.0; + dif1[i] = (ab * ad / z / (z + 2.0) + 1.0) / 2.0; - if (i == 1) - dif2[i] = (ab + ap + z1) / z / z / (z + 1.0); - else - { - z *= z; - double y = z1 * (ab + z1); - y *= (ap + y); - dif2[i] = y / z / (z - 1.0); - } - } - } + if (i == 1) + dif2[i] = (ab + ap + z1) / z / z / (z + 1.0); + else + { + z *= z; + double y = z1 * (ab + z1); + y *= (ap + y); + dif2[i] = y / z / (z - 1.0); + } + } + } - // Root determination by Newton method with suppression of previously - // determined roots. + // Root determination by Newton method with suppression of previously + // determined roots. - double x = 0.0; + double x = 0.0; - for (octave_idx_type i = 0; i < n; i++) - { - bool done = false; + for (octave_idx_type i = 0; i < n; i++) + { + bool done = false; - int k = 0; + int k = 0; - while (! done) - { - double xd = 0.0; - double xn = 1.0; - double xd1 = 0.0; - double xn1 = 0.0; + while (! done) + { + double xd = 0.0; + double xn = 1.0; + double xd1 = 0.0; + double xn1 = 0.0; - for (octave_idx_type j = 0; j < n; j++) - { - double xp = (dif1[j] - x) * xn - dif2[j] * xd; - double xp1 = (dif1[j] - x) * xn1 - dif2[j] * xd1 - xn; + for (octave_idx_type j = 0; j < n; j++) + { + double xp = (dif1[j] - x) * xn - dif2[j] * xd; + double xp1 = (dif1[j] - x) * xn1 - dif2[j] * xd1 - xn; - xd = xn; - xd1 = xn1; - xn = xp; - xn1 = xp1; - } + xd = xn; + xd1 = xn1; + xn = xp; + xn1 = xp1; + } - double zc = 1.0; - double z = xn / xn1; + double zc = 1.0; + double z = xn / xn1; - if (i != 0) - { - for (octave_idx_type j = 1; j <= i; j++) - zc -= z / (x - root[j-1]); - } + if (i != 0) + { + for (octave_idx_type j = 1; j <= i; j++) + zc -= z / (x - root[j-1]); + } - z /= zc; - x -= z; + z /= zc; + x -= z; - // Famous last words: 100 iterations should be more than - // enough in all cases. + // Famous last words: 100 iterations should be more than + // enough in all cases. - if (++k > 100 || math::isnan (z)) - return false; + if (++k > 100 || math::isnan (z)) + return false; - if (std::abs (z) <= 100 * std::numeric_limits::epsilon ()) - done = true; - } + if (std::abs (z) <= 100 * std::numeric_limits::epsilon ()) + done = true; + } - root[i] = x; - x += std::sqrt (std::numeric_limits::epsilon ()); - } + root[i] = x; + x += std::sqrt (std::numeric_limits::epsilon ()); + } - // Add interpolation points at x = 0 and/or x = 1. + // Add interpolation points at x = 0 and/or x = 1. - if (n0 != 0) - { - for (octave_idx_type i = n; i > 0; i--) - root[i] = root[i-1]; + if (n0 != 0) + { + for (octave_idx_type i = n; i > 0; i--) + root[i] = root[i-1]; - root[0] = 0.0; - } + root[0] = 0.0; + } - if (n1 != 0) - root[nt-1] = 1.0; + if (n1 != 0) + root[nt-1] = 1.0; - dif (nt, root, dif1, dif2, dif3); + dif (nt, root, dif1, dif2, dif3); - return true; - } + return true; +} - // Compute derivative weights for orthogonal collocation. - // - // See Villadsen and Michelsen, pages 133-134, 419. - // - // Input parameters: - // - // nd : the dimension of the vectors dif1, dif2, dif3, and root - // - // n : the degree of the jacobi polynomial, (i.e., the number - // of interior interpolation points) - // - // n0 : determines whether x = 0 is included as an - // interpolation point - // - // n0 = 0 ==> x = 0 is not included - // n0 = 1 ==> x = 0 is included - // - // n1 : determines whether x = 1 is included as an - // interpolation point - // - // n1 = 0 ==> x = 1 is not included - // n1 = 1 ==> x = 1 is included - // - // i : the index of the node for which the weights are to be - // calculated - // - // id : indicator - // - // id = 1 ==> first derivative weights are computed - // id = 2 ==> second derivative weights are computed - // id = 3 ==> gaussian weights are computed (in this - // case, the value of i is irrelevant) - // - // Output parameters: - // - // dif1 : one dimensional vector containing the first derivative - // of the node polynomial at the zeros - // - // dif2 : one dimensional vector containing the second derivative - // of the node polynomial at the zeros - // - // dif3 : one dimensional vector containing the third derivative - // of the node polynomial at the zeros - // - // vect : one dimensional vector of computed weights +// Compute derivative weights for orthogonal collocation. +// +// See Villadsen and Michelsen, pages 133-134, 419. +// +// Input parameters: +// +// nd : the dimension of the vectors dif1, dif2, dif3, and root +// +// n : the degree of the jacobi polynomial, (i.e., the number +// of interior interpolation points) +// +// n0 : determines whether x = 0 is included as an +// interpolation point +// +// n0 = 0 ==> x = 0 is not included +// n0 = 1 ==> x = 0 is included +// +// n1 : determines whether x = 1 is included as an +// interpolation point +// +// n1 = 0 ==> x = 1 is not included +// n1 = 1 ==> x = 1 is included +// +// i : the index of the node for which the weights are to be +// calculated +// +// id : indicator +// +// id = 1 ==> first derivative weights are computed +// id = 2 ==> second derivative weights are computed +// id = 3 ==> gaussian weights are computed (in this +// case, the value of i is irrelevant) +// +// Output parameters: +// +// dif1 : one dimensional vector containing the first derivative +// of the node polynomial at the zeros +// +// dif2 : one dimensional vector containing the second derivative +// of the node polynomial at the zeros +// +// dif3 : one dimensional vector containing the third derivative +// of the node polynomial at the zeros +// +// vect : one dimensional vector of computed weights - static void dfopr (octave_idx_type n, octave_idx_type n0, octave_idx_type n1, - octave_idx_type i, octave_idx_type id, double *dif1, - double *dif2, double *dif3, double *root, double *vect) - { - assert (n0 == 0 || n0 == 1); - assert (n1 == 0 || n1 == 1); +static void dfopr (octave_idx_type n, octave_idx_type n0, octave_idx_type n1, + octave_idx_type i, octave_idx_type id, double *dif1, + double *dif2, double *dif3, double *root, double *vect) +{ + assert (n0 == 0 || n0 == 1); + assert (n1 == 0 || n1 == 1); - octave_idx_type nt = n + n0 + n1; + octave_idx_type nt = n + n0 + n1; - assert (nt >= 1); + assert (nt >= 1); - assert (id == 1 || id == 2 || id == 3); + assert (id == 1 || id == 2 || id == 3); - if (id != 3) - assert (i >= 0 && i < nt); + if (id != 3) + assert (i >= 0 && i < nt); - // Evaluate discretization matrices and Gaussian quadrature weights. - // Quadrature weights are normalized to sum to one. + // Evaluate discretization matrices and Gaussian quadrature weights. + // Quadrature weights are normalized to sum to one. - if (id != 3) - { - for (octave_idx_type j = 0; j < nt; j++) - { - if (j == i) - { - if (id == 1) - vect[i] = dif2[i] / dif1[i] / 2.0; - else - vect[i] = dif3[i] / dif1[i] / 3.0; - } - else - { - double y = root[i] - root[j]; + if (id != 3) + { + for (octave_idx_type j = 0; j < nt; j++) + { + if (j == i) + { + if (id == 1) + vect[i] = dif2[i] / dif1[i] / 2.0; + else + vect[i] = dif3[i] / dif1[i] / 3.0; + } + else + { + double y = root[i] - root[j]; - vect[j] = dif1[i] / dif1[j] / y; + vect[j] = dif1[i] / dif1[j] / y; - if (id == 2) - vect[j] = vect[j] * (dif2[i] / dif1[i] - 2.0 / y); - } - } - } - else - { - double y = 0.0; + if (id == 2) + vect[j] = vect[j] * (dif2[i] / dif1[i] - 2.0 / y); + } + } + } + else + { + double y = 0.0; - for (octave_idx_type j = 0; j < nt; j++) - { - double x = root[j]; + for (octave_idx_type j = 0; j < nt; j++) + { + double x = root[j]; - double ax = x * (1.0 - x); + double ax = x * (1.0 - x); - if (n0 == 0) - ax = ax / x / x; + if (n0 == 0) + ax = ax / x / x; - if (n1 == 0) - ax = ax / (1.0 - x) / (1.0 - x); + if (n1 == 0) + ax = ax / (1.0 - x) / (1.0 - x); - vect[j] = ax / (dif1[j] * dif1[j]); + vect[j] = ax / (dif1[j] * dif1[j]); - y += vect[j]; - } + y += vect[j]; + } - for (octave_idx_type j = 0; j < nt; j++) - vect[j] = vect[j] / y; - } - } + for (octave_idx_type j = 0; j < nt; j++) + vect[j] = vect[j] / y; + } +} - // Error handling. +// Error handling. - void CollocWt::error (const char *msg) - { - (*current_liboctave_error_handler) ("CollocWt: fatal error '%s'", msg); - } +void CollocWt::error (const char *msg) +{ + (*current_liboctave_error_handler) ("CollocWt: fatal error '%s'", msg); +} - CollocWt& CollocWt::set_left (double val) - { - if (val >= m_rb) - error ("CollocWt: left bound greater than right bound"); +CollocWt& CollocWt::set_left (double val) +{ + if (val >= m_rb) + error ("CollocWt: left bound greater than right bound"); - m_lb = val; - m_initialized = 0; - return *this; - } + m_lb = val; + m_initialized = 0; + return *this; +} - CollocWt& CollocWt::set_right (double val) - { - if (val <= m_lb) - error ("CollocWt: right bound less than left bound"); +CollocWt& CollocWt::set_right (double val) +{ + if (val <= m_lb) + error ("CollocWt: right bound less than left bound"); - m_rb = val; - m_initialized = 0; - return *this; - } + m_rb = val; + m_initialized = 0; + return *this; +} - void CollocWt::init (void) - { - // Check for possible errors. +void CollocWt::init (void) +{ + // Check for possible errors. - double wid = m_rb - m_lb; - if (wid <= 0.0) - { - error ("CollocWt: width less than or equal to zero"); - } + double wid = m_rb - m_lb; + if (wid <= 0.0) + { + error ("CollocWt: width less than or equal to zero"); + } - octave_idx_type nt = m_n + m_inc_left + m_inc_right; + octave_idx_type nt = m_n + m_inc_left + m_inc_right; - if (nt < 0) - error ("CollocWt: total number of collocation points less than zero"); - else if (nt == 0) - return; + if (nt < 0) + error ("CollocWt: total number of collocation points less than zero"); + else if (nt == 0) + return; - Array dif1 (dim_vector (nt, 1)); - double *pdif1 = dif1.fortran_vec (); + Array dif1 (dim_vector (nt, 1)); + double *pdif1 = dif1.fortran_vec (); - Array dif2 (dim_vector (nt, 1)); - double *pdif2 = dif2.fortran_vec (); + Array dif2 (dim_vector (nt, 1)); + double *pdif2 = dif2.fortran_vec (); - Array dif3 (dim_vector (nt, 1)); - double *pdif3 = dif3.fortran_vec (); + Array dif3 (dim_vector (nt, 1)); + double *pdif3 = dif3.fortran_vec (); - Array vect (dim_vector (nt, 1)); - double *pvect = vect.fortran_vec (); + Array vect (dim_vector (nt, 1)); + double *pvect = vect.fortran_vec (); - m_r.resize (nt, 1); - m_q.resize (nt, 1); - m_A.resize (nt, nt); - m_B.resize (nt, nt); + m_r.resize (nt, 1); + m_q.resize (nt, 1); + m_A.resize (nt, nt); + m_B.resize (nt, nt); - double *pr = m_r.fortran_vec (); + double *pr = m_r.fortran_vec (); - // Compute roots. + // Compute roots. - if (! jcobi (m_n, m_inc_left, m_inc_right, m_alpha, m_beta, pdif1, - pdif2, pdif3, pr)) - error ("jcobi: newton iteration failed"); + if (! jcobi (m_n, m_inc_left, m_inc_right, m_alpha, m_beta, pdif1, + pdif2, pdif3, pr)) + error ("jcobi: newton iteration failed"); - octave_idx_type id; + octave_idx_type id; - // First derivative weights. + // First derivative weights. - id = 1; - for (octave_idx_type i = 0; i < nt; i++) - { - dfopr (m_n, m_inc_left, m_inc_right, i, id, pdif1, pdif2, pdif3, - pr, pvect); + id = 1; + for (octave_idx_type i = 0; i < nt; i++) + { + dfopr (m_n, m_inc_left, m_inc_right, i, id, pdif1, pdif2, pdif3, + pr, pvect); - for (octave_idx_type j = 0; j < nt; j++) - m_A(i, j) = vect(j); - } + for (octave_idx_type j = 0; j < nt; j++) + m_A(i, j) = vect(j); + } - // Second derivative weights. + // Second derivative weights. - id = 2; - for (octave_idx_type i = 0; i < nt; i++) - { - dfopr (m_n, m_inc_left, m_inc_right, i, id, pdif1, pdif2, pdif3, - pr, pvect); + id = 2; + for (octave_idx_type i = 0; i < nt; i++) + { + dfopr (m_n, m_inc_left, m_inc_right, i, id, pdif1, pdif2, pdif3, + pr, pvect); - for (octave_idx_type j = 0; j < nt; j++) - m_B(i, j) = vect(j); - } + for (octave_idx_type j = 0; j < nt; j++) + m_B(i, j) = vect(j); + } - // Gaussian quadrature weights. + // Gaussian quadrature weights. - id = 3; - double *pq = m_q.fortran_vec (); - dfopr (m_n, m_inc_left, m_inc_right, id, id, pdif1, pdif2, pdif3, pr, pq); + id = 3; + double *pq = m_q.fortran_vec (); + dfopr (m_n, m_inc_left, m_inc_right, id, id, pdif1, pdif2, pdif3, pr, pq); - m_initialized = 1; - } + m_initialized = 1; +} - std::ostream& operator << (std::ostream& os, const CollocWt& a) - { - if (a.left_included ()) - os << "left boundary is included\n"; - else - os << "left boundary is not included\n"; +std::ostream& operator << (std::ostream& os, const CollocWt& a) +{ + if (a.left_included ()) + os << "left boundary is included\n"; + else + os << "left boundary is not included\n"; - if (a.right_included ()) - os << "right boundary is included\n"; - else - os << "right boundary is not included\n"; + if (a.right_included ()) + os << "right boundary is included\n"; + else + os << "right boundary is not included\n"; - os << "\n"; + os << "\n"; - os << a.m_alpha << ' ' << a.m_beta << "\n\n" - << a.m_r << "\n\n" - << a.m_q << "\n\n" - << a.m_A << "\n" - << a.m_B << "\n"; + os << a.m_alpha << ' ' << a.m_beta << "\n\n" + << a.m_r << "\n\n" + << a.m_q << "\n\n" + << a.m_A << "\n" + << a.m_B << "\n"; - return os; - } + return os; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/CollocWt.h --- a/liboctave/numeric/CollocWt.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/CollocWt.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,177 +35,177 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class OCTAVE_API CollocWt - { - public: +class OCTAVE_API CollocWt +{ +public: - CollocWt (void) - : m_n (0), m_inc_left (0), m_inc_right (0), m_lb (0.0), m_rb (1.0), - m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (), - m_initialized (false) - { } + CollocWt (void) + : m_n (0), m_inc_left (0), m_inc_right (0), m_lb (0.0), m_rb (1.0), + m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (), + m_initialized (false) + { } - CollocWt (octave_idx_type nc, octave_idx_type il, octave_idx_type ir) - : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (0.0), m_rb (1.0), - m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (), - m_initialized (false) - { } + CollocWt (octave_idx_type nc, octave_idx_type il, octave_idx_type ir) + : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (0.0), m_rb (1.0), + m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (), + m_initialized (false) + { } - CollocWt (octave_idx_type nc, octave_idx_type il, octave_idx_type ir, - double l, double rr) - : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (l), m_rb (rr), - m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (), - m_initialized (false) - { } + CollocWt (octave_idx_type nc, octave_idx_type il, octave_idx_type ir, + double l, double rr) + : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (l), m_rb (rr), + m_alpha (0.0), m_beta (0.0), m_r (), m_q (), m_A (), m_B (), + m_initialized (false) + { } - CollocWt (octave_idx_type nc, double a, double b, octave_idx_type il, - octave_idx_type ir) - : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (0.0), m_rb (1.0), - m_alpha (a), m_beta (b), m_r (), m_q (), m_A (), m_B (), - m_initialized (false) - { } + CollocWt (octave_idx_type nc, double a, double b, octave_idx_type il, + octave_idx_type ir) + : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (0.0), m_rb (1.0), + m_alpha (a), m_beta (b), m_r (), m_q (), m_A (), m_B (), + m_initialized (false) + { } - CollocWt (octave_idx_type nc, double a, double b, octave_idx_type il, - octave_idx_type ir, - double ll, double rr) - : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (ll), m_rb (rr), - m_alpha (a), m_beta (b), m_r (), m_q (), m_A (), m_B (), - m_initialized (false) - { } + CollocWt (octave_idx_type nc, double a, double b, octave_idx_type il, + octave_idx_type ir, + double ll, double rr) + : m_n (nc), m_inc_left (il), m_inc_right (ir), m_lb (ll), m_rb (rr), + m_alpha (a), m_beta (b), m_r (), m_q (), m_A (), m_B (), + m_initialized (false) + { } - CollocWt (const CollocWt& a) = default; + CollocWt (const CollocWt& a) = default; - CollocWt& operator = (const CollocWt& a) = default; + CollocWt& operator = (const CollocWt& a) = default; - ~CollocWt (void) = default; + ~CollocWt (void) = default; - CollocWt& resize (octave_idx_type nc) - { - m_n = nc; - m_initialized = false; - return *this; - } + CollocWt& resize (octave_idx_type nc) + { + m_n = nc; + m_initialized = false; + return *this; + } - CollocWt& add_left (void) - { - m_inc_left = 1; - m_initialized = false; - return *this; - } + CollocWt& add_left (void) + { + m_inc_left = 1; + m_initialized = false; + return *this; + } - CollocWt& delete_left (void) - { - m_inc_left = 0; - m_initialized = false; - return *this; - } + CollocWt& delete_left (void) + { + m_inc_left = 0; + m_initialized = false; + return *this; + } - CollocWt& set_left (double val); + CollocWt& set_left (double val); - CollocWt& add_right (void) - { - m_inc_right = 1; - m_initialized = false; - return *this; - } + CollocWt& add_right (void) + { + m_inc_right = 1; + m_initialized = false; + return *this; + } - CollocWt& delete_right (void) - { - m_inc_right = 0; - m_initialized = false; - return *this; - } + CollocWt& delete_right (void) + { + m_inc_right = 0; + m_initialized = false; + return *this; + } - CollocWt& set_right (double val); + CollocWt& set_right (double val); - CollocWt& set_alpha (double val) - { - m_alpha = val; - m_initialized = false; - return *this; - } + CollocWt& set_alpha (double val) + { + m_alpha = val; + m_initialized = false; + return *this; + } - CollocWt& set_beta (double val) - { - m_beta = val; - m_initialized = false; - return *this; - } + CollocWt& set_beta (double val) + { + m_beta = val; + m_initialized = false; + return *this; + } - octave_idx_type ncol (void) const { return m_n; } + octave_idx_type ncol (void) const { return m_n; } - octave_idx_type left_included (void) const { return m_inc_left; } - octave_idx_type right_included (void) const { return m_inc_right; } + octave_idx_type left_included (void) const { return m_inc_left; } + octave_idx_type right_included (void) const { return m_inc_right; } - double left (void) const { return m_lb; } - double right (void) const { return m_rb; } + double left (void) const { return m_lb; } + double right (void) const { return m_rb; } - double width (void) const { return m_rb - m_lb; } + double width (void) const { return m_rb - m_lb; } - double alpha (void) const { return m_alpha; } - double beta (void) const { return m_beta; } + double alpha (void) const { return m_alpha; } + double beta (void) const { return m_beta; } - ColumnVector roots (void) - { - if (! m_initialized) - init (); + ColumnVector roots (void) + { + if (! m_initialized) + init (); - return m_r; - } + return m_r; + } - ColumnVector quad (void) - { - if (! m_initialized) - init (); + ColumnVector quad (void) + { + if (! m_initialized) + init (); - return m_q; - } + return m_q; + } - ColumnVector quad_weights (void) { return quad (); } + ColumnVector quad_weights (void) { return quad (); } - Matrix first (void) - { - if (! m_initialized) - init (); + Matrix first (void) + { + if (! m_initialized) + init (); - return m_A; - } + return m_A; + } - Matrix second (void) - { - if (! m_initialized) - init (); + Matrix second (void) + { + if (! m_initialized) + init (); - return m_B; - } + return m_B; + } - friend std::ostream& operator << (std::ostream&, const CollocWt&); + friend std::ostream& operator << (std::ostream&, const CollocWt&); - protected: +protected: - octave_idx_type m_n; + octave_idx_type m_n; - octave_idx_type m_inc_left; - octave_idx_type m_inc_right; + octave_idx_type m_inc_left; + octave_idx_type m_inc_right; - double m_lb; - double m_rb; + double m_lb; + double m_rb; - double m_alpha; - double m_beta; + double m_alpha; + double m_beta; - ColumnVector m_r; - ColumnVector m_q; + ColumnVector m_r; + ColumnVector m_q; - Matrix m_A; - Matrix m_B; + Matrix m_A; + Matrix m_B; - bool m_initialized; + bool m_initialized; - void init (void); + void init (void); - void error (const char *msg); - }; + void error (const char *msg); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/aepbalance.cc --- a/liboctave/numeric/aepbalance.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/aepbalance.cc Thu Dec 01 20:05:44 2022 -0800 @@ -39,234 +39,234 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static inline char - get_job (bool noperm, bool noscal) - { - return noperm ? (noscal ? 'N' : 'S') : (noscal ? 'P' : 'B'); - } +static inline char +get_job (bool noperm, bool noscal) +{ + return noperm ? (noscal ? 'N' : 'S') : (noscal ? 'P' : 'B'); +} OCTAVE_BEGIN_NAMESPACE(math) - template <> - OCTAVE_API - aepbalance::aepbalance (const Matrix& a, bool noperm, bool noscal) - : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), - m_job (get_job (noperm, noscal)) - { - F77_INT n = to_f77_int (a.cols ()); +template <> +OCTAVE_API +aepbalance::aepbalance (const Matrix& a, bool noperm, bool noscal) + : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), + m_job (get_job (noperm, noscal)) +{ + F77_INT n = to_f77_int (a.cols ()); - if (a.rows () != n) - (*current_liboctave_error_handler) - ("aepbalance: requires square matrix"); + if (a.rows () != n) + (*current_liboctave_error_handler) + ("aepbalance: requires square matrix"); - m_scale = ColumnVector (n); + m_scale = ColumnVector (n); - F77_INT info, t_ilo, t_ihi; + F77_INT info, t_ilo, t_ihi; - F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n, - m_balanced_mat.fortran_vec (), n, - t_ilo, t_ihi, m_scale.fortran_vec (), info - F77_CHAR_ARG_LEN (1))); + F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n, + m_balanced_mat.fortran_vec (), n, + t_ilo, t_ihi, m_scale.fortran_vec (), info + F77_CHAR_ARG_LEN (1))); - m_ilo = t_ilo; - m_ihi = t_ihi; - } + m_ilo = t_ilo; + m_ihi = t_ihi; +} - template <> - OCTAVE_API Matrix - aepbalance::balancing_matrix (void) const - { - F77_INT n = to_f77_int (m_balanced_mat.rows ()); +template <> +OCTAVE_API Matrix +aepbalance::balancing_matrix (void) const +{ + F77_INT n = to_f77_int (m_balanced_mat.rows ()); - Matrix balancing_mat (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - balancing_mat.elem (i, i) = 1.0; + Matrix balancing_mat (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + balancing_mat.elem (i, i) = 1.0; - F77_INT info; - F77_INT t_ilo = to_f77_int (m_ilo); - F77_INT t_ihi = to_f77_int (m_ihi); + F77_INT info; + F77_INT t_ilo = to_f77_int (m_ilo); + F77_INT t_ihi = to_f77_int (m_ihi); - char side = 'R'; + char side = 'R'; - F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, t_ilo, t_ihi, m_scale.data (), n, - balancing_mat.fortran_vec (), n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, t_ilo, t_ihi, m_scale.data (), n, + balancing_mat.fortran_vec (), n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - return balancing_mat; - } + return balancing_mat; +} - template <> - OCTAVE_API - aepbalance::aepbalance (const FloatMatrix& a, bool noperm, - bool noscal) - : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), - m_job (get_job (noperm, noscal)) - { - F77_INT n = to_f77_int (a.cols ()); +template <> +OCTAVE_API +aepbalance::aepbalance (const FloatMatrix& a, bool noperm, + bool noscal) + : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), + m_job (get_job (noperm, noscal)) +{ + F77_INT n = to_f77_int (a.cols ()); - if (a.rows () != n) - (*current_liboctave_error_handler) - ("aepbalance: requires square matrix"); + if (a.rows () != n) + (*current_liboctave_error_handler) + ("aepbalance: requires square matrix"); - m_scale = FloatColumnVector (n); + m_scale = FloatColumnVector (n); - F77_INT info, t_ilo, t_ihi; + F77_INT info, t_ilo, t_ihi; - F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n, - m_balanced_mat.fortran_vec (), n, t_ilo, - t_ihi, m_scale.fortran_vec (), info - F77_CHAR_ARG_LEN (1))); + F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n, + m_balanced_mat.fortran_vec (), n, t_ilo, + t_ihi, m_scale.fortran_vec (), info + F77_CHAR_ARG_LEN (1))); - m_ilo = t_ilo; - m_ihi = t_ihi; - } + m_ilo = t_ilo; + m_ihi = t_ihi; +} - template <> - OCTAVE_API FloatMatrix - aepbalance::balancing_matrix (void) const - { - F77_INT n = to_f77_int (m_balanced_mat.rows ()); +template <> +OCTAVE_API FloatMatrix +aepbalance::balancing_matrix (void) const +{ + F77_INT n = to_f77_int (m_balanced_mat.rows ()); - FloatMatrix balancing_mat (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - balancing_mat.elem (i, i) = 1.0; + FloatMatrix balancing_mat (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + balancing_mat.elem (i, i) = 1.0; - F77_INT info; - F77_INT t_ilo = to_f77_int (m_ilo); - F77_INT t_ihi = to_f77_int (m_ihi); + F77_INT info; + F77_INT t_ilo = to_f77_int (m_ilo); + F77_INT t_ihi = to_f77_int (m_ihi); - char side = 'R'; + char side = 'R'; - F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, t_ilo, t_ihi, m_scale.data (), n, - balancing_mat.fortran_vec (), n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, t_ilo, t_ihi, m_scale.data (), n, + balancing_mat.fortran_vec (), n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - return balancing_mat; - } + return balancing_mat; +} - template <> - OCTAVE_API - aepbalance::aepbalance (const ComplexMatrix& a, bool noperm, - bool noscal) - : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), - m_job (get_job (noperm, noscal)) - { - F77_INT n = to_f77_int (a.cols ()); +template <> +OCTAVE_API +aepbalance::aepbalance (const ComplexMatrix& a, bool noperm, + bool noscal) + : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), + m_job (get_job (noperm, noscal)) +{ + F77_INT n = to_f77_int (a.cols ()); - if (a.rows () != n) - (*current_liboctave_error_handler) - ("aepbalance: requires square matrix"); + if (a.rows () != n) + (*current_liboctave_error_handler) + ("aepbalance: requires square matrix"); - m_scale = ColumnVector (n); + m_scale = ColumnVector (n); - F77_INT info, t_ilo, t_ihi; + F77_INT info, t_ilo, t_ihi; - F77_XFCN (zgebal, ZGEBAL, - (F77_CONST_CHAR_ARG2 (&m_job, 1), n, - F77_DBLE_CMPLX_ARG (m_balanced_mat.fortran_vec ()), - n, t_ilo, t_ihi, m_scale.fortran_vec (), info - F77_CHAR_ARG_LEN (1))); + F77_XFCN (zgebal, ZGEBAL, + (F77_CONST_CHAR_ARG2 (&m_job, 1), n, + F77_DBLE_CMPLX_ARG (m_balanced_mat.fortran_vec ()), + n, t_ilo, t_ihi, m_scale.fortran_vec (), info + F77_CHAR_ARG_LEN (1))); - m_ilo = t_ilo; - m_ihi = t_ihi; - } + m_ilo = t_ilo; + m_ihi = t_ihi; +} - template <> - OCTAVE_API ComplexMatrix - aepbalance::balancing_matrix (void) const - { - F77_INT n = to_f77_int (m_balanced_mat.rows ()); +template <> +OCTAVE_API ComplexMatrix +aepbalance::balancing_matrix (void) const +{ + F77_INT n = to_f77_int (m_balanced_mat.rows ()); - ComplexMatrix balancing_mat (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - balancing_mat.elem (i, i) = 1.0; + ComplexMatrix balancing_mat (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + balancing_mat.elem (i, i) = 1.0; - F77_INT info; - F77_INT t_ilo = to_f77_int (m_ilo); - F77_INT t_ihi = to_f77_int (m_ihi); + F77_INT info; + F77_INT t_ilo = to_f77_int (m_ilo); + F77_INT t_ihi = to_f77_int (m_ihi); - char side = 'R'; + char side = 'R'; - F77_XFCN (zgebak, ZGEBAK, - (F77_CONST_CHAR_ARG2 (&m_job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, t_ilo, t_ihi, m_scale.data (), n, - F77_DBLE_CMPLX_ARG (balancing_mat.fortran_vec ()), - n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (zgebak, ZGEBAK, + (F77_CONST_CHAR_ARG2 (&m_job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, t_ilo, t_ihi, m_scale.data (), n, + F77_DBLE_CMPLX_ARG (balancing_mat.fortran_vec ()), + n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - return balancing_mat; - } + return balancing_mat; +} - template <> - OCTAVE_API - aepbalance::aepbalance (const FloatComplexMatrix& a, - bool noperm, bool noscal) - : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), - m_job (get_job (noperm, noscal)) - { - F77_INT n = to_f77_int (a.cols ()); +template <> +OCTAVE_API +aepbalance::aepbalance (const FloatComplexMatrix& a, + bool noperm, bool noscal) + : m_balanced_mat (a), m_scale (), m_ilo (), m_ihi (), + m_job (get_job (noperm, noscal)) +{ + F77_INT n = to_f77_int (a.cols ()); - if (a.rows () != n) - (*current_liboctave_error_handler) - ("aepbalance: requires square matrix"); + if (a.rows () != n) + (*current_liboctave_error_handler) + ("aepbalance: requires square matrix"); - m_scale = FloatColumnVector (n); + m_scale = FloatColumnVector (n); - F77_INT info, t_ilo, t_ihi; + F77_INT info, t_ilo, t_ihi; - F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n, - F77_CMPLX_ARG (m_balanced_mat.fortran_vec ()), - n, t_ilo, t_ihi, m_scale.fortran_vec (), info - F77_CHAR_ARG_LEN (1))); + F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n, + F77_CMPLX_ARG (m_balanced_mat.fortran_vec ()), + n, t_ilo, t_ihi, m_scale.fortran_vec (), info + F77_CHAR_ARG_LEN (1))); - m_ilo = t_ilo; - m_ihi = t_ihi; - } + m_ilo = t_ilo; + m_ihi = t_ihi; +} - template <> - OCTAVE_API FloatComplexMatrix - aepbalance::balancing_matrix (void) const - { - F77_INT n = to_f77_int (m_balanced_mat.rows ()); +template <> +OCTAVE_API FloatComplexMatrix +aepbalance::balancing_matrix (void) const +{ + F77_INT n = to_f77_int (m_balanced_mat.rows ()); - FloatComplexMatrix balancing_mat (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - balancing_mat.elem (i, i) = 1.0; + FloatComplexMatrix balancing_mat (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + balancing_mat.elem (i, i) = 1.0; - F77_INT info; - F77_INT t_ilo = to_f77_int (m_ilo); - F77_INT t_ihi = to_f77_int (m_ihi); + F77_INT info; + F77_INT t_ilo = to_f77_int (m_ilo); + F77_INT t_ihi = to_f77_int (m_ihi); - char side = 'R'; + char side = 'R'; - F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, t_ilo, t_ihi, m_scale.data (), n, - F77_CMPLX_ARG (balancing_mat.fortran_vec ()), - n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, t_ilo, t_ihi, m_scale.data (), n, + F77_CMPLX_ARG (balancing_mat.fortran_vec ()), + n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - return balancing_mat; - } + return balancing_mat; +} - // Instantiations we need. +// Instantiations we need. - template class aepbalance; +template class aepbalance; - template class aepbalance; +template class aepbalance; - template class aepbalance; +template class aepbalance; - template class aepbalance; +template class aepbalance; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/aepbalance.h --- a/liboctave/numeric/aepbalance.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/aepbalance.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,96 +34,96 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - aepbalance - { - public: +template +class +aepbalance +{ +public: - typedef typename MT::real_column_vector_type VT; + typedef typename MT::real_column_vector_type VT; + + aepbalance (void) : m_balanced_mat (), m_scale (), m_ilo (), m_ihi (), m_job () { } - aepbalance (void) : m_balanced_mat (), m_scale (), m_ilo (), m_ihi (), m_job () { } - - OCTAVE_API aepbalance (const MT& a, bool noperm = false, bool noscal = false); + OCTAVE_API aepbalance (const MT& a, bool noperm = false, bool noscal = false); - aepbalance (const aepbalance& a) - : m_balanced_mat (a.m_balanced_mat), m_scale (a.m_scale), - m_ilo(a.m_ilo), m_ihi(a.m_ihi), m_job(a.m_job) - { } + aepbalance (const aepbalance& a) + : m_balanced_mat (a.m_balanced_mat), m_scale (a.m_scale), + m_ilo(a.m_ilo), m_ihi(a.m_ihi), m_job(a.m_job) + { } - aepbalance& operator = (const aepbalance& a) + aepbalance& operator = (const aepbalance& a) + { + if (this != &a) { - if (this != &a) - { - m_balanced_mat = a.m_balanced_mat; - m_scale = a.m_scale; - m_ilo = a.m_ilo; - m_ihi = a.m_ihi; - m_job = a.m_job; - } - - return *this; - } - - virtual ~aepbalance (void) = default; - - OCTAVE_API MT balancing_matrix (void) const; - - MT balanced_matrix (void) const - { - return m_balanced_mat; + m_balanced_mat = a.m_balanced_mat; + m_scale = a.m_scale; + m_ilo = a.m_ilo; + m_ihi = a.m_ihi; + m_job = a.m_job; } - VT permuting_vector (void) const - { - octave_idx_type n = m_balanced_mat.rows (); + return *this; + } + + virtual ~aepbalance (void) = default; - VT pv (n); + OCTAVE_API MT balancing_matrix (void) const; - for (octave_idx_type i = 0; i < n; i++) - pv(i) = i+1; + MT balanced_matrix (void) const + { + return m_balanced_mat; + } - for (octave_idx_type i = n-1; i >= m_ihi; i--) - { - octave_idx_type j = m_scale(i) - 1; - std::swap (pv(i), pv(j)); - } + VT permuting_vector (void) const + { + octave_idx_type n = m_balanced_mat.rows (); + + VT pv (n); - for (octave_idx_type i = 0; i < m_ilo-1; i++) - { - octave_idx_type j = m_scale(i) - 1; - std::swap (pv(i), pv(j)); - } + for (octave_idx_type i = 0; i < n; i++) + pv(i) = i+1; - return pv; + for (octave_idx_type i = n-1; i >= m_ihi; i--) + { + octave_idx_type j = m_scale(i) - 1; + std::swap (pv(i), pv(j)); } - VT scaling_vector (void) const + for (octave_idx_type i = 0; i < m_ilo-1; i++) { - octave_idx_type n = m_balanced_mat.rows (); - - VT scv (n); - - for (octave_idx_type i = 0; i < m_ilo-1; i++) - scv(i) = 1; - - for (octave_idx_type i = m_ilo-1; i < m_ihi; i++) - scv(i) = m_scale(i); - - for (octave_idx_type i = m_ihi; i < n; i++) - scv(i) = 1; - - return scv; + octave_idx_type j = m_scale(i) - 1; + std::swap (pv(i), pv(j)); } - protected: + return pv; + } + + VT scaling_vector (void) const + { + octave_idx_type n = m_balanced_mat.rows (); + + VT scv (n); + + for (octave_idx_type i = 0; i < m_ilo-1; i++) + scv(i) = 1; + + for (octave_idx_type i = m_ilo-1; i < m_ihi; i++) + scv(i) = m_scale(i); - MT m_balanced_mat; - VT m_scale; - octave_idx_type m_ilo; - octave_idx_type m_ihi; - char m_job; - }; + for (octave_idx_type i = m_ihi; i < n; i++) + scv(i) = 1; + + return scv; + } + +protected: + + MT m_balanced_mat; + VT m_scale; + octave_idx_type m_ilo; + octave_idx_type m_ihi; + char m_job; +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/chol.cc --- a/liboctave/numeric/chol.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/chol.cc Thu Dec 01 20:05:44 2022 -0800 @@ -49,1111 +49,1111 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static Matrix - chol2inv_internal (const Matrix& r, bool is_upper = true) - { - Matrix retval; +static Matrix +chol2inv_internal (const Matrix& r, bool is_upper = true) +{ + Matrix retval; - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); + octave_idx_type r_nr = r.rows (); + octave_idx_type r_nc = r.cols (); - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("chol2inv requires square matrix"); + if (r_nr != r_nc) + (*current_liboctave_error_handler) ("chol2inv requires square matrix"); - F77_INT n = to_f77_int (r_nc); - F77_INT info; + F77_INT n = to_f77_int (r_nc); + F77_INT info; - Matrix tmp = r; - double *v = tmp.fortran_vec (); + Matrix tmp = r; + double *v = tmp.fortran_vec (); - if (is_upper) - F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, - v, n, info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, - v, n, info - F77_CHAR_ARG_LEN (1))); + if (is_upper) + F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, + v, n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, + v, n, info + F77_CHAR_ARG_LEN (1))); - // FIXME: Should we check info exit value and possibly report an error? + // FIXME: Should we check info exit value and possibly report an error? - // If someone thinks of a more graceful way of doing this - // (or faster for that matter :-)), please let me know! + // If someone thinks of a more graceful way of doing this + // (or faster for that matter :-)), please let me know! - if (n > 1) - { - if (is_upper) - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (i, j) = tmp.xelem (j, i); - else - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (j, i) = tmp.xelem (i, j); - } + if (n > 1) + { + if (is_upper) + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (i, j) = tmp.xelem (j, i); + else + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (j, i) = tmp.xelem (i, j); + } - retval = tmp; + retval = tmp; - return retval; - } + return retval; +} - static FloatMatrix - chol2inv_internal (const FloatMatrix& r, bool is_upper = true) - { - FloatMatrix retval; +static FloatMatrix +chol2inv_internal (const FloatMatrix& r, bool is_upper = true) +{ + FloatMatrix retval; - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); + octave_idx_type r_nr = r.rows (); + octave_idx_type r_nc = r.cols (); - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("chol2inv requires square matrix"); + if (r_nr != r_nc) + (*current_liboctave_error_handler) ("chol2inv requires square matrix"); - F77_INT n = to_f77_int (r_nc); - F77_INT info; + F77_INT n = to_f77_int (r_nc); + F77_INT info; - FloatMatrix tmp = r; - float *v = tmp.fortran_vec (); + FloatMatrix tmp = r; + float *v = tmp.fortran_vec (); - if (is_upper) - F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, - v, n, info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, - v, n, info - F77_CHAR_ARG_LEN (1))); + if (is_upper) + F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, + v, n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, + v, n, info + F77_CHAR_ARG_LEN (1))); - // FIXME: Should we check info exit value and possibly report an error? + // FIXME: Should we check info exit value and possibly report an error? - // If someone thinks of a more graceful way of doing this (or - // faster for that matter :-)), please let me know! + // If someone thinks of a more graceful way of doing this (or + // faster for that matter :-)), please let me know! - if (n > 1) - { - if (is_upper) - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (i, j) = tmp.xelem (j, i); - else - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (j, i) = tmp.xelem (i, j); - } + if (n > 1) + { + if (is_upper) + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (i, j) = tmp.xelem (j, i); + else + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (j, i) = tmp.xelem (i, j); + } - retval = tmp; + retval = tmp; - return retval; - } + return retval; +} - static ComplexMatrix - chol2inv_internal (const ComplexMatrix& r, bool is_upper = true) - { - ComplexMatrix retval; +static ComplexMatrix +chol2inv_internal (const ComplexMatrix& r, bool is_upper = true) +{ + ComplexMatrix retval; - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); + octave_idx_type r_nr = r.rows (); + octave_idx_type r_nc = r.cols (); - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("chol2inv requires square matrix"); + if (r_nr != r_nc) + (*current_liboctave_error_handler) ("chol2inv requires square matrix"); - F77_INT n = to_f77_int (r_nc); - F77_INT info; + F77_INT n = to_f77_int (r_nc); + F77_INT info; - ComplexMatrix tmp = r; + ComplexMatrix tmp = r; - if (is_upper) - F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, - F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, - F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info - F77_CHAR_ARG_LEN (1))); + if (is_upper) + F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, + F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, + F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info + F77_CHAR_ARG_LEN (1))); - // If someone thinks of a more graceful way of doing this (or - // faster for that matter :-)), please let me know! + // If someone thinks of a more graceful way of doing this (or + // faster for that matter :-)), please let me know! - if (n > 1) - { - if (is_upper) - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (i, j) = std::conj (tmp.xelem (j, i)); - else - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (j, i) = std::conj (tmp.xelem (i, j)); - } + if (n > 1) + { + if (is_upper) + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (i, j) = std::conj (tmp.xelem (j, i)); + else + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (j, i) = std::conj (tmp.xelem (i, j)); + } - retval = tmp; + retval = tmp; - return retval; - } + return retval; +} - static FloatComplexMatrix - chol2inv_internal (const FloatComplexMatrix& r, bool is_upper = true) - { - FloatComplexMatrix retval; +static FloatComplexMatrix +chol2inv_internal (const FloatComplexMatrix& r, bool is_upper = true) +{ + FloatComplexMatrix retval; - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); + octave_idx_type r_nr = r.rows (); + octave_idx_type r_nc = r.cols (); - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("chol2inv requires square matrix"); + if (r_nr != r_nc) + (*current_liboctave_error_handler) ("chol2inv requires square matrix"); - F77_INT n = to_f77_int (r_nc); - F77_INT info; + F77_INT n = to_f77_int (r_nc); + F77_INT info; - FloatComplexMatrix tmp = r; + FloatComplexMatrix tmp = r; - if (is_upper) - F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, - F77_CMPLX_ARG (tmp.fortran_vec ()), n, info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, - F77_CMPLX_ARG (tmp.fortran_vec ()), n, info - F77_CHAR_ARG_LEN (1))); + if (is_upper) + F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n, + F77_CMPLX_ARG (tmp.fortran_vec ()), n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n, + F77_CMPLX_ARG (tmp.fortran_vec ()), n, info + F77_CHAR_ARG_LEN (1))); - // If someone thinks of a more graceful way of doing this (or - // faster for that matter :-)), please let me know! + // If someone thinks of a more graceful way of doing this (or + // faster for that matter :-)), please let me know! - if (n > 1) - { - if (is_upper) - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (i, j) = std::conj (tmp.xelem (j, i)); - else - for (octave_idx_type j = 0; j < r_nc; j++) - for (octave_idx_type i = j+1; i < r_nr; i++) - tmp.xelem (j, i) = std::conj (tmp.xelem (i, j)); - } + if (n > 1) + { + if (is_upper) + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (i, j) = std::conj (tmp.xelem (j, i)); + else + for (octave_idx_type j = 0; j < r_nc; j++) + for (octave_idx_type i = j+1; i < r_nr; i++) + tmp.xelem (j, i) = std::conj (tmp.xelem (i, j)); + } - retval = tmp; + retval = tmp; - return retval; - } + return retval; +} OCTAVE_BEGIN_NAMESPACE(math) - template - T - chol2inv (const T& r) - { - return chol2inv_internal (r); - } +template +T +chol2inv (const T& r) +{ + return chol2inv_internal (r); +} - // Compute the inverse of a matrix using the Cholesky factorization. - template - T - chol::inverse (void) const - { - return chol2inv_internal (m_chol_mat, m_is_upper); - } +// Compute the inverse of a matrix using the Cholesky factorization. +template +T +chol::inverse (void) const +{ + return chol2inv_internal (m_chol_mat, m_is_upper); +} - template - void - chol::set (const T& R) - { - if (! R.issquare ()) - (*current_liboctave_error_handler) ("chol: requires square matrix"); +template +void +chol::set (const T& R) +{ + if (! R.issquare ()) + (*current_liboctave_error_handler) ("chol: requires square matrix"); - m_chol_mat = R; - } + m_chol_mat = R; +} #if ! defined (HAVE_QRUPDATE) - template - void - chol::update (const VT& u) - { - warn_qrupdate_once (); +template +void +chol::update (const VT& u) +{ + warn_qrupdate_once (); - octave_idx_type n = m_chol_mat.rows (); + octave_idx_type n = m_chol_mat.rows (); + + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + + init (m_chol_mat.hermitian () * m_chol_mat + T (u) * T (u).hermitian (), + true, false); +} - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); +template +bool +singular (const T& a) +{ + static typename T::element_type zero (0); + for (octave_idx_type i = 0; i < a.rows (); i++) + if (a(i, i) == zero) return true; + return false; +} - init (m_chol_mat.hermitian () * m_chol_mat + T (u) * T (u).hermitian (), - true, false); - } +template +octave_idx_type +chol::downdate (const VT& u) +{ + warn_qrupdate_once (); + + octave_idx_type info = -1; - template - bool - singular (const T& a) + octave_idx_type n = m_chol_mat.rows (); + + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + + if (singular (m_chol_mat)) + info = 2; + else { - static typename T::element_type zero (0); - for (octave_idx_type i = 0; i < a.rows (); i++) - if (a(i, i) == zero) return true; - return false; - } - - template - octave_idx_type - chol::downdate (const VT& u) - { - warn_qrupdate_once (); - - octave_idx_type info = -1; - - octave_idx_type n = m_chol_mat.rows (); - - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - - if (singular (m_chol_mat)) - info = 2; - else - { - info = init (m_chol_mat.hermitian () * m_chol_mat - - T (u) * T (u).hermitian (), true, false); - if (info) info = 1; - } - - return info; + info = init (m_chol_mat.hermitian () * m_chol_mat + - T (u) * T (u).hermitian (), true, false); + if (info) info = 1; } - template - octave_idx_type - chol::insert_sym (const VT& u, octave_idx_type j) - { - static typename T::element_type zero (0); + return info; +} - warn_qrupdate_once (); +template +octave_idx_type +chol::insert_sym (const VT& u, octave_idx_type j) +{ + static typename T::element_type zero (0); - octave_idx_type info = -1; + warn_qrupdate_once (); - octave_idx_type n = m_chol_mat.rows (); + octave_idx_type info = -1; - if (u.numel () != n + 1) - (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("cholinsert: index out of range"); + octave_idx_type n = m_chol_mat.rows (); + + if (u.numel () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("cholinsert: index out of range"); - if (singular (m_chol_mat)) - info = 2; - else if (std::imag (u(j)) != zero) - info = 3; - else - { - T a = m_chol_mat.hermitian () * m_chol_mat; - T a1 (n+1, n+1); - for (octave_idx_type k = 0; k < n+1; k++) - for (octave_idx_type l = 0; l < n+1; l++) - { - if (l == j) - a1(k, l) = u(k); - else if (k == j) - a1(k, l) = math::conj (u(l)); - else - a1(k, l) = a(k < j ? k : k-1, l < j ? l : l-1); - } - info = init (a1, true, false); - if (info) info = 1; - } - - return info; + if (singular (m_chol_mat)) + info = 2; + else if (std::imag (u(j)) != zero) + info = 3; + else + { + T a = m_chol_mat.hermitian () * m_chol_mat; + T a1 (n+1, n+1); + for (octave_idx_type k = 0; k < n+1; k++) + for (octave_idx_type l = 0; l < n+1; l++) + { + if (l == j) + a1(k, l) = u(k); + else if (k == j) + a1(k, l) = math::conj (u(l)); + else + a1(k, l) = a(k < j ? k : k-1, l < j ? l : l-1); + } + info = init (a1, true, false); + if (info) info = 1; } - template - void - chol::delete_sym (octave_idx_type j) - { - warn_qrupdate_once (); + return info; +} + +template +void +chol::delete_sym (octave_idx_type j) +{ + warn_qrupdate_once (); - octave_idx_type n = m_chol_mat.rows (); + octave_idx_type n = m_chol_mat.rows (); + + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("choldelete: index out of range"); + + T a = m_chol_mat.hermitian () * m_chol_mat; + a.delete_elements (1, idx_vector (j)); + a.delete_elements (0, idx_vector (j)); + init (a, true, false); +} - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("choldelete: index out of range"); +template +void +chol::shift_sym (octave_idx_type i, octave_idx_type j) +{ + warn_qrupdate_once (); + + octave_idx_type n = m_chol_mat.rows (); + + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("cholshift: index out of range"); - T a = m_chol_mat.hermitian () * m_chol_mat; - a.delete_elements (1, idx_vector (j)); - a.delete_elements (0, idx_vector (j)); - init (a, true, false); + T a = m_chol_mat.hermitian () * m_chol_mat; + Array p (dim_vector (n, 1)); + for (octave_idx_type k = 0; k < n; k++) p(k) = k; + if (i < j) + { + for (octave_idx_type k = i; k < j; k++) p(k) = k+1; + p(j) = i; + } + else if (j < i) + { + p(j) = i; + for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1; } - template - void - chol::shift_sym (octave_idx_type i, octave_idx_type j) - { - warn_qrupdate_once (); - - octave_idx_type n = m_chol_mat.rows (); - - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("cholshift: index out of range"); - - T a = m_chol_mat.hermitian () * m_chol_mat; - Array p (dim_vector (n, 1)); - for (octave_idx_type k = 0; k < n; k++) p(k) = k; - if (i < j) - { - for (octave_idx_type k = i; k < j; k++) p(k) = k+1; - p(j) = i; - } - else if (j < i) - { - p(j) = i; - for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1; - } - - init (a.index (idx_vector (p), idx_vector (p)), true, false); - } + init (a.index (idx_vector (p), idx_vector (p)), true, false); +} #endif - // Specializations. +// Specializations. - template <> - OCTAVE_API octave_idx_type - chol::init (const Matrix& a, bool upper, bool calc_cond) - { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); +template <> +OCTAVE_API octave_idx_type +chol::init (const Matrix& a, bool upper, bool calc_cond) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("chol: requires square matrix"); + + F77_INT n = to_f77_int (a_nc); + F77_INT info; + + m_is_upper = upper; - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("chol: requires square matrix"); + m_chol_mat.clear (n, n); + if (m_is_upper) + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i <= j; i++) + m_chol_mat.xelem (i, j) = a(i, j); + for (octave_idx_type i = j+1; i < n; i++) + m_chol_mat.xelem (i, j) = 0.0; + } + else + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i < j; i++) + m_chol_mat.xelem (i, j) = 0.0; + for (octave_idx_type i = j; i < n; i++) + m_chol_mat.xelem (i, j) = a(i, j); + } + double *h = m_chol_mat.fortran_vec (); - F77_INT n = to_f77_int (a_nc); - F77_INT info; + // Calculate the norm of the matrix, for later use. + double anorm = 0; + if (calc_cond) + anorm = octave::xnorm (a, 1); + + if (m_is_upper) + F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, n, info + F77_CHAR_ARG_LEN (1))); - m_is_upper = upper; + m_rcond = 0.0; + if (info > 0) + m_chol_mat.resize (info - 1, info - 1); + else if (calc_cond) + { + F77_INT dpocon_info = 0; - m_chol_mat.clear (n, n); + // Now calculate the condition number for non-singular matrix. + Array z (dim_vector (3*n, 1)); + double *pz = z.fortran_vec (); + OCTAVE_LOCAL_BUFFER (F77_INT, iz, n); if (m_is_upper) - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i <= j; i++) - m_chol_mat.xelem (i, j) = a(i, j); - for (octave_idx_type i = j+1; i < n; i++) - m_chol_mat.xelem (i, j) = 0.0; - } - else - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i < j; i++) - m_chol_mat.xelem (i, j) = 0.0; - for (octave_idx_type i = j; i < n; i++) - m_chol_mat.xelem (i, j) = a(i, j); - } - double *h = m_chol_mat.fortran_vec (); - - // Calculate the norm of the matrix, for later use. - double anorm = 0; - if (calc_cond) - anorm = octave::xnorm (a, 1); - - if (m_is_upper) - F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info + F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, + n, anorm, m_rcond, pz, iz, dpocon_info F77_CHAR_ARG_LEN (1))); else - F77_XFCN (dpotrf, DPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, n, info + F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, + n, anorm, m_rcond, pz, iz, dpocon_info F77_CHAR_ARG_LEN (1))); - m_rcond = 0.0; - if (info > 0) - m_chol_mat.resize (info - 1, info - 1); - else if (calc_cond) - { - F77_INT dpocon_info = 0; + if (dpocon_info != 0) + info = -1; + } - // Now calculate the condition number for non-singular matrix. - Array z (dim_vector (3*n, 1)); - double *pz = z.fortran_vec (); - OCTAVE_LOCAL_BUFFER (F77_INT, iz, n); - if (m_is_upper) - F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, - n, anorm, m_rcond, pz, iz, dpocon_info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, - n, anorm, m_rcond, pz, iz, dpocon_info - F77_CHAR_ARG_LEN (1))); - - if (dpocon_info != 0) - info = -1; - } - - return info; - } + return info; +} #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - chol::update (const ColumnVector& u) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); +template <> +OCTAVE_API void +chol::update (const ColumnVector& u) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - ColumnVector utmp = u; + ColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, n); + OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dch1up, DCH1UP, (n, m_chol_mat.fortran_vec (), n, - utmp.fortran_vec (), w)); - } + F77_XFCN (dch1up, DCH1UP, (n, m_chol_mat.fortran_vec (), n, + utmp.fortran_vec (), w)); +} - template <> - OCTAVE_API octave_idx_type - chol::downdate (const ColumnVector& u) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::downdate (const ColumnVector& u) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - ColumnVector utmp = u; + ColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, n); + OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dch1dn, DCH1DN, (n, m_chol_mat.fortran_vec (), n, - utmp.fortran_vec (), w, info)); + F77_XFCN (dch1dn, DCH1DN, (n, m_chol_mat.fortran_vec (), n, + utmp.fortran_vec (), w, info)); - return info; - } + return info; +} - template <> - OCTAVE_API octave_idx_type - chol::insert_sym (const ColumnVector& u, octave_idx_type j_arg) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::insert_sym (const ColumnVector& u, octave_idx_type j_arg) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (u.numel () != n + 1) - (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("cholinsert: index out of range"); + if (u.numel () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("cholinsert: index out of range"); - ColumnVector utmp = u; + ColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, n); + OCTAVE_LOCAL_BUFFER (double, w, n); - m_chol_mat.resize (n+1, n+1); - F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); + m_chol_mat.resize (n+1, n+1); + F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); - F77_XFCN (dchinx, DCHINX, (n, m_chol_mat.fortran_vec (), ldcm, - j + 1, utmp.fortran_vec (), w, info)); + F77_XFCN (dchinx, DCHINX, (n, m_chol_mat.fortran_vec (), ldcm, + j + 1, utmp.fortran_vec (), w, info)); - return info; - } + return info; +} - template <> - OCTAVE_API void - chol::delete_sym (octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::delete_sym (octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("choldelete: index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("choldelete: index out of range"); - OCTAVE_LOCAL_BUFFER (double, w, n); + OCTAVE_LOCAL_BUFFER (double, w, n); - F77_XFCN (dchdex, DCHDEX, (n, m_chol_mat.fortran_vec (), n, j + 1, w)); + F77_XFCN (dchdex, DCHDEX, (n, m_chol_mat.fortran_vec (), n, j + 1, w)); - m_chol_mat.resize (n-1, n-1); - } + m_chol_mat.resize (n-1, n-1); +} - template <> - OCTAVE_API void - chol::shift_sym (octave_idx_type i_arg, octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::shift_sym (octave_idx_type i_arg, octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("cholshift: index out of range"); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("cholshift: index out of range"); - OCTAVE_LOCAL_BUFFER (double, w, 2*n); + OCTAVE_LOCAL_BUFFER (double, w, 2*n); - F77_XFCN (dchshx, DCHSHX, (n, m_chol_mat.fortran_vec (), n, - i + 1, j + 1, w)); - } + F77_XFCN (dchshx, DCHSHX, (n, m_chol_mat.fortran_vec (), n, + i + 1, j + 1, w)); +} #endif - template <> - OCTAVE_API octave_idx_type - chol::init (const FloatMatrix& a, bool upper, bool calc_cond) - { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); +template <> +OCTAVE_API octave_idx_type +chol::init (const FloatMatrix& a, bool upper, bool calc_cond) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("chol: requires square matrix"); + + F77_INT n = to_f77_int (a_nc); + F77_INT info; + + m_is_upper = upper; - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("chol: requires square matrix"); + m_chol_mat.clear (n, n); + if (m_is_upper) + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i <= j; i++) + m_chol_mat.xelem (i, j) = a(i, j); + for (octave_idx_type i = j+1; i < n; i++) + m_chol_mat.xelem (i, j) = 0.0f; + } + else + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i < j; i++) + m_chol_mat.xelem (i, j) = 0.0f; + for (octave_idx_type i = j; i < n; i++) + m_chol_mat.xelem (i, j) = a(i, j); + } + float *h = m_chol_mat.fortran_vec (); - F77_INT n = to_f77_int (a_nc); - F77_INT info; + // Calculate the norm of the matrix, for later use. + float anorm = 0; + if (calc_cond) + anorm = octave::xnorm (a, 1); + + if (m_is_upper) + F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, n, info + F77_CHAR_ARG_LEN (1))); - m_is_upper = upper; + m_rcond = 0.0; + if (info > 0) + m_chol_mat.resize (info - 1, info - 1); + else if (calc_cond) + { + F77_INT spocon_info = 0; - m_chol_mat.clear (n, n); + // Now calculate the condition number for non-singular matrix. + Array z (dim_vector (3*n, 1)); + float *pz = z.fortran_vec (); + OCTAVE_LOCAL_BUFFER (F77_INT, iz, n); if (m_is_upper) - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i <= j; i++) - m_chol_mat.xelem (i, j) = a(i, j); - for (octave_idx_type i = j+1; i < n; i++) - m_chol_mat.xelem (i, j) = 0.0f; - } - else - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i < j; i++) - m_chol_mat.xelem (i, j) = 0.0f; - for (octave_idx_type i = j; i < n; i++) - m_chol_mat.xelem (i, j) = a(i, j); - } - float *h = m_chol_mat.fortran_vec (); - - // Calculate the norm of the matrix, for later use. - float anorm = 0; - if (calc_cond) - anorm = octave::xnorm (a, 1); - - if (m_is_upper) - F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, n, info + F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, + n, anorm, m_rcond, pz, iz, spocon_info F77_CHAR_ARG_LEN (1))); else - F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, n, info + F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, + n, anorm, m_rcond, pz, iz, spocon_info F77_CHAR_ARG_LEN (1))); - m_rcond = 0.0; - if (info > 0) - m_chol_mat.resize (info - 1, info - 1); - else if (calc_cond) - { - F77_INT spocon_info = 0; + if (spocon_info != 0) + info = -1; + } - // Now calculate the condition number for non-singular matrix. - Array z (dim_vector (3*n, 1)); - float *pz = z.fortran_vec (); - OCTAVE_LOCAL_BUFFER (F77_INT, iz, n); - if (m_is_upper) - F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h, - n, anorm, m_rcond, pz, iz, spocon_info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 ("L", 1), n, h, - n, anorm, m_rcond, pz, iz, spocon_info - F77_CHAR_ARG_LEN (1))); - - if (spocon_info != 0) - info = -1; - } - - return info; - } + return info; +} #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - chol::update (const FloatColumnVector& u) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); +template <> +OCTAVE_API void +chol::update (const FloatColumnVector& u) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - FloatColumnVector utmp = u; + FloatColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, n); + OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (sch1up, SCH1UP, (n, m_chol_mat.fortran_vec (), n, - utmp.fortran_vec (), w)); - } + F77_XFCN (sch1up, SCH1UP, (n, m_chol_mat.fortran_vec (), n, + utmp.fortran_vec (), w)); +} - template <> - OCTAVE_API octave_idx_type - chol::downdate (const FloatColumnVector& u) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::downdate (const FloatColumnVector& u) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - FloatColumnVector utmp = u; + FloatColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, n); + OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (sch1dn, SCH1DN, (n, m_chol_mat.fortran_vec (), n, - utmp.fortran_vec (), w, info)); + F77_XFCN (sch1dn, SCH1DN, (n, m_chol_mat.fortran_vec (), n, + utmp.fortran_vec (), w, info)); - return info; - } + return info; +} - template <> - OCTAVE_API octave_idx_type - chol::insert_sym (const FloatColumnVector& u, - octave_idx_type j_arg) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::insert_sym (const FloatColumnVector& u, + octave_idx_type j_arg) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (u.numel () != n + 1) - (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("cholinsert: index out of range"); + if (u.numel () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("cholinsert: index out of range"); - FloatColumnVector utmp = u; + FloatColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, n); + OCTAVE_LOCAL_BUFFER (float, w, n); - m_chol_mat.resize (n+1, n+1); - F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); + m_chol_mat.resize (n+1, n+1); + F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); - F77_XFCN (schinx, SCHINX, (n, m_chol_mat.fortran_vec (), ldcm, - j + 1, utmp.fortran_vec (), w, info)); + F77_XFCN (schinx, SCHINX, (n, m_chol_mat.fortran_vec (), ldcm, + j + 1, utmp.fortran_vec (), w, info)); - return info; - } + return info; +} - template <> - OCTAVE_API void - chol::delete_sym (octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::delete_sym (octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("choldelete: index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("choldelete: index out of range"); - OCTAVE_LOCAL_BUFFER (float, w, n); + OCTAVE_LOCAL_BUFFER (float, w, n); - F77_XFCN (schdex, SCHDEX, (n, m_chol_mat.fortran_vec (), n, - j + 1, w)); + F77_XFCN (schdex, SCHDEX, (n, m_chol_mat.fortran_vec (), n, + j + 1, w)); - m_chol_mat.resize (n-1, n-1); - } + m_chol_mat.resize (n-1, n-1); +} - template <> - OCTAVE_API void - chol::shift_sym (octave_idx_type i_arg, octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::shift_sym (octave_idx_type i_arg, octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("cholshift: index out of range"); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("cholshift: index out of range"); - OCTAVE_LOCAL_BUFFER (float, w, 2*n); + OCTAVE_LOCAL_BUFFER (float, w, 2*n); - F77_XFCN (schshx, SCHSHX, (n, m_chol_mat.fortran_vec (), n, - i + 1, j + 1, w)); - } + F77_XFCN (schshx, SCHSHX, (n, m_chol_mat.fortran_vec (), n, + i + 1, j + 1, w)); +} #endif - template <> - OCTAVE_API octave_idx_type - chol::init (const ComplexMatrix& a, bool upper, bool calc_cond) - { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); +template <> +OCTAVE_API octave_idx_type +chol::init (const ComplexMatrix& a, bool upper, bool calc_cond) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("chol: requires square matrix"); + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("chol: requires square matrix"); - F77_INT n = to_f77_int (a_nc); - F77_INT info; + F77_INT n = to_f77_int (a_nc); + F77_INT info; - m_is_upper = upper; + m_is_upper = upper; - m_chol_mat.clear (n, n); - if (m_is_upper) - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i <= j; i++) - m_chol_mat.xelem (i, j) = a(i, j); - for (octave_idx_type i = j+1; i < n; i++) - m_chol_mat.xelem (i, j) = 0.0; - } - else - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i < j; i++) - m_chol_mat.xelem (i, j) = 0.0; - for (octave_idx_type i = j; i < n; i++) - m_chol_mat.xelem (i, j) = a(i, j); - } - Complex *h = m_chol_mat.fortran_vec (); + m_chol_mat.clear (n, n); + if (m_is_upper) + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i <= j; i++) + m_chol_mat.xelem (i, j) = a(i, j); + for (octave_idx_type i = j+1; i < n; i++) + m_chol_mat.xelem (i, j) = 0.0; + } + else + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i < j; i++) + m_chol_mat.xelem (i, j) = 0.0; + for (octave_idx_type i = j; i < n; i++) + m_chol_mat.xelem (i, j) = a(i, j); + } + Complex *h = m_chol_mat.fortran_vec (); - // Calculate the norm of the matrix, for later use. - double anorm = 0; - if (calc_cond) - anorm = octave::xnorm (a, 1); + // Calculate the norm of the matrix, for later use. + double anorm = 0; + if (calc_cond) + anorm = octave::xnorm (a, 1); - if (m_is_upper) - F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, - F77_DBLE_CMPLX_ARG (h), n, info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, - F77_DBLE_CMPLX_ARG (h), n, info - F77_CHAR_ARG_LEN (1))); + if (m_is_upper) + F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), n, + F77_DBLE_CMPLX_ARG (h), n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (zpotrf, ZPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), n, + F77_DBLE_CMPLX_ARG (h), n, info + F77_CHAR_ARG_LEN (1))); - m_rcond = 0.0; - if (info > 0) - m_chol_mat.resize (info - 1, info - 1); - else if (calc_cond) - { - F77_INT zpocon_info = 0; + m_rcond = 0.0; + if (info > 0) + m_chol_mat.resize (info - 1, info - 1); + else if (calc_cond) + { + F77_INT zpocon_info = 0; - // Now calculate the condition number for non-singular matrix. - Array z (dim_vector (2*n, 1)); - Complex *pz = z.fortran_vec (); - Array rz (dim_vector (n, 1)); - double *prz = rz.fortran_vec (); - F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, - F77_DBLE_CMPLX_ARG (h), n, anorm, m_rcond, - F77_DBLE_CMPLX_ARG (pz), prz, zpocon_info - F77_CHAR_ARG_LEN (1))); + // Now calculate the condition number for non-singular matrix. + Array z (dim_vector (2*n, 1)); + Complex *pz = z.fortran_vec (); + Array rz (dim_vector (n, 1)); + double *prz = rz.fortran_vec (); + F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, + F77_DBLE_CMPLX_ARG (h), n, anorm, m_rcond, + F77_DBLE_CMPLX_ARG (pz), prz, zpocon_info + F77_CHAR_ARG_LEN (1))); - if (zpocon_info != 0) - info = -1; - } + if (zpocon_info != 0) + info = -1; + } - return info; - } + return info; +} #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - chol::update (const ComplexColumnVector& u) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); +template <> +OCTAVE_API void +chol::update (const ComplexColumnVector& u) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - ComplexColumnVector utmp = u; + ComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, rw, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zch1up, ZCH1UP, (n, - F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, - F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), - rw)); - } + F77_XFCN (zch1up, ZCH1UP, (n, + F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, + F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), + rw)); +} - template <> - OCTAVE_API octave_idx_type - chol::downdate (const ComplexColumnVector& u) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::downdate (const ComplexColumnVector& u) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - ComplexColumnVector utmp = u; + ComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, rw, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zch1dn, ZCH1DN, (n, - F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, - F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), - rw, info)); + F77_XFCN (zch1dn, ZCH1DN, (n, + F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, + F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), + rw, info)); - return info; - } + return info; +} - template <> - OCTAVE_API octave_idx_type - chol::insert_sym (const ComplexColumnVector& u, - octave_idx_type j_arg) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::insert_sym (const ComplexColumnVector& u, + octave_idx_type j_arg) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (u.numel () != n + 1) - (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("cholinsert: index out of range"); + if (u.numel () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("cholinsert: index out of range"); - ComplexColumnVector utmp = u; + ComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, rw, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - m_chol_mat.resize (n+1, n+1); - F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); + m_chol_mat.resize (n+1, n+1); + F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); - F77_XFCN (zchinx, ZCHINX, (n, - F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), - ldcm, j + 1, - F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), - rw, info)); + F77_XFCN (zchinx, ZCHINX, (n, + F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), + ldcm, j + 1, + F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), + rw, info)); - return info; - } + return info; +} - template <> - OCTAVE_API void - chol::delete_sym (octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::delete_sym (octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("choldelete: index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("choldelete: index out of range"); - OCTAVE_LOCAL_BUFFER (double, rw, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zchdex, ZCHDEX, (n, - F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, j + 1, rw)); + F77_XFCN (zchdex, ZCHDEX, (n, + F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, j + 1, rw)); - m_chol_mat.resize (n-1, n-1); - } + m_chol_mat.resize (n-1, n-1); +} - template <> - OCTAVE_API void - chol::shift_sym (octave_idx_type i_arg, - octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::shift_sym (octave_idx_type i_arg, + octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("cholshift: index out of range"); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("cholshift: index out of range"); - OCTAVE_LOCAL_BUFFER (Complex, w, n); - OCTAVE_LOCAL_BUFFER (double, rw, n); + OCTAVE_LOCAL_BUFFER (Complex, w, n); + OCTAVE_LOCAL_BUFFER (double, rw, n); - F77_XFCN (zchshx, ZCHSHX, (n, - F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, i + 1, j + 1, - F77_DBLE_CMPLX_ARG (w), rw)); - } + F77_XFCN (zchshx, ZCHSHX, (n, + F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, i + 1, j + 1, + F77_DBLE_CMPLX_ARG (w), rw)); +} #endif - template <> - OCTAVE_API octave_idx_type - chol::init (const FloatComplexMatrix& a, bool upper, - bool calc_cond) - { - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); +template <> +OCTAVE_API octave_idx_type +chol::init (const FloatComplexMatrix& a, bool upper, + bool calc_cond) +{ + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("chol: requires square matrix"); + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("chol: requires square matrix"); - F77_INT n = to_f77_int (a_nc); - F77_INT info; + F77_INT n = to_f77_int (a_nc); + F77_INT info; - m_is_upper = upper; + m_is_upper = upper; - m_chol_mat.clear (n, n); - if (m_is_upper) - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i <= j; i++) - m_chol_mat.xelem (i, j) = a(i, j); - for (octave_idx_type i = j+1; i < n; i++) - m_chol_mat.xelem (i, j) = 0.0f; - } - else - for (octave_idx_type j = 0; j < n; j++) - { - for (octave_idx_type i = 0; i < j; i++) - m_chol_mat.xelem (i, j) = 0.0f; - for (octave_idx_type i = j; i < n; i++) - m_chol_mat.xelem (i, j) = a(i, j); - } - FloatComplex *h = m_chol_mat.fortran_vec (); + m_chol_mat.clear (n, n); + if (m_is_upper) + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i <= j; i++) + m_chol_mat.xelem (i, j) = a(i, j); + for (octave_idx_type i = j+1; i < n; i++) + m_chol_mat.xelem (i, j) = 0.0f; + } + else + for (octave_idx_type j = 0; j < n; j++) + { + for (octave_idx_type i = 0; i < j; i++) + m_chol_mat.xelem (i, j) = 0.0f; + for (octave_idx_type i = j; i < n; i++) + m_chol_mat.xelem (i, j) = a(i, j); + } + FloatComplex *h = m_chol_mat.fortran_vec (); - // Calculate the norm of the matrix, for later use. - float anorm = 0; - if (calc_cond) - anorm = octave::xnorm (a, 1); + // Calculate the norm of the matrix, for later use. + float anorm = 0; + if (calc_cond) + anorm = octave::xnorm (a, 1); - if (m_is_upper) - F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), - n, F77_CMPLX_ARG (h), n, info - F77_CHAR_ARG_LEN (1))); - else - F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), - n, F77_CMPLX_ARG (h), n, info - F77_CHAR_ARG_LEN (1))); + if (m_is_upper) + F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("U", 1), + n, F77_CMPLX_ARG (h), n, info + F77_CHAR_ARG_LEN (1))); + else + F77_XFCN (cpotrf, CPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1), + n, F77_CMPLX_ARG (h), n, info + F77_CHAR_ARG_LEN (1))); - m_rcond = 0.0; - if (info > 0) - m_chol_mat.resize (info - 1, info - 1); - else if (calc_cond) - { - F77_INT cpocon_info = 0; + m_rcond = 0.0; + if (info > 0) + m_chol_mat.resize (info - 1, info - 1); + else if (calc_cond) + { + F77_INT cpocon_info = 0; - // Now calculate the condition number for non-singular matrix. - Array z (dim_vector (2*n, 1)); - FloatComplex *pz = z.fortran_vec (); - Array rz (dim_vector (n, 1)); - float *prz = rz.fortran_vec (); - F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, - F77_CMPLX_ARG (h), n, anorm, m_rcond, - F77_CMPLX_ARG (pz), prz, cpocon_info - F77_CHAR_ARG_LEN (1))); + // Now calculate the condition number for non-singular matrix. + Array z (dim_vector (2*n, 1)); + FloatComplex *pz = z.fortran_vec (); + Array rz (dim_vector (n, 1)); + float *prz = rz.fortran_vec (); + F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, + F77_CMPLX_ARG (h), n, anorm, m_rcond, + F77_CMPLX_ARG (pz), prz, cpocon_info + F77_CHAR_ARG_LEN (1))); - if (cpocon_info != 0) - info = -1; - } + if (cpocon_info != 0) + info = -1; + } - return info; - } + return info; +} #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - chol::update (const FloatComplexColumnVector& u) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); +template <> +OCTAVE_API void +chol::update (const FloatComplexColumnVector& u) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - FloatComplexColumnVector utmp = u; + FloatComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, rw, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cch1up, CCH1UP, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, F77_CMPLX_ARG (utmp.fortran_vec ()), rw)); - } + F77_XFCN (cch1up, CCH1UP, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, F77_CMPLX_ARG (utmp.fortran_vec ()), rw)); +} - template <> - OCTAVE_API octave_idx_type - chol::downdate (const FloatComplexColumnVector& u) - { - F77_INT info = -1; +template <> +OCTAVE_API octave_idx_type +chol::downdate (const FloatComplexColumnVector& u) +{ + F77_INT info = -1; - F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n) - (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); + if (u.numel () != n) + (*current_liboctave_error_handler) ("cholupdate: dimension mismatch"); - FloatComplexColumnVector utmp = u; + FloatComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, rw, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cch1dn, CCH1DN, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, F77_CMPLX_ARG (utmp.fortran_vec ()), - rw, info)); + F77_XFCN (cch1dn, CCH1DN, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, F77_CMPLX_ARG (utmp.fortran_vec ()), + rw, info)); - return info; - } + return info; +} - template <> - OCTAVE_API octave_idx_type - chol::insert_sym (const FloatComplexColumnVector& u, - octave_idx_type j_arg) - { - F77_INT info = -1; - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API octave_idx_type +chol::insert_sym (const FloatComplexColumnVector& u, + octave_idx_type j_arg) +{ + F77_INT info = -1; + F77_INT j = to_f77_int (j_arg); - F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT n = to_f77_int (m_chol_mat.rows ()); - if (u.numel () != n + 1) - (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("cholinsert: index out of range"); + if (u.numel () != n + 1) + (*current_liboctave_error_handler) ("cholinsert: dimension mismatch"); + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("cholinsert: index out of range"); - FloatComplexColumnVector utmp = u; + FloatComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, rw, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - m_chol_mat.resize (n+1, n+1); - F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); + m_chol_mat.resize (n+1, n+1); + F77_INT ldcm = to_f77_int (m_chol_mat.rows ()); - F77_XFCN (cchinx, CCHINX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), - ldcm, j + 1, - F77_CMPLX_ARG (utmp.fortran_vec ()), - rw, info)); + F77_XFCN (cchinx, CCHINX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), + ldcm, j + 1, + F77_CMPLX_ARG (utmp.fortran_vec ()), + rw, info)); - return info; - } + return info; +} - template <> - OCTAVE_API void - chol::delete_sym (octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::delete_sym (octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT j = to_f77_int (j_arg); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("choldelete: index out of range"); + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("choldelete: index out of range"); - OCTAVE_LOCAL_BUFFER (float, rw, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cchdex, CCHDEX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, j + 1, rw)); + F77_XFCN (cchdex, CCHDEX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, j + 1, rw)); - m_chol_mat.resize (n-1, n-1); - } + m_chol_mat.resize (n-1, n-1); +} - template <> - OCTAVE_API void - chol::shift_sym (octave_idx_type i_arg, - octave_idx_type j_arg) - { - F77_INT n = to_f77_int (m_chol_mat.rows ()); - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +chol::shift_sym (octave_idx_type i_arg, + octave_idx_type j_arg) +{ + F77_INT n = to_f77_int (m_chol_mat.rows ()); + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("cholshift: index out of range"); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("cholshift: index out of range"); - OCTAVE_LOCAL_BUFFER (FloatComplex, w, n); - OCTAVE_LOCAL_BUFFER (float, rw, n); + OCTAVE_LOCAL_BUFFER (FloatComplex, w, n); + OCTAVE_LOCAL_BUFFER (float, rw, n); - F77_XFCN (cchshx, CCHSHX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), - n, i + 1, j + 1, F77_CMPLX_ARG (w), rw)); - } + F77_XFCN (cchshx, CCHSHX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()), + n, i + 1, j + 1, F77_CMPLX_ARG (w), rw)); +} #endif - // Instantiations we need. +// Instantiations we need. - template class chol; +template class chol; - template class chol; +template class chol; - template class chol; +template class chol; - template class chol; +template class chol; - template OCTAVE_API Matrix - chol2inv (const Matrix& r); +template OCTAVE_API Matrix +chol2inv (const Matrix& r); - template OCTAVE_API ComplexMatrix - chol2inv (const ComplexMatrix& r); +template OCTAVE_API ComplexMatrix +chol2inv (const ComplexMatrix& r); - template OCTAVE_API FloatMatrix - chol2inv (const FloatMatrix& r); +template OCTAVE_API FloatMatrix +chol2inv (const FloatMatrix& r); - template OCTAVE_API FloatComplexMatrix - chol2inv (const FloatComplexMatrix& r); +template OCTAVE_API FloatComplexMatrix +chol2inv (const FloatComplexMatrix& r); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/chol.h --- a/liboctave/numeric/chol.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/chol.h Thu Dec 01 20:05:44 2022 -0800 @@ -32,78 +32,78 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - chol - { - public: +template +class +chol +{ +public: - typedef typename T::column_vector_type VT; - typedef typename T::real_elt_type COND_T; + typedef typename T::column_vector_type VT; + typedef typename T::real_elt_type COND_T; + + chol (void) : m_chol_mat (), m_rcond (0), m_is_upper (true) { } - chol (void) : m_chol_mat (), m_rcond (0), m_is_upper (true) { } + chol (const T& a, bool upper = true, bool calc_cond = false) + : m_chol_mat (), m_rcond (0) + { + init (a, upper, calc_cond); + } - chol (const T& a, bool upper = true, bool calc_cond = false) - : m_chol_mat (), m_rcond (0) - { - init (a, upper, calc_cond); - } + chol (const T& a, octave_idx_type& info, bool upper = true, + bool calc_cond = false) + : m_chol_mat (), m_rcond (0) + { + info = init (a, upper, calc_cond); + } - chol (const T& a, octave_idx_type& info, bool upper = true, - bool calc_cond = false) - : m_chol_mat (), m_rcond (0) + chol (const chol& a) + : m_chol_mat (a.m_chol_mat), m_rcond (a.m_rcond), m_is_upper (a.m_is_upper) { } + + chol& operator = (const chol& a) + { + if (this != &a) { - info = init (a, upper, calc_cond); + m_chol_mat = a.m_chol_mat; + m_rcond = a.m_rcond; + m_is_upper = a.m_is_upper; } - chol (const chol& a) - : m_chol_mat (a.m_chol_mat), m_rcond (a.m_rcond), m_is_upper (a.m_is_upper) { } + return *this; + } - chol& operator = (const chol& a) - { - if (this != &a) - { - m_chol_mat = a.m_chol_mat; - m_rcond = a.m_rcond; - m_is_upper = a.m_is_upper; - } + T chol_matrix (void) const { return m_chol_mat; } + + COND_T rcond (void) const { return m_rcond; } - return *this; - } + // Compute the inverse of a matrix using the Cholesky factorization. + OCTAVE_API T inverse (void) const; - T chol_matrix (void) const { return m_chol_mat; } + OCTAVE_API void set (const T& R); - COND_T rcond (void) const { return m_rcond; } + OCTAVE_API void update (const VT& u); - // Compute the inverse of a matrix using the Cholesky factorization. - OCTAVE_API T inverse (void) const; + OCTAVE_API octave_idx_type downdate (const VT& u); - OCTAVE_API void set (const T& R); + OCTAVE_API octave_idx_type insert_sym (const VT& u, octave_idx_type j); - OCTAVE_API void update (const VT& u); + OCTAVE_API void delete_sym (octave_idx_type j); - OCTAVE_API octave_idx_type downdate (const VT& u); - - OCTAVE_API octave_idx_type insert_sym (const VT& u, octave_idx_type j); + OCTAVE_API void shift_sym (octave_idx_type i, octave_idx_type j); - OCTAVE_API void delete_sym (octave_idx_type j); +private: - OCTAVE_API void shift_sym (octave_idx_type i, octave_idx_type j); - - private: + T m_chol_mat; - T m_chol_mat; + COND_T m_rcond; - COND_T m_rcond; - - bool m_is_upper; + bool m_is_upper; - OCTAVE_API octave_idx_type init (const T& a, bool upper, bool calc_cond); - }; + OCTAVE_API octave_idx_type init (const T& a, bool upper, bool calc_cond); +}; - template - OCTAVE_API T - chol2inv (const T& r); +template +OCTAVE_API T +chol2inv (const T& r); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/gepbalance.cc --- a/liboctave/numeric/gepbalance.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/gepbalance.cc Thu Dec 01 20:05:44 2022 -0800 @@ -42,285 +42,285 @@ OCTAVE_BEGIN_NAMESPACE(math) - template <> - OCTAVE_API octave_idx_type - gepbalance::init (const Matrix& a, const Matrix& b, - const std::string& balance_job) - { - F77_INT n = to_f77_int (a.cols ()); - - if (a.rows () != n) - (*current_liboctave_error_handler) - ("GEPBALANCE requires square matrix"); - - if (a.dims () != b.dims ()) - err_nonconformant ("GEPBALANCE", n, n, b.rows(), b.cols()); +template <> +OCTAVE_API octave_idx_type +gepbalance::init (const Matrix& a, const Matrix& b, + const std::string& balance_job) +{ + F77_INT n = to_f77_int (a.cols ()); - F77_INT info; - F77_INT ilo; - F77_INT ihi; + if (a.rows () != n) + (*current_liboctave_error_handler) + ("GEPBALANCE requires square matrix"); - OCTAVE_LOCAL_BUFFER (double, plscale, n); - OCTAVE_LOCAL_BUFFER (double, prscale, n); - OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n); + if (a.dims () != b.dims ()) + err_nonconformant ("GEPBALANCE", n, n, b.rows(), b.cols()); - m_balanced_mat = a; - double *p_balanced_mat = m_balanced_mat.fortran_vec (); - m_balanced_mat2 = b; - double *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); - - char job = balance_job[0]; + F77_INT info; + F77_INT ilo; + F77_INT ihi; - F77_XFCN (dggbal, DGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, p_balanced_mat, n, p_balanced_mat2, - n, ilo, ihi, plscale, prscale, pwork, info - F77_CHAR_ARG_LEN (1))); + OCTAVE_LOCAL_BUFFER (double, plscale, n); + OCTAVE_LOCAL_BUFFER (double, prscale, n); + OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n); - m_balancing_mat = Matrix (n, n, 0.0); - m_balancing_mat2 = Matrix (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - { - octave_quit (); - m_balancing_mat.elem (i, i) = 1.0; - m_balancing_mat2.elem (i, i) = 1.0; - } + m_balanced_mat = a; + double *p_balanced_mat = m_balanced_mat.fortran_vec (); + m_balanced_mat2 = b; + double *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); - double *p_balancing_mat = m_balancing_mat.fortran_vec (); - double *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); + char job = balance_job[0]; - // first left - F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("L", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (dggbal, DGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, p_balanced_mat, n, p_balanced_mat2, + n, ilo, ihi, plscale, prscale, pwork, info + F77_CHAR_ARG_LEN (1))); - // then right - F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("R", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat2, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); - - return info; + m_balancing_mat = Matrix (n, n, 0.0); + m_balancing_mat2 = Matrix (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + { + octave_quit (); + m_balancing_mat.elem (i, i) = 1.0; + m_balancing_mat2.elem (i, i) = 1.0; } - template <> - OCTAVE_API octave_idx_type - gepbalance::init (const FloatMatrix& a, const FloatMatrix& b, - const std::string& balance_job) - { - F77_INT n = to_f77_int (a.cols ()); + double *p_balancing_mat = m_balancing_mat.fortran_vec (); + double *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); - if (a.rows () != n) - (*current_liboctave_error_handler) - ("FloatGEPBALANCE requires square matrix"); - - if (a.dims () != b.dims ()) - err_nonconformant ("FloatGEPBALANCE", - n, n, b.rows(), b.cols()); + // first left + F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("L", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - F77_INT info; - F77_INT ilo; - F77_INT ihi; + // then right + F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("R", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat2, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - OCTAVE_LOCAL_BUFFER (float, plscale, n); - OCTAVE_LOCAL_BUFFER (float, prscale, n); - OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n); + return info; +} - m_balanced_mat = a; - float *p_balanced_mat = m_balanced_mat.fortran_vec (); - m_balanced_mat2 = b; - float *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); - - char job = balance_job[0]; +template <> +OCTAVE_API octave_idx_type +gepbalance::init (const FloatMatrix& a, const FloatMatrix& b, + const std::string& balance_job) +{ + F77_INT n = to_f77_int (a.cols ()); - F77_XFCN (sggbal, SGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, p_balanced_mat, n, p_balanced_mat2, - n, ilo, ihi, plscale, prscale, pwork, info - F77_CHAR_ARG_LEN (1))); + if (a.rows () != n) + (*current_liboctave_error_handler) + ("FloatGEPBALANCE requires square matrix"); + + if (a.dims () != b.dims ()) + err_nonconformant ("FloatGEPBALANCE", + n, n, b.rows(), b.cols()); - m_balancing_mat = FloatMatrix (n, n, 0.0); - m_balancing_mat2 = FloatMatrix (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - { - octave_quit (); - m_balancing_mat.elem (i, i) = 1.0; - m_balancing_mat2.elem (i, i) = 1.0; - } + F77_INT info; + F77_INT ilo; + F77_INT ihi; - float *p_balancing_mat = m_balancing_mat.fortran_vec (); - float *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); + OCTAVE_LOCAL_BUFFER (float, plscale, n); + OCTAVE_LOCAL_BUFFER (float, prscale, n); + OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n); - // first left - F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("L", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + m_balanced_mat = a; + float *p_balanced_mat = m_balanced_mat.fortran_vec (); + m_balanced_mat2 = b; + float *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); + + char job = balance_job[0]; - // then right - F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("R", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat2, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (sggbal, SGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, p_balanced_mat, n, p_balanced_mat2, + n, ilo, ihi, plscale, prscale, pwork, info + F77_CHAR_ARG_LEN (1))); - return info; + m_balancing_mat = FloatMatrix (n, n, 0.0); + m_balancing_mat2 = FloatMatrix (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + { + octave_quit (); + m_balancing_mat.elem (i, i) = 1.0; + m_balancing_mat2.elem (i, i) = 1.0; } - template <> - OCTAVE_API octave_idx_type - gepbalance::init (const ComplexMatrix& a, - const ComplexMatrix& b, - const std::string& balance_job) - { - F77_INT n = to_f77_int (a.cols ()); + float *p_balancing_mat = m_balancing_mat.fortran_vec (); + float *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); - if (a.rows () != n) - (*current_liboctave_error_handler) - ("ComplexGEPBALANCE requires square matrix"); + // first left + F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("L", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - if (a.dims () != b.dims ()) - err_nonconformant ("ComplexGEPBALANCE", - n, n, b.rows(), b.cols()); - - F77_INT info; - F77_INT ilo; - F77_INT ihi; + // then right + F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("R", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat2, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - OCTAVE_LOCAL_BUFFER (double, plscale, n); - OCTAVE_LOCAL_BUFFER (double, prscale, n); - OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n); + return info; +} - m_balanced_mat = a; - Complex *p_balanced_mat = m_balanced_mat.fortran_vec (); - m_balanced_mat2 = b; - Complex *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); - - char job = balance_job[0]; +template <> +OCTAVE_API octave_idx_type +gepbalance::init (const ComplexMatrix& a, + const ComplexMatrix& b, + const std::string& balance_job) +{ + F77_INT n = to_f77_int (a.cols ()); - F77_XFCN (zggbal, ZGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, F77_DBLE_CMPLX_ARG (p_balanced_mat), - n, F77_DBLE_CMPLX_ARG (p_balanced_mat2), - n, ilo, ihi, plscale, prscale, pwork, info - F77_CHAR_ARG_LEN (1))); + if (a.rows () != n) + (*current_liboctave_error_handler) + ("ComplexGEPBALANCE requires square matrix"); + + if (a.dims () != b.dims ()) + err_nonconformant ("ComplexGEPBALANCE", + n, n, b.rows(), b.cols()); - m_balancing_mat = Matrix (n, n, 0.0); - m_balancing_mat2 = Matrix (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - { - octave_quit (); - m_balancing_mat.elem (i, i) = 1.0; - m_balancing_mat2.elem (i, i) = 1.0; - } + F77_INT info; + F77_INT ilo; + F77_INT ihi; - double *p_balancing_mat = m_balancing_mat.fortran_vec (); - double *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); + OCTAVE_LOCAL_BUFFER (double, plscale, n); + OCTAVE_LOCAL_BUFFER (double, prscale, n); + OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n); - // first left - F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("L", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + m_balanced_mat = a; + Complex *p_balanced_mat = m_balanced_mat.fortran_vec (); + m_balanced_mat2 = b; + Complex *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); + + char job = balance_job[0]; - // then right - F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("R", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat2, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (zggbal, ZGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, F77_DBLE_CMPLX_ARG (p_balanced_mat), + n, F77_DBLE_CMPLX_ARG (p_balanced_mat2), + n, ilo, ihi, plscale, prscale, pwork, info + F77_CHAR_ARG_LEN (1))); - return info; + m_balancing_mat = Matrix (n, n, 0.0); + m_balancing_mat2 = Matrix (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + { + octave_quit (); + m_balancing_mat.elem (i, i) = 1.0; + m_balancing_mat2.elem (i, i) = 1.0; } - template <> - OCTAVE_API octave_idx_type - gepbalance::init (const FloatComplexMatrix& a, - const FloatComplexMatrix& b, - const std::string& balance_job) - { - F77_INT n = to_f77_int (a.cols ()); - - if (a.rows () != n) - { - (*current_liboctave_error_handler) - ("FloatComplexGEPBALANCE requires square matrix"); - return -1; - } + double *p_balancing_mat = m_balancing_mat.fortran_vec (); + double *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); - if (a.dims () != b.dims ()) - err_nonconformant ("FloatComplexGEPBALANCE", - n, n, b.rows(), b.cols()); - - F77_INT info; - F77_INT ilo; - F77_INT ihi; - - OCTAVE_LOCAL_BUFFER (float, plscale, n); - OCTAVE_LOCAL_BUFFER (float, prscale, n); - OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n); - - m_balanced_mat = a; - FloatComplex *p_balanced_mat = m_balanced_mat.fortran_vec (); - m_balanced_mat2 = b; - FloatComplex *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); - - char job = balance_job[0]; + // first left + F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("L", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - F77_XFCN (cggbal, CGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, F77_CMPLX_ARG (p_balanced_mat), - n, F77_CMPLX_ARG (p_balanced_mat2), - n, ilo, ihi, plscale, prscale, pwork, info - F77_CHAR_ARG_LEN (1))); + // then right + F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("R", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat2, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - m_balancing_mat = FloatMatrix (n, n, 0.0); - m_balancing_mat2 = FloatMatrix (n, n, 0.0); - for (F77_INT i = 0; i < n; i++) - { - octave_quit (); - m_balancing_mat.elem (i, i) = 1.0; - m_balancing_mat2.elem (i, i) = 1.0; - } - - float *p_balancing_mat = m_balancing_mat.fortran_vec (); - float *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); + return info; +} - // first left - F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("L", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); +template <> +OCTAVE_API octave_idx_type +gepbalance::init (const FloatComplexMatrix& a, + const FloatComplexMatrix& b, + const std::string& balance_job) +{ + F77_INT n = to_f77_int (a.cols ()); - // then right - F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 ("R", 1), - n, ilo, ihi, plscale, prscale, - n, p_balancing_mat2, n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); - - return info; + if (a.rows () != n) + { + (*current_liboctave_error_handler) + ("FloatComplexGEPBALANCE requires square matrix"); + return -1; } - // Instantiations we need. + if (a.dims () != b.dims ()) + err_nonconformant ("FloatComplexGEPBALANCE", + n, n, b.rows(), b.cols()); + + F77_INT info; + F77_INT ilo; + F77_INT ihi; + + OCTAVE_LOCAL_BUFFER (float, plscale, n); + OCTAVE_LOCAL_BUFFER (float, prscale, n); + OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n); - template class gepbalance; + m_balanced_mat = a; + FloatComplex *p_balanced_mat = m_balanced_mat.fortran_vec (); + m_balanced_mat2 = b; + FloatComplex *p_balanced_mat2 = m_balanced_mat2.fortran_vec (); + + char job = balance_job[0]; + + F77_XFCN (cggbal, CGGBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, F77_CMPLX_ARG (p_balanced_mat), + n, F77_CMPLX_ARG (p_balanced_mat2), + n, ilo, ihi, plscale, prscale, pwork, info + F77_CHAR_ARG_LEN (1))); - template class gepbalance; + m_balancing_mat = FloatMatrix (n, n, 0.0); + m_balancing_mat2 = FloatMatrix (n, n, 0.0); + for (F77_INT i = 0; i < n; i++) + { + octave_quit (); + m_balancing_mat.elem (i, i) = 1.0; + m_balancing_mat2.elem (i, i) = 1.0; + } + + float *p_balancing_mat = m_balancing_mat.fortran_vec (); + float *p_balancing_mat2 = m_balancing_mat2.fortran_vec (); + + // first left + F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("L", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - template class gepbalance; + // then right + F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 ("R", 1), + n, ilo, ihi, plscale, prscale, + n, p_balancing_mat2, n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - template class gepbalance; + return info; +} + +// Instantiations we need. + +template class gepbalance; + +template class gepbalance; + +template class gepbalance; + +template class gepbalance; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/gepbalance.h --- a/liboctave/numeric/gepbalance.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/gepbalance.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,66 +34,66 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - gepbalance - { - public: +template +class +gepbalance +{ +public: - typedef typename T::real_matrix_type RT; + typedef typename T::real_matrix_type RT; + + gepbalance (void) + : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (), + m_balancing_mat2 () + { } - gepbalance (void) - : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (), - m_balancing_mat2 () - { } + gepbalance (const T& a, const T& b, const std::string& job) + : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (), + m_balancing_mat2 () + { + init (a, b, job); + } - gepbalance (const T& a, const T& b, const std::string& job) - : m_balanced_mat (), m_balanced_mat2 (), m_balancing_mat (), - m_balancing_mat2 () + gepbalance (const gepbalance& a) + : m_balanced_mat (a.m_balanced_mat), + m_balanced_mat2 (a.m_balanced_mat2), + m_balancing_mat (a.m_balancing_mat), + m_balancing_mat2 (a.m_balancing_mat2) + { } + + gepbalance& operator = (const gepbalance& a) + { + if (this != &a) { - init (a, b, job); + m_balanced_mat = a.m_balanced_mat; + m_balanced_mat2 = a.m_balanced_mat2; + m_balancing_mat = a.m_balancing_mat; + m_balancing_mat2 = a.m_balancing_mat2; } - gepbalance (const gepbalance& a) - : m_balanced_mat (a.m_balanced_mat), - m_balanced_mat2 (a.m_balanced_mat2), - m_balancing_mat (a.m_balancing_mat), - m_balancing_mat2 (a.m_balancing_mat2) - { } + return *this; + } + + ~gepbalance (void) = default; - gepbalance& operator = (const gepbalance& a) - { - if (this != &a) - { - m_balanced_mat = a.m_balanced_mat; - m_balanced_mat2 = a.m_balanced_mat2; - m_balancing_mat = a.m_balancing_mat; - m_balancing_mat2 = a.m_balancing_mat2; - } + T balanced_matrix (void) const { return m_balanced_mat; } - return *this; - } + T balanced_matrix2 (void) const { return m_balanced_mat2; } + + RT balancing_matrix (void) const { return m_balancing_mat; } - ~gepbalance (void) = default; - - T balanced_matrix (void) const { return m_balanced_mat; } + RT balancing_matrix2 (void) const { return m_balancing_mat2; } - T balanced_matrix2 (void) const { return m_balanced_mat2; } - - RT balancing_matrix (void) const { return m_balancing_mat; } - - RT balancing_matrix2 (void) const { return m_balancing_mat2; } +private: - private: + T m_balanced_mat; + T m_balanced_mat2; + RT m_balancing_mat; + RT m_balancing_mat2; - T m_balanced_mat; - T m_balanced_mat2; - RT m_balancing_mat; - RT m_balancing_mat2; - - OCTAVE_API octave_idx_type - init (const T& a, const T& b, const std::string& job); - }; + OCTAVE_API octave_idx_type + init (const T& a, const T& b, const std::string& job); +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/gsvd.cc --- a/liboctave/numeric/gsvd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/gsvd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,655 +44,655 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static std::unordered_map gsvd_fcn; +static std::unordered_map gsvd_fcn; - static bool have_DGGSVD3 = false; - static bool gsvd_initialized = false; +static bool have_DGGSVD3 = false; +static bool gsvd_initialized = false; - /* Hack to stringize results of F77_FUNC macro. */ - #define xSTRINGIZE(x) #x - #define STRINGIZE(x) xSTRINGIZE(x) +/* Hack to stringize results of F77_FUNC macro. */ +#define xSTRINGIZE(x) #x +#define STRINGIZE(x) xSTRINGIZE(x) - static void initialize_gsvd (void) - { - if (gsvd_initialized) - return; +static void initialize_gsvd (void) +{ + if (gsvd_initialized) + return; - dynamic_library libs (""); - if (! libs) - (*current_liboctave_error_handler) - ("gsvd: unable to query LAPACK library"); + dynamic_library libs (""); + if (! libs) + (*current_liboctave_error_handler) + ("gsvd: unable to query LAPACK library"); - have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3))) - != nullptr); + have_DGGSVD3 = (libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3))) + != nullptr); - if (have_DGGSVD3) - { - gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3))); - gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3))); - gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3))); - gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3))); - } - else - { - gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD))); - gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD))); - gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD))); - gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD))); - } + if (have_DGGSVD3) + { + gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd3, DGGSVD3))); + gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd3, SGGSVD3))); + gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd3, ZGGSVD3))); + gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd3, CGGSVD3))); + } + else + { + gsvd_fcn["dg"] = libs.search (STRINGIZE (F77_FUNC (dggsvd, DGGSVD))); + gsvd_fcn["sg"] = libs.search (STRINGIZE (F77_FUNC (sggsvd, SGGSVD))); + gsvd_fcn["zg"] = libs.search (STRINGIZE (F77_FUNC (zggsvd, ZGGSVD))); + gsvd_fcn["cg"] = libs.search (STRINGIZE (F77_FUNC (cggsvd, CGGSVD))); + } - gsvd_initialized = true; - } + gsvd_initialized = true; +} - /* Clean up macro namespace as soon as we are done using them */ - #undef xSTRINGIZE - #undef STRINGIZE +/* Clean up macro namespace as soon as we are done using them */ +#undef xSTRINGIZE +#undef STRINGIZE - template - struct real_ggsvd_ptr - { - typedef F77_RET_T (*type) +template +struct real_ggsvd_ptr +{ + typedef F77_RET_T (*type) (F77_CONST_CHAR_ARG_DECL, // JOBU - F77_CONST_CHAR_ARG_DECL, // JOBV - F77_CONST_CHAR_ARG_DECL, // JOBQ - const F77_INT&, // M - const F77_INT&, // N - const F77_INT&, // P - F77_INT&, // K - F77_INT&, // L - T1 *, // A(LDA,N) - const F77_INT&, // LDA - T1 *, // B(LDB,N) - const F77_INT&, // LDB - T1 *, // ALPHA(N) - T1 *, // BETA(N) - T1 *, // U(LDU,M) - const F77_INT&, // LDU - T1 *, // V(LDV,P) - const F77_INT&, // LDV - T1 *, // Q(LDQ,N) - const F77_INT&, // LDQ - T1 *, // WORK - F77_INT *, // IWORK(N) - F77_INT& // INFO - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); - }; + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT&, // K + F77_INT&, // L + T1 *, // A(LDA,N) + const F77_INT&, // LDA + T1 *, // B(LDB,N) + const F77_INT&, // LDB + T1 *, // ALPHA(N) + T1 *, // BETA(N) + T1 *, // U(LDU,M) + const F77_INT&, // LDU + T1 *, // V(LDV,P) + const F77_INT&, // LDV + T1 *, // Q(LDQ,N) + const F77_INT&, // LDQ + T1 *, // WORK + F77_INT *, // IWORK(N) + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); +}; - template - struct real_ggsvd3_ptr - { - typedef F77_RET_T (*type) +template +struct real_ggsvd3_ptr +{ + typedef F77_RET_T (*type) (F77_CONST_CHAR_ARG_DECL, // JOBU - F77_CONST_CHAR_ARG_DECL, // JOBV - F77_CONST_CHAR_ARG_DECL, // JOBQ - const F77_INT&, // M - const F77_INT&, // N - const F77_INT&, // P - F77_INT&, // K - F77_INT&, // L - T1 *, // A(LDA,N) - const F77_INT&, // LDA - T1 *, // B(LDB,N) - const F77_INT&, // LDB - T1 *, // ALPHA(N) - T1 *, // BETA(N) - T1 *, // U(LDU,M) - const F77_INT&, // LDU - T1 *, // V(LDV,P) - const F77_INT&, // LDV - T1 *, // Q(LDQ,N) - const F77_INT&, // LDQ - T1 *, // WORK - const F77_INT&, // LWORK - F77_INT *, // IWORK(N) - F77_INT& // INFO - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); - }; + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT&, // K + F77_INT&, // L + T1 *, // A(LDA,N) + const F77_INT&, // LDA + T1 *, // B(LDB,N) + const F77_INT&, // LDB + T1 *, // ALPHA(N) + T1 *, // BETA(N) + T1 *, // U(LDU,M) + const F77_INT&, // LDU + T1 *, // V(LDV,P) + const F77_INT&, // LDV + T1 *, // Q(LDQ,N) + const F77_INT&, // LDQ + T1 *, // WORK + const F77_INT&, // LWORK + F77_INT *, // IWORK(N) + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); +}; - template - struct comp_ggsvd_ptr - { - typedef F77_RET_T (*type) +template +struct comp_ggsvd_ptr +{ + typedef F77_RET_T (*type) (F77_CONST_CHAR_ARG_DECL, // JOBU - F77_CONST_CHAR_ARG_DECL, // JOBV - F77_CONST_CHAR_ARG_DECL, // JOBQ - const F77_INT&, // M - const F77_INT&, // N - const F77_INT&, // P - F77_INT&, // K - F77_INT&, // L - T1 *, // A(LDA,N) - const F77_INT&, // LDA - T1 *, // B(LDB,N) - const F77_INT&, // LDB - T2 *, // ALPHA(N) - T2 *, // BETA(N) - T1 *, // U(LDU,M) - const F77_INT&, // LDU - T1 *, // V(LDV,P) - const F77_INT&, // LDV - T1 *, // Q(LDQ,N) - const F77_INT&, // LDQ - T1 *, // WORK - T2 *, // RWORK - F77_INT *, // IWORK(N) - F77_INT& // INFO - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); - }; + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT&, // K + F77_INT&, // L + T1 *, // A(LDA,N) + const F77_INT&, // LDA + T1 *, // B(LDB,N) + const F77_INT&, // LDB + T2 *, // ALPHA(N) + T2 *, // BETA(N) + T1 *, // U(LDU,M) + const F77_INT&, // LDU + T1 *, // V(LDV,P) + const F77_INT&, // LDV + T1 *, // Q(LDQ,N) + const F77_INT&, // LDQ + T1 *, // WORK + T2 *, // RWORK + F77_INT *, // IWORK(N) + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); +}; - template - struct comp_ggsvd3_ptr - { - typedef F77_RET_T (*type) +template +struct comp_ggsvd3_ptr +{ + typedef F77_RET_T (*type) (F77_CONST_CHAR_ARG_DECL, // JOBU - F77_CONST_CHAR_ARG_DECL, // JOBV - F77_CONST_CHAR_ARG_DECL, // JOBQ - const F77_INT&, // M - const F77_INT&, // N - const F77_INT&, // P - F77_INT&, // K - F77_INT&, // L - T1 *, // A(LDA,N) - const F77_INT&, // LDA - T1 *, // B(LDB,N) - const F77_INT&, // LDB - T2 *, // ALPHA(N) - T2 *, // BETA(N) - T1 *, // U(LDU,M) - const F77_INT&, // LDU - T1 *, // V(LDV,P) - const F77_INT&, // LDV - T1 *, // Q(LDQ,N) - const F77_INT&, // LDQ - T1 *, // WORK - const F77_INT&, // LWORK - T2 *, // RWORK - F77_INT *, // IWORK(N) - F77_INT& // INFO - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL - F77_CHAR_ARG_LEN_DECL); - }; + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT&, // K + F77_INT&, // L + T1 *, // A(LDA,N) + const F77_INT&, // LDA + T1 *, // B(LDB,N) + const F77_INT&, // LDB + T2 *, // ALPHA(N) + T2 *, // BETA(N) + T1 *, // U(LDU,M) + const F77_INT&, // LDU + T1 *, // V(LDV,P) + const F77_INT&, // LDV + T1 *, // Q(LDQ,N) + const F77_INT&, // LDQ + T1 *, // WORK + const F77_INT&, // LWORK + T2 *, // RWORK + F77_INT *, // IWORK(N) + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); +}; - // template specializations - typedef real_ggsvd_ptr::type dggsvd_type; - typedef real_ggsvd3_ptr::type dggsvd3_type; - typedef real_ggsvd_ptr::type sggsvd_type; - typedef real_ggsvd3_ptr::type sggsvd3_type; - typedef comp_ggsvd_ptr::type zggsvd_type; - typedef comp_ggsvd3_ptr::type zggsvd3_type; - typedef comp_ggsvd_ptr::type cggsvd_type; - typedef comp_ggsvd3_ptr::type cggsvd3_type; +// template specializations +typedef real_ggsvd_ptr::type dggsvd_type; +typedef real_ggsvd3_ptr::type dggsvd3_type; +typedef real_ggsvd_ptr::type sggsvd_type; +typedef real_ggsvd3_ptr::type sggsvd3_type; +typedef comp_ggsvd_ptr::type zggsvd_type; +typedef comp_ggsvd3_ptr::type zggsvd3_type; +typedef comp_ggsvd_ptr::type cggsvd_type; +typedef comp_ggsvd3_ptr::type cggsvd3_type; OCTAVE_BEGIN_NAMESPACE(math) - template <> - void - gsvd::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m, - F77_INT n, F77_INT p, F77_INT& k, F77_INT& l, - double *tmp_dataA, F77_INT m1, double *tmp_dataB, - F77_INT p1, Matrix& alpha, Matrix& beta, double *u, - F77_INT nrow_u, double *v, F77_INT nrow_v, double *q, - F77_INT nrow_q, double *work, F77_INT lwork, - F77_INT *iwork, F77_INT& info) +template <> +void +gsvd::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m, + F77_INT n, F77_INT p, F77_INT& k, F77_INT& l, + double *tmp_dataA, F77_INT m1, double *tmp_dataB, + F77_INT p1, Matrix& alpha, Matrix& beta, double *u, + F77_INT nrow_u, double *v, F77_INT nrow_v, double *q, + F77_INT nrow_q, double *work, F77_INT lwork, + F77_INT *iwork, F77_INT& info) +{ + if (! gsvd_initialized) + initialize_gsvd (); + + if (have_DGGSVD3) { - if (! gsvd_initialized) - initialize_gsvd (); + dggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["dg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, + alpha.fortran_vec (), beta.fortran_vec (), + u, nrow_u, v, nrow_v, q, nrow_q, + work, lwork, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); + } + else + { + dggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["dg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, + alpha.fortran_vec (), beta.fortran_vec (), + u, nrow_u, v, nrow_v, q, nrow_q, + work, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); + } +} - if (have_DGGSVD3) - { - dggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["dg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, - alpha.fortran_vec (), beta.fortran_vec (), - u, nrow_u, v, nrow_v, q, nrow_q, - work, lwork, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } - else - { - dggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["dg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, - alpha.fortran_vec (), beta.fortran_vec (), - u, nrow_u, v, nrow_v, q, nrow_q, - work, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } +template <> +void +gsvd::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m, + F77_INT n, F77_INT p, F77_INT& k, F77_INT& l, + float *tmp_dataA, F77_INT m1, float *tmp_dataB, + F77_INT p1, FloatMatrix& alpha, + FloatMatrix& beta, float *u, F77_INT nrow_u, + float *v, F77_INT nrow_v, float *q, + F77_INT nrow_q, float *work, + F77_INT lwork, F77_INT *iwork, F77_INT& info) +{ + if (! gsvd_initialized) + initialize_gsvd (); + + if (have_DGGSVD3) + { + sggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["sg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, + alpha.fortran_vec (), beta.fortran_vec (), + u, nrow_u, v, nrow_v, q, nrow_q, + work, lwork, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); } + else + { + sggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["sg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, + alpha.fortran_vec (), beta.fortran_vec (), + u, nrow_u, v, nrow_v, q, nrow_q, + work, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); + } +} - template <> - void - gsvd::ggsvd (char& jobu, char& jobv, char& jobq, F77_INT m, - F77_INT n, F77_INT p, F77_INT& k, F77_INT& l, - float *tmp_dataA, F77_INT m1, float *tmp_dataB, - F77_INT p1, FloatMatrix& alpha, - FloatMatrix& beta, float *u, F77_INT nrow_u, - float *v, F77_INT nrow_v, float *q, - F77_INT nrow_q, float *work, - F77_INT lwork, F77_INT *iwork, F77_INT& info) - { - if (! gsvd_initialized) - initialize_gsvd (); +template <> +void +gsvd::ggsvd (char& jobu, char& jobv, char& jobq, + F77_INT m, F77_INT n, F77_INT p, F77_INT& k, + F77_INT& l, Complex *tmp_dataA, F77_INT m1, + Complex *tmp_dataB, F77_INT p1, Matrix& alpha, + Matrix& beta, Complex *u, F77_INT nrow_u, + Complex *v, F77_INT nrow_v, Complex *q, + F77_INT nrow_q, Complex *work, + F77_INT lwork, F77_INT *iwork, F77_INT& info) +{ + if (! gsvd_initialized) + initialize_gsvd (); + + OCTAVE_LOCAL_BUFFER(double, rwork, 2*n); - if (have_DGGSVD3) - { - sggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["sg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, - alpha.fortran_vec (), beta.fortran_vec (), - u, nrow_u, v, nrow_v, q, nrow_q, - work, lwork, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } - else - { - sggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["sg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1, - alpha.fortran_vec (), beta.fortran_vec (), - u, nrow_u, v, nrow_v, q, nrow_q, - work, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } + if (have_DGGSVD3) + { + zggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["zg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, + F77_DBLE_CMPLX_ARG (tmp_dataA), m1, + F77_DBLE_CMPLX_ARG (tmp_dataB), p1, + alpha.fortran_vec (), beta.fortran_vec (), + F77_DBLE_CMPLX_ARG (u), nrow_u, + F77_DBLE_CMPLX_ARG (v), nrow_v, + F77_DBLE_CMPLX_ARG (q), nrow_q, + F77_DBLE_CMPLX_ARG (work), + lwork, rwork, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); + } + else + { + zggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["zg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, + F77_DBLE_CMPLX_ARG (tmp_dataA), m1, + F77_DBLE_CMPLX_ARG (tmp_dataB), p1, + alpha.fortran_vec (), beta.fortran_vec (), + F77_DBLE_CMPLX_ARG (u), nrow_u, + F77_DBLE_CMPLX_ARG (v), nrow_v, + F77_DBLE_CMPLX_ARG (q), nrow_q, + F77_DBLE_CMPLX_ARG (work), + rwork, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); } +} - template <> - void - gsvd::ggsvd (char& jobu, char& jobv, char& jobq, - F77_INT m, F77_INT n, F77_INT p, F77_INT& k, - F77_INT& l, Complex *tmp_dataA, F77_INT m1, - Complex *tmp_dataB, F77_INT p1, Matrix& alpha, - Matrix& beta, Complex *u, F77_INT nrow_u, - Complex *v, F77_INT nrow_v, Complex *q, - F77_INT nrow_q, Complex *work, - F77_INT lwork, F77_INT *iwork, F77_INT& info) +template <> +void +gsvd::ggsvd (char& jobu, char& jobv, char& jobq, + F77_INT m, F77_INT n, F77_INT p, + F77_INT& k, F77_INT& l, + FloatComplex *tmp_dataA, F77_INT m1, + FloatComplex *tmp_dataB, F77_INT p1, + FloatMatrix& alpha, FloatMatrix& beta, + FloatComplex *u, F77_INT nrow_u, + FloatComplex *v, F77_INT nrow_v, + FloatComplex *q, F77_INT nrow_q, + FloatComplex *work, F77_INT lwork, + F77_INT *iwork, F77_INT& info) +{ + if (! gsvd_initialized) + initialize_gsvd (); + + OCTAVE_LOCAL_BUFFER(float, rwork, 2*n); + + if (have_DGGSVD3) + { + cggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["cg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, + F77_CMPLX_ARG (tmp_dataA), m1, + F77_CMPLX_ARG (tmp_dataB), p1, + alpha.fortran_vec (), beta.fortran_vec (), + F77_CMPLX_ARG (u), nrow_u, + F77_CMPLX_ARG (v), nrow_v, + F77_CMPLX_ARG (q), nrow_q, + F77_CMPLX_ARG (work), lwork, + rwork, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); + } + else { - if (! gsvd_initialized) - initialize_gsvd (); + cggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["cg"]); + f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, + F77_CMPLX_ARG (tmp_dataA), m1, + F77_CMPLX_ARG (tmp_dataB), p1, + alpha.fortran_vec (), beta.fortran_vec (), + F77_CMPLX_ARG (u), nrow_u, + F77_CMPLX_ARG (v), nrow_v, + F77_CMPLX_ARG (q), nrow_q, + F77_CMPLX_ARG (work), + rwork, iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1)); + } +} - OCTAVE_LOCAL_BUFFER(double, rwork, 2*n); +template +T +gsvd::left_singular_matrix_A (void) const +{ + if (m_type == gsvd::Type::sigma_only) + (*current_liboctave_error_handler) + ("gsvd: U not computed because type == gsvd::sigma_only"); + + return m_left_smA; +} + +template +T +gsvd::left_singular_matrix_B (void) const +{ + if (m_type == gsvd::Type::sigma_only) + (*current_liboctave_error_handler) + ("gsvd: V not computed because type == gsvd::sigma_only"); + + return m_left_smB; +} + +template +T +gsvd::right_singular_matrix (void) const +{ + if (m_type == gsvd::Type::sigma_only) + (*current_liboctave_error_handler) + ("gsvd: X not computed because type == gsvd::sigma_only"); - if (have_DGGSVD3) - { - zggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["zg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, - F77_DBLE_CMPLX_ARG (tmp_dataA), m1, - F77_DBLE_CMPLX_ARG (tmp_dataB), p1, - alpha.fortran_vec (), beta.fortran_vec (), - F77_DBLE_CMPLX_ARG (u), nrow_u, - F77_DBLE_CMPLX_ARG (v), nrow_v, - F77_DBLE_CMPLX_ARG (q), nrow_q, - F77_DBLE_CMPLX_ARG (work), - lwork, rwork, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } - else - { - zggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["zg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, - F77_DBLE_CMPLX_ARG (tmp_dataA), m1, - F77_DBLE_CMPLX_ARG (tmp_dataB), p1, - alpha.fortran_vec (), beta.fortran_vec (), - F77_DBLE_CMPLX_ARG (u), nrow_u, - F77_DBLE_CMPLX_ARG (v), nrow_v, - F77_DBLE_CMPLX_ARG (q), nrow_q, - F77_DBLE_CMPLX_ARG (work), - rwork, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } + return m_right_sm; +} + +template +gsvd::gsvd (const T& a, const T& b, gsvd::Type gsvd_type) +{ + if (a.isempty () || b.isempty ()) + (*current_liboctave_error_handler) + ("gsvd: A and B cannot be empty matrices"); + + F77_INT info; + + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); + F77_INT p = to_f77_int (b.rows ()); + + T atmp = a; + P *tmp_dataA = atmp.fortran_vec (); + + T btmp = b; + P *tmp_dataB = btmp.fortran_vec (); + + char jobu = 'U'; + char jobv = 'V'; + char jobq = 'Q'; + + F77_INT nrow_u = m; + F77_INT nrow_v = p; + F77_INT nrow_q = n; + + F77_INT k, l; + + switch (gsvd_type) + { + case gsvd::Type::sigma_only: + + // FIXME: In LAPACK 3.0, problem below seems to be fixed, + // so we now set jobX = 'N'. + // + // For calculating sigma_only, both jobu and jobv should be 'N', but + // there seems to be a bug in dgesvd from LAPACK V2.0. To + // demonstrate the bug, set both jobu and jobv to 'N' and find the + // singular values of [eye(3), eye(3)]. The result is + // [-sqrt(2), -sqrt(2), -sqrt(2)]. + + jobu = jobv = jobq = 'N'; + nrow_u = nrow_v = nrow_q = 1; + break; + + default: + break; } - template <> - void - gsvd::ggsvd (char& jobu, char& jobv, char& jobq, - F77_INT m, F77_INT n, F77_INT p, - F77_INT& k, F77_INT& l, - FloatComplex *tmp_dataA, F77_INT m1, - FloatComplex *tmp_dataB, F77_INT p1, - FloatMatrix& alpha, FloatMatrix& beta, - FloatComplex *u, F77_INT nrow_u, - FloatComplex *v, F77_INT nrow_v, - FloatComplex *q, F77_INT nrow_q, - FloatComplex *work, F77_INT lwork, - F77_INT *iwork, F77_INT& info) - { - if (! gsvd_initialized) - initialize_gsvd (); + m_type = gsvd_type; - OCTAVE_LOCAL_BUFFER(float, rwork, 2*n); + if (jobu != 'N') + m_left_smA.resize (nrow_u, m); + + P *u = m_left_smA.fortran_vec (); - if (have_DGGSVD3) - { - cggsvd3_type f_ptr = reinterpret_cast (gsvd_fcn["cg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, - F77_CMPLX_ARG (tmp_dataA), m1, - F77_CMPLX_ARG (tmp_dataB), p1, - alpha.fortran_vec (), beta.fortran_vec (), - F77_CMPLX_ARG (u), nrow_u, - F77_CMPLX_ARG (v), nrow_v, - F77_CMPLX_ARG (q), nrow_q, - F77_CMPLX_ARG (work), lwork, - rwork, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } - else - { - cggsvd_type f_ptr = reinterpret_cast (gsvd_fcn["cg"]); - f_ptr (F77_CONST_CHAR_ARG2 (&jobu, 1), - F77_CONST_CHAR_ARG2 (&jobv, 1), - F77_CONST_CHAR_ARG2 (&jobq, 1), - m, n, p, k, l, - F77_CMPLX_ARG (tmp_dataA), m1, - F77_CMPLX_ARG (tmp_dataB), p1, - alpha.fortran_vec (), beta.fortran_vec (), - F77_CMPLX_ARG (u), nrow_u, - F77_CMPLX_ARG (v), nrow_v, - F77_CMPLX_ARG (q), nrow_q, - F77_CMPLX_ARG (work), - rwork, iwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1)); - } - } + if (jobv != 'N') + m_left_smB.resize (nrow_v, p); - template - T - gsvd::left_singular_matrix_A (void) const - { - if (m_type == gsvd::Type::sigma_only) - (*current_liboctave_error_handler) - ("gsvd: U not computed because type == gsvd::sigma_only"); - - return m_left_smA; - } + P *v = m_left_smB.fortran_vec (); - template - T - gsvd::left_singular_matrix_B (void) const - { - if (m_type == gsvd::Type::sigma_only) - (*current_liboctave_error_handler) - ("gsvd: V not computed because type == gsvd::sigma_only"); - - return m_left_smB; - } - - template - T - gsvd::right_singular_matrix (void) const - { - if (m_type == gsvd::Type::sigma_only) - (*current_liboctave_error_handler) - ("gsvd: X not computed because type == gsvd::sigma_only"); - - return m_right_sm; - } + if (jobq != 'N') + m_right_sm.resize (nrow_q, n); - template - gsvd::gsvd (const T& a, const T& b, gsvd::Type gsvd_type) - { - if (a.isempty () || b.isempty ()) - (*current_liboctave_error_handler) - ("gsvd: A and B cannot be empty matrices"); - - F77_INT info; - - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - F77_INT p = to_f77_int (b.rows ()); - - T atmp = a; - P *tmp_dataA = atmp.fortran_vec (); - - T btmp = b; - P *tmp_dataB = btmp.fortran_vec (); - - char jobu = 'U'; - char jobv = 'V'; - char jobq = 'Q'; + P *q = m_right_sm.fortran_vec (); - F77_INT nrow_u = m; - F77_INT nrow_v = p; - F77_INT nrow_q = n; - - F77_INT k, l; - - switch (gsvd_type) - { - case gsvd::Type::sigma_only: + real_matrix alpha (n, 1); + real_matrix beta (n, 1); - // FIXME: In LAPACK 3.0, problem below seems to be fixed, - // so we now set jobX = 'N'. - // - // For calculating sigma_only, both jobu and jobv should be 'N', but - // there seems to be a bug in dgesvd from LAPACK V2.0. To - // demonstrate the bug, set both jobu and jobv to 'N' and find the - // singular values of [eye(3), eye(3)]. The result is - // [-sqrt(2), -sqrt(2), -sqrt(2)]. - - jobu = jobv = jobq = 'N'; - nrow_u = nrow_v = nrow_q = 1; - break; + OCTAVE_LOCAL_BUFFER(F77_INT, iwork, n); - default: - break; - } - - m_type = gsvd_type; - - if (jobu != 'N') - m_left_smA.resize (nrow_u, m); - - P *u = m_left_smA.fortran_vec (); - - if (jobv != 'N') - m_left_smB.resize (nrow_v, p); - - P *v = m_left_smB.fortran_vec (); - - if (jobq != 'N') - m_right_sm.resize (nrow_q, n); - - P *q = m_right_sm.fortran_vec (); - - real_matrix alpha (n, 1); - real_matrix beta (n, 1); + if (! gsvd_initialized) + initialize_gsvd (); - OCTAVE_LOCAL_BUFFER(F77_INT, iwork, n); - - if (! gsvd_initialized) - initialize_gsvd (); - - F77_INT lwork; - if (have_DGGSVD3) - { - lwork = -1; - P work_tmp; - - gsvd::ggsvd (jobu, jobv, jobq, m, n, p, k, l, - tmp_dataA, m, tmp_dataB, p, - alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q, - &work_tmp, lwork, iwork, info); - - lwork = static_cast (std::abs (work_tmp)); - } - else - { - lwork = std::max ({3*n, m, p}) + n; - } - info = 0; - - OCTAVE_LOCAL_BUFFER(P, work, lwork); + F77_INT lwork; + if (have_DGGSVD3) + { + lwork = -1; + P work_tmp; gsvd::ggsvd (jobu, jobv, jobq, m, n, p, k, l, tmp_dataA, m, tmp_dataB, p, alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q, - work, lwork, iwork, info); + &work_tmp, lwork, iwork, info); - if (info < 0) - (*current_liboctave_error_handler) - ("*ggsvd.f: argument %" OCTAVE_F77_INT_TYPE_FORMAT " illegal", - -info); + lwork = static_cast (std::abs (work_tmp)); + } + else + { + lwork = std::max ({3*n, m, p}) + n; + } + info = 0; + + OCTAVE_LOCAL_BUFFER(P, work, lwork); + + gsvd::ggsvd (jobu, jobv, jobq, m, n, p, k, l, + tmp_dataA, m, tmp_dataB, p, + alpha, beta, u, nrow_u, v, nrow_v, q, nrow_q, + work, lwork, iwork, info); - if (info > 0) - (*current_liboctave_error_handler) - ("*ggsvd.f: Jacobi-type procedure failed to converge"); + if (info < 0) + (*current_liboctave_error_handler) + ("*ggsvd.f: argument %" OCTAVE_F77_INT_TYPE_FORMAT " illegal", + -info); + + if (info > 0) + (*current_liboctave_error_handler) + ("*ggsvd.f: Jacobi-type procedure failed to converge"); - F77_INT i, j; + F77_INT i, j; - if (gsvd_type != gsvd::Type::sigma_only) + if (gsvd_type != gsvd::Type::sigma_only) + { + // Size according to LAPACK is k+l,k+l, but this needs + // to be nxn for Matlab compatibility. + T R (n, n, 0.0); + int astart = n-k-l; + if (m - k - l >= 0) { - // Size according to LAPACK is k+l,k+l, but this needs - // to be nxn for Matlab compatibility. - T R (n, n, 0.0); - int astart = n-k-l; - if (m - k - l >= 0) - { - // R is stored in A(1:K+L,N-K-L+1:N) - for (i = 0; i < k+l; i++) - for (j = 0; j < k+l; j++) - R.xelem (i, j) = atmp.xelem (i, astart + j); - } - else - { - // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) - // ( 0 R22 R23 ) - for (i = 0; i < m; i++) - for (j = 0; j < k+l; j++) - R.xelem (i, j) = atmp.xelem (i, astart + j); - // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N) - for (i = m; i < k + l; i++) - for (j = n - l - k + m; j < n; j++) - R.xelem (i, j) = btmp.xelem (i - k, j); - } - - // Output X = Q*R' - // FIXME: Is there a way to call BLAS multiply directly - // with flags so that R is transposed? - m_right_sm = m_right_sm * R.hermitian (); - } - - // Fill in C and S - F77_INT rank; - bool fill_ptn; - if (m-k-l >= 0) - { - rank = l; - fill_ptn = true; + // R is stored in A(1:K+L,N-K-L+1:N) + for (i = 0; i < k+l; i++) + for (j = 0; j < k+l; j++) + R.xelem (i, j) = atmp.xelem (i, astart + j); } else { - rank = m-k; - fill_ptn = false; + // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N) + // ( 0 R22 R23 ) + for (i = 0; i < m; i++) + for (j = 0; j < k+l; j++) + R.xelem (i, j) = atmp.xelem (i, astart + j); + // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N) + for (i = m; i < k + l; i++) + for (j = n - l - k + m; j < n; j++) + R.xelem (i, j) = btmp.xelem (i - k, j); } - if (gsvd_type == gsvd::Type::sigma_only) + // Output X = Q*R' + // FIXME: Is there a way to call BLAS multiply directly + // with flags so that R is transposed? + m_right_sm = m_right_sm * R.hermitian (); + } + + // Fill in C and S + F77_INT rank; + bool fill_ptn; + if (m-k-l >= 0) + { + rank = l; + fill_ptn = true; + } + else + { + rank = m-k; + fill_ptn = false; + } + + if (gsvd_type == gsvd::Type::sigma_only) + { + // Return column vector with results + m_sigmaA.resize (k+l, 1); + m_sigmaB.resize (k+l, 1); + + if (fill_ptn) { - // Return column vector with results - m_sigmaA.resize (k+l, 1); - m_sigmaB.resize (k+l, 1); - - if (fill_ptn) + for (i = 0; i < k; i++) { - for (i = 0; i < k; i++) - { - m_sigmaA.xelem (i) = 1.0; - m_sigmaB.xelem (i) = 0.0; - } - for (i = k, j = k+l-1; i < k+l; i++, j--) - { - m_sigmaA.xelem (i) = alpha.xelem (i); - m_sigmaB.xelem (i) = beta.xelem (i); - } + m_sigmaA.xelem (i) = 1.0; + m_sigmaB.xelem (i) = 0.0; } - else + for (i = k, j = k+l-1; i < k+l; i++, j--) { - for (i = 0; i < k; i++) - { - m_sigmaA.xelem (i) = 1.0; - m_sigmaB.xelem (i) = 0.0; - } - for (i = k; i < m; i++) - { - m_sigmaA.xelem (i) = alpha.xelem (i); - m_sigmaB.xelem (i) = beta.xelem (i); - } - for (i = m; i < k+l; i++) - { - m_sigmaA.xelem (i) = 0.0; - m_sigmaB.xelem (i) = 1.0; - } + m_sigmaA.xelem (i) = alpha.xelem (i); + m_sigmaB.xelem (i) = beta.xelem (i); } } - else // returning all matrices + else { - // Number of columns according to LAPACK is k+l, but this needs - // to be n for Matlab compatibility. - m_sigmaA.resize (m, n); - m_sigmaB.resize (p, n); - for (i = 0; i < k; i++) - m_sigmaA.xelem (i, i) = 1.0; - - for (i = 0; i < rank; i++) { - m_sigmaA.xelem (k+i, k+i) = alpha.xelem (k+i); - m_sigmaB.xelem (i, k+i) = beta.xelem (k+i); + m_sigmaA.xelem (i) = 1.0; + m_sigmaB.xelem (i) = 0.0; } - - if (! fill_ptn) + for (i = k; i < m; i++) { - for (i = m; i < n; i++) - m_sigmaB.xelem (i-k, i) = 1.0; + m_sigmaA.xelem (i) = alpha.xelem (i); + m_sigmaB.xelem (i) = beta.xelem (i); } - + for (i = m; i < k+l; i++) + { + m_sigmaA.xelem (i) = 0.0; + m_sigmaB.xelem (i) = 1.0; + } } } + else // returning all matrices + { + // Number of columns according to LAPACK is k+l, but this needs + // to be n for Matlab compatibility. + m_sigmaA.resize (m, n); + m_sigmaB.resize (p, n); - // Instantiations needed in octave::math namespace. - template class gsvd; - template class gsvd; - template class gsvd; - template class gsvd; + for (i = 0; i < k; i++) + m_sigmaA.xelem (i, i) = 1.0; + + for (i = 0; i < rank; i++) + { + m_sigmaA.xelem (k+i, k+i) = alpha.xelem (k+i); + m_sigmaB.xelem (i, k+i) = beta.xelem (k+i); + } + + if (! fill_ptn) + { + for (i = m; i < n; i++) + m_sigmaB.xelem (i-k, i) = 1.0; + } + + } +} + +// Instantiations needed in octave::math namespace. +template class gsvd; +template class gsvd; +template class gsvd; +template class gsvd; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/gsvd.h --- a/liboctave/numeric/gsvd.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/gsvd.h Thu Dec 01 20:05:44 2022 -0800 @@ -32,84 +32,84 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - OCTAVE_API - gsvd - { - public: +template +class +OCTAVE_API +gsvd +{ +public: - enum class Type - { - std, - economy, - sigma_only - }; + enum class Type + { + std, + economy, + sigma_only + }; - gsvd (void) : m_sigmaA (), m_sigmaB (), m_left_smA (), m_left_smB (), m_right_sm () - { } - - gsvd (const T& a, const T& b, - gsvd::Type gsvd_type = gsvd::Type::std); + gsvd (void) : m_sigmaA (), m_sigmaB (), m_left_smA (), m_left_smB (), m_right_sm () + { } - gsvd (const gsvd& a) - : m_type (a.m_type), - m_sigmaA (a.m_sigmaA), m_sigmaB (a.m_sigmaB), - m_left_smA (a.m_left_smA), m_left_smB (a.m_left_smB), m_right_sm (a.m_right_sm) - { } + gsvd (const T& a, const T& b, + gsvd::Type gsvd_type = gsvd::Type::std); - gsvd& operator = (const gsvd& a) + gsvd (const gsvd& a) + : m_type (a.m_type), + m_sigmaA (a.m_sigmaA), m_sigmaB (a.m_sigmaB), + m_left_smA (a.m_left_smA), m_left_smB (a.m_left_smB), m_right_sm (a.m_right_sm) + { } + + gsvd& operator = (const gsvd& a) + { + if (this != &a) { - if (this != &a) - { - m_type = a.m_type; - m_sigmaA = a.m_sigmaA; - m_sigmaB = a.m_sigmaB; - m_left_smA = a.m_left_smA; - m_left_smB = a.m_left_smB; - m_right_sm = a.m_right_sm; - } - - return *this; + m_type = a.m_type; + m_sigmaA = a.m_sigmaA; + m_sigmaB = a.m_sigmaB; + m_left_smA = a.m_left_smA; + m_left_smB = a.m_left_smB; + m_right_sm = a.m_right_sm; } - ~gsvd (void) = default; + return *this; + } - typename T::real_matrix_type - singular_values_A (void) const { return m_sigmaA; } + ~gsvd (void) = default; - typename T::real_matrix_type - singular_values_B (void) const { return m_sigmaB; } + typename T::real_matrix_type + singular_values_A (void) const { return m_sigmaA; } - T left_singular_matrix_A (void) const; - T left_singular_matrix_B (void) const; + typename T::real_matrix_type + singular_values_B (void) const { return m_sigmaB; } + + T left_singular_matrix_A (void) const; + T left_singular_matrix_B (void) const; - T right_singular_matrix (void) const; + T right_singular_matrix (void) const; - private: - typedef typename T::value_type P; - typedef typename T::real_matrix_type real_matrix; +private: + typedef typename T::value_type P; + typedef typename T::real_matrix_type real_matrix; - void ggsvd (char& jobu, char& jobv, char& jobq, octave_f77_int_type m, - octave_f77_int_type n, octave_f77_int_type p, - octave_f77_int_type& k, octave_f77_int_type& l, - P *tmp_dataA, octave_f77_int_type m1, - P *tmp_dataB, octave_f77_int_type p1, - real_matrix& alpha, real_matrix& beta, - P *u, octave_f77_int_type nrow_u, - P *v, octave_f77_int_type nrow_v, - P *q, octave_f77_int_type nrow_q, - P *work, octave_f77_int_type lwork, - octave_f77_int_type *iwork, - octave_f77_int_type& info); + void ggsvd (char& jobu, char& jobv, char& jobq, octave_f77_int_type m, + octave_f77_int_type n, octave_f77_int_type p, + octave_f77_int_type& k, octave_f77_int_type& l, + P *tmp_dataA, octave_f77_int_type m1, + P *tmp_dataB, octave_f77_int_type p1, + real_matrix& alpha, real_matrix& beta, + P *u, octave_f77_int_type nrow_u, + P *v, octave_f77_int_type nrow_v, + P *q, octave_f77_int_type nrow_q, + P *work, octave_f77_int_type lwork, + octave_f77_int_type *iwork, + octave_f77_int_type& info); - //-------- + //-------- - gsvd::Type m_type; - real_matrix m_sigmaA, m_sigmaB; - T m_left_smA, m_left_smB; - T m_right_sm; - }; + gsvd::Type m_type; + real_matrix m_sigmaA, m_sigmaB; + T m_left_smA, m_left_smB; + T m_right_sm; +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/hess.cc --- a/liboctave/numeric/hess.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/hess.cc Thu Dec 01 20:05:44 2022 -0800 @@ -40,260 +40,260 @@ OCTAVE_BEGIN_NAMESPACE(math) - template <> - OCTAVE_API octave_idx_type - hess::init (const Matrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); +template <> +OCTAVE_API octave_idx_type +hess::init (const Matrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("hess: requires square matrix"); - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("hess: requires square matrix"); + char job = 'N'; + char side = 'R'; - char job = 'N'; - char side = 'R'; + F77_INT n = a_nc; + F77_INT lwork = 32 * n; + F77_INT info; + F77_INT ilo; + F77_INT ihi; + + m_hess_mat = a; + double *h = m_hess_mat.fortran_vec (); - F77_INT n = a_nc; - F77_INT lwork = 32 * n; - F77_INT info; - F77_INT ilo; - F77_INT ihi; + Array scale (dim_vector (n, 1)); + double *pscale = scale.fortran_vec (); + + F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, h, n, ilo, ihi, pscale, info + F77_CHAR_ARG_LEN (1))); + + Array tau (dim_vector (n-1, 1)); + double *ptau = tau.fortran_vec (); - m_hess_mat = a; - double *h = m_hess_mat.fortran_vec (); + Array work (dim_vector (lwork, 1)); + double *pwork = work.fortran_vec (); + + F77_XFCN (dgehrd, DGEHRD, (n, ilo, ihi, h, n, ptau, pwork, + lwork, info)); - Array scale (dim_vector (n, 1)); - double *pscale = scale.fortran_vec (); + m_unitary_hess_mat = m_hess_mat; + double *z = m_unitary_hess_mat.fortran_vec (); - F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, h, n, ilo, ihi, pscale, info - F77_CHAR_ARG_LEN (1))); + F77_XFCN (dorghr, DORGHR, (n, ilo, ihi, z, n, ptau, pwork, + lwork, info)); - Array tau (dim_vector (n-1, 1)); - double *ptau = tau.fortran_vec (); + F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, ilo, ihi, pscale, n, z, + n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - Array work (dim_vector (lwork, 1)); - double *pwork = work.fortran_vec (); + // If someone thinks of a more graceful way of doing + // this (or faster for that matter :-)), please let + // me know! - F77_XFCN (dgehrd, DGEHRD, (n, ilo, ihi, h, n, ptau, pwork, - lwork, info)); + if (n > 2) + for (F77_INT j = 0; j < a_nc; j++) + for (F77_INT i = j+2; i < a_nr; i++) + m_hess_mat.elem (i, j) = 0; - m_unitary_hess_mat = m_hess_mat; - double *z = m_unitary_hess_mat.fortran_vec (); + return info; +} - F77_XFCN (dorghr, DORGHR, (n, ilo, ihi, z, n, ptau, pwork, - lwork, info)); +template <> +OCTAVE_API octave_idx_type +hess::init (const FloatMatrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); - F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, ilo, ihi, pscale, n, z, - n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("hess: requires square matrix"); + + char job = 'N'; + char side = 'R'; + + F77_INT n = a_nc; + F77_INT lwork = 32 * n; + F77_INT info; + F77_INT ilo; + F77_INT ihi; - // If someone thinks of a more graceful way of doing - // this (or faster for that matter :-)), please let - // me know! + m_hess_mat = a; + float *h = m_hess_mat.fortran_vec (); + + Array scale (dim_vector (n, 1)); + float *pscale = scale.fortran_vec (); - if (n > 2) - for (F77_INT j = 0; j < a_nc; j++) - for (F77_INT i = j+2; i < a_nr; i++) - m_hess_mat.elem (i, j) = 0; + F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, h, n, ilo, ihi, pscale, info + F77_CHAR_ARG_LEN (1))); + + Array tau (dim_vector (n-1, 1)); + float *ptau = tau.fortran_vec (); + + Array work (dim_vector (lwork, 1)); + float *pwork = work.fortran_vec (); - return info; - } + F77_XFCN (sgehrd, SGEHRD, (n, ilo, ihi, h, n, ptau, pwork, + lwork, info)); + + m_unitary_hess_mat = m_hess_mat; + float *z = m_unitary_hess_mat.fortran_vec (); + + F77_XFCN (sorghr, SORGHR, (n, ilo, ihi, z, n, ptau, pwork, + lwork, info)); - template <> - OCTAVE_API octave_idx_type - hess::init (const FloatMatrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); + F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, ilo, ihi, pscale, n, z, + n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("hess: requires square matrix"); + // If someone thinks of a more graceful way of doing + // this (or faster for that matter :-)), please let + // me know! - char job = 'N'; - char side = 'R'; + if (n > 2) + for (F77_INT j = 0; j < a_nc; j++) + for (F77_INT i = j+2; i < a_nr; i++) + m_hess_mat.elem (i, j) = 0; - F77_INT n = a_nc; - F77_INT lwork = 32 * n; - F77_INT info; - F77_INT ilo; - F77_INT ihi; + return info; +} + +template <> +OCTAVE_API octave_idx_type +hess::init (const ComplexMatrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); - m_hess_mat = a; - float *h = m_hess_mat.fortran_vec (); + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("hess: requires square matrix"); + + char job = 'N'; + char side = 'R'; - Array scale (dim_vector (n, 1)); - float *pscale = scale.fortran_vec (); + F77_INT n = a_nc; + F77_INT lwork = 32 * n; + F77_INT info; + F77_INT ilo; + F77_INT ihi; - F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, h, n, ilo, ihi, pscale, info - F77_CHAR_ARG_LEN (1))); + m_hess_mat = a; + Complex *h = m_hess_mat.fortran_vec (); - Array tau (dim_vector (n-1, 1)); - float *ptau = tau.fortran_vec (); + Array scale (dim_vector (n, 1)); + double *pscale = scale.fortran_vec (); - Array work (dim_vector (lwork, 1)); - float *pwork = work.fortran_vec (); + F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, F77_DBLE_CMPLX_ARG (h), n, ilo, ihi, pscale, info + F77_CHAR_ARG_LEN (1))); + + Array tau (dim_vector (n-1, 1)); + Complex *ptau = tau.fortran_vec (); - F77_XFCN (sgehrd, SGEHRD, (n, ilo, ihi, h, n, ptau, pwork, - lwork, info)); + Array work (dim_vector (lwork, 1)); + Complex *pwork = work.fortran_vec (); + + F77_XFCN (zgehrd, ZGEHRD, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (h), n, + F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork), lwork, info)); - m_unitary_hess_mat = m_hess_mat; - float *z = m_unitary_hess_mat.fortran_vec (); + m_unitary_hess_mat = m_hess_mat; + Complex *z = m_unitary_hess_mat.fortran_vec (); - F77_XFCN (sorghr, SORGHR, (n, ilo, ihi, z, n, ptau, pwork, - lwork, info)); + F77_XFCN (zunghr, ZUNGHR, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (z), n, + F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork), + lwork, info)); - F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, ilo, ihi, pscale, n, z, - n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (zgebak, ZGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, ilo, ihi, pscale, n, F77_DBLE_CMPLX_ARG (z), n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + // If someone thinks of a more graceful way of + // doing this (or faster for that matter :-)), + // please let me know! + + if (n > 2) + for (F77_INT j = 0; j < a_nc; j++) + for (F77_INT i = j+2; i < a_nr; i++) + m_hess_mat.elem (i, j) = 0; - // If someone thinks of a more graceful way of doing - // this (or faster for that matter :-)), please let - // me know! + return info; +} - if (n > 2) - for (F77_INT j = 0; j < a_nc; j++) - for (F77_INT i = j+2; i < a_nr; i++) - m_hess_mat.elem (i, j) = 0; +template <> +OCTAVE_API octave_idx_type +hess::init (const FloatComplexMatrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); - return info; + if (a_nr != a_nc) + { + (*current_liboctave_error_handler) ("hess: requires square matrix"); + return -1; } - template <> - OCTAVE_API octave_idx_type - hess::init (const ComplexMatrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("hess: requires square matrix"); - - char job = 'N'; - char side = 'R'; + char job = 'N'; + char side = 'R'; - F77_INT n = a_nc; - F77_INT lwork = 32 * n; - F77_INT info; - F77_INT ilo; - F77_INT ihi; + F77_INT n = a_nc; + F77_INT lwork = 32 * n; + F77_INT info; + F77_INT ilo; + F77_INT ihi; - m_hess_mat = a; - Complex *h = m_hess_mat.fortran_vec (); - - Array scale (dim_vector (n, 1)); - double *pscale = scale.fortran_vec (); - - F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, F77_DBLE_CMPLX_ARG (h), n, ilo, ihi, pscale, info - F77_CHAR_ARG_LEN (1))); + m_hess_mat = a; + FloatComplex *h = m_hess_mat.fortran_vec (); - Array tau (dim_vector (n-1, 1)); - Complex *ptau = tau.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - Complex *pwork = work.fortran_vec (); - - F77_XFCN (zgehrd, ZGEHRD, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (h), n, - F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork), lwork, info)); - - m_unitary_hess_mat = m_hess_mat; - Complex *z = m_unitary_hess_mat.fortran_vec (); - - F77_XFCN (zunghr, ZUNGHR, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (z), n, - F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork), - lwork, info)); + Array scale (dim_vector (n, 1)); + float *pscale = scale.fortran_vec (); - F77_XFCN (zgebak, ZGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, ilo, ihi, pscale, n, F77_DBLE_CMPLX_ARG (z), n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), + n, F77_CMPLX_ARG (h), n, ilo, ihi, pscale, info + F77_CHAR_ARG_LEN (1))); - // If someone thinks of a more graceful way of - // doing this (or faster for that matter :-)), - // please let me know! + Array tau (dim_vector (n-1, 1)); + FloatComplex *ptau = tau.fortran_vec (); - if (n > 2) - for (F77_INT j = 0; j < a_nc; j++) - for (F77_INT i = j+2; i < a_nr; i++) - m_hess_mat.elem (i, j) = 0; - - return info; - } + Array work (dim_vector (lwork, 1)); + FloatComplex *pwork = work.fortran_vec (); - template <> - OCTAVE_API octave_idx_type - hess::init (const FloatComplexMatrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); - - if (a_nr != a_nc) - { - (*current_liboctave_error_handler) ("hess: requires square matrix"); - return -1; - } - - char job = 'N'; - char side = 'R'; + F77_XFCN (cgehrd, CGEHRD, (n, ilo, ihi, F77_CMPLX_ARG (h), n, + F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork), lwork, info)); - F77_INT n = a_nc; - F77_INT lwork = 32 * n; - F77_INT info; - F77_INT ilo; - F77_INT ihi; + m_unitary_hess_mat = m_hess_mat; + FloatComplex *z = m_unitary_hess_mat.fortran_vec (); - m_hess_mat = a; - FloatComplex *h = m_hess_mat.fortran_vec (); - - Array scale (dim_vector (n, 1)); - float *pscale = scale.fortran_vec (); - - F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1), - n, F77_CMPLX_ARG (h), n, ilo, ihi, pscale, info - F77_CHAR_ARG_LEN (1))); + F77_XFCN (cunghr, CUNGHR, (n, ilo, ihi, F77_CMPLX_ARG (z), n, + F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork), + lwork, info)); - Array tau (dim_vector (n-1, 1)); - FloatComplex *ptau = tau.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - FloatComplex *pwork = work.fortran_vec (); - - F77_XFCN (cgehrd, CGEHRD, (n, ilo, ihi, F77_CMPLX_ARG (h), n, - F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork), lwork, info)); - - m_unitary_hess_mat = m_hess_mat; - FloatComplex *z = m_unitary_hess_mat.fortran_vec (); - - F77_XFCN (cunghr, CUNGHR, (n, ilo, ihi, F77_CMPLX_ARG (z), n, - F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork), - lwork, info)); + F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), + F77_CONST_CHAR_ARG2 (&side, 1), + n, ilo, ihi, pscale, n, F77_CMPLX_ARG (z), n, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&job, 1), - F77_CONST_CHAR_ARG2 (&side, 1), - n, ilo, ihi, pscale, n, F77_CMPLX_ARG (z), n, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + // If someone thinks of a more graceful way of + // doing this (or faster for that matter :-)), + // please let me know! - // If someone thinks of a more graceful way of - // doing this (or faster for that matter :-)), - // please let me know! + if (n > 2) + for (F77_INT j = 0; j < a_nc; j++) + for (F77_INT i = j+2; i < a_nr; i++) + m_hess_mat.elem (i, j) = 0; - if (n > 2) - for (F77_INT j = 0; j < a_nc; j++) - for (F77_INT i = j+2; i < a_nr; i++) - m_hess_mat.elem (i, j) = 0; - - return info; - } + return info; +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/hess.h --- a/liboctave/numeric/hess.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/hess.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,60 +34,60 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - hess - { - public: +template +class +hess +{ +public: - hess (void) - : m_hess_mat (), m_unitary_hess_mat () - { } + hess (void) + : m_hess_mat (), m_unitary_hess_mat () + { } + + hess (const T& a) + : m_hess_mat (), m_unitary_hess_mat () + { + init (a); + } - hess (const T& a) - : m_hess_mat (), m_unitary_hess_mat () + hess (const T& a, octave_idx_type& info) + : m_hess_mat (), m_unitary_hess_mat () + { + info = init (a); + } + + hess (const hess& a) + : m_hess_mat (a.m_hess_mat), m_unitary_hess_mat (a.m_unitary_hess_mat) + { } + + hess& operator = (const hess& a) + { + if (this != &a) { - init (a); - } - - hess (const T& a, octave_idx_type& info) - : m_hess_mat (), m_unitary_hess_mat () - { - info = init (a); + m_hess_mat = a.m_hess_mat; + m_unitary_hess_mat = a.m_unitary_hess_mat; } - hess (const hess& a) - : m_hess_mat (a.m_hess_mat), m_unitary_hess_mat (a.m_unitary_hess_mat) - { } + return *this; + } - hess& operator = (const hess& a) - { - if (this != &a) - { - m_hess_mat = a.m_hess_mat; - m_unitary_hess_mat = a.m_unitary_hess_mat; - } + ~hess (void) = default; - return *this; - } + T hess_matrix (void) const { return m_hess_mat; } + + T unitary_hess_matrix (void) const { return m_unitary_hess_mat; } - ~hess (void) = default; - - T hess_matrix (void) const { return m_hess_mat; } +private: - T unitary_hess_matrix (void) const { return m_unitary_hess_mat; } - - private: + T m_hess_mat; + T m_unitary_hess_mat; - T m_hess_mat; - T m_unitary_hess_mat; + OCTAVE_API octave_idx_type init (const T& a); +}; - OCTAVE_API octave_idx_type init (const T& a); - }; - - template - extern OCTAVE_API std::ostream& - operator << (std::ostream& os, const hess& a); +template +extern OCTAVE_API std::ostream& +operator << (std::ostream& os, const hess& a); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/lo-mappers.cc --- a/liboctave/numeric/lo-mappers.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/lo-mappers.cc Thu Dec 01 20:05:44 2022 -0800 @@ -43,301 +43,301 @@ OCTAVE_BEGIN_NAMESPACE(math) - bool - isna (double x) - { - return lo_ieee_is_NA (x); - } +bool +isna (double x) +{ + return lo_ieee_is_NA (x); +} - bool - isna (const Complex& x) - { - return (isna (std::real (x)) || isna (std::imag (x))); - } +bool +isna (const Complex& x) +{ + return (isna (std::real (x)) || isna (std::imag (x))); +} - bool - isna (float x) - { - return lo_ieee_is_NA (x); - } +bool +isna (float x) +{ + return lo_ieee_is_NA (x); +} - bool - isna (const FloatComplex& x) - { - return (isna (std::real (x)) || isna (std::imag (x))); - } +bool +isna (const FloatComplex& x) +{ + return (isna (std::real (x)) || isna (std::imag (x))); +} - bool - is_NaN_or_NA (const Complex& x) - { - return (isnan (std::real (x)) || isnan (std::imag (x))); - } +bool +is_NaN_or_NA (const Complex& x) +{ + return (isnan (std::real (x)) || isnan (std::imag (x))); +} - bool - is_NaN_or_NA (const FloatComplex& x) - { - return (isnan (std::real (x)) || isnan (std::imag (x))); - } +bool +is_NaN_or_NA (const FloatComplex& x) +{ + return (isnan (std::real (x)) || isnan (std::imag (x))); +} - // Matlab returns a different phase for acos, asin then std library - // which requires a small function to remap the phase. - Complex - acos (const Complex& x) - { - Complex y = std::acos (x); +// Matlab returns a different phase for acos, asin then std library +// which requires a small function to remap the phase. +Complex +acos (const Complex& x) +{ + Complex y = std::acos (x); - if (std::imag (x) == 0.0 && std::real (x) > 1.0) - return std::conj (y); - else - return y; - } + if (std::imag (x) == 0.0 && std::real (x) > 1.0) + return std::conj (y); + else + return y; +} - FloatComplex - acos (const FloatComplex& x) - { - FloatComplex y = std::acos (x); +FloatComplex +acos (const FloatComplex& x) +{ + FloatComplex y = std::acos (x); - if (std::imag (x) == 0.0f && std::real (x) > 1.0f) - return std::conj (y); - else - return y; - } + if (std::imag (x) == 0.0f && std::real (x) > 1.0f) + return std::conj (y); + else + return y; +} - Complex - asin (const Complex& x) - { - Complex y = std::asin (x); +Complex +asin (const Complex& x) +{ + Complex y = std::asin (x); - if (std::imag (x) == 0.0 && std::real (x) > 1.0) - return std::conj (y); - else - return y; - } + if (std::imag (x) == 0.0 && std::real (x) > 1.0) + return std::conj (y); + else + return y; +} - FloatComplex - asin (const FloatComplex& x) - { - FloatComplex y = std::asin (x); +FloatComplex +asin (const FloatComplex& x) +{ + FloatComplex y = std::asin (x); - if (std::imag (x) == 0.0f && std::real (x) > 1.0f) - return std::conj (y); - else - return y; - } + if (std::imag (x) == 0.0f && std::real (x) > 1.0f) + return std::conj (y); + else + return y; +} - double frexp (double x, int *expptr) - { - return octave_frexp_wrapper (x, expptr); - } +double frexp (double x, int *expptr) +{ + return octave_frexp_wrapper (x, expptr); +} - float frexp (float x, int *expptr) - { - return octave_frexpf_wrapper (x, expptr); - } +float frexp (float x, int *expptr) +{ + return octave_frexpf_wrapper (x, expptr); +} - Complex - log2 (const Complex& x) - { - return std::log (x) / M_LN2; - } +Complex +log2 (const Complex& x) +{ + return std::log (x) / M_LN2; +} - FloatComplex - log2 (const FloatComplex& x) - { - return std::log (x) / static_cast (M_LN2); - } +FloatComplex +log2 (const FloatComplex& x) +{ + return std::log (x) / static_cast (M_LN2); +} - double - log2 (double x, int& exp) - { - return frexp (x, &exp); - } +double +log2 (double x, int& exp) +{ + return frexp (x, &exp); +} - float - log2 (float x, int& exp) - { - return frexp (x, &exp); - } +float +log2 (float x, int& exp) +{ + return frexp (x, &exp); +} - Complex - log2 (const Complex& x, int& exp) - { - double ax = std::abs (x); - double lax = log2 (ax, exp); - return (ax != lax) ? (x / ax) * lax : x; - } +Complex +log2 (const Complex& x, int& exp) +{ + double ax = std::abs (x); + double lax = log2 (ax, exp); + return (ax != lax) ? (x / ax) * lax : x; +} - FloatComplex - log2 (const FloatComplex& x, int& exp) - { - float ax = std::abs (x); - float lax = log2 (ax, exp); - return (ax != lax) ? (x / ax) * lax : x; - } +FloatComplex +log2 (const FloatComplex& x, int& exp) +{ + float ax = std::abs (x); + float lax = log2 (ax, exp); + return (ax != lax) ? (x / ax) * lax : x; +} - bool negative_sign (double x) { return __lo_ieee_signbit (x); } - bool negative_sign (float x) { return __lo_ieee_float_signbit (x); } +bool negative_sign (double x) { return __lo_ieee_signbit (x); } +bool negative_sign (float x) { return __lo_ieee_float_signbit (x); } - // Sometimes you need a large integer, but not always. +// Sometimes you need a large integer, but not always. - octave_idx_type - nint_big (double x) - { - static const double out_of_range_top - = static_cast(std::numeric_limits::max ())+1.; - if (x >= out_of_range_top) - return std::numeric_limits::max (); - else if (x < std::numeric_limits::min ()) - return std::numeric_limits::min (); - else - return static_cast ((x > 0.0) ? (x + 0.5) - : (x - 0.5)); - } +octave_idx_type +nint_big (double x) +{ + static const double out_of_range_top + = static_cast(std::numeric_limits::max ())+1.; + if (x >= out_of_range_top) + return std::numeric_limits::max (); + else if (x < std::numeric_limits::min ()) + return std::numeric_limits::min (); + else + return static_cast ((x > 0.0) ? (x + 0.5) + : (x - 0.5)); +} - octave_idx_type - nint_big (float x) - { - static const float out_of_range_top - = static_cast(std::numeric_limits::max ())+1.; - if (x >= out_of_range_top) - return std::numeric_limits::max (); - else if (x < std::numeric_limits::min ()) - return std::numeric_limits::min (); - else - return static_cast ((x > 0.0f) ? (x + 0.5f) - : (x - 0.5f)); - } +octave_idx_type +nint_big (float x) +{ + static const float out_of_range_top + = static_cast(std::numeric_limits::max ())+1.; + if (x >= out_of_range_top) + return std::numeric_limits::max (); + else if (x < std::numeric_limits::min ()) + return std::numeric_limits::min (); + else + return static_cast ((x > 0.0f) ? (x + 0.5f) + : (x - 0.5f)); +} - int - nint (double x) - { - if (x > std::numeric_limits::max ()) - return std::numeric_limits::max (); - else if (x < std::numeric_limits::min ()) - return std::numeric_limits::min (); - else - return static_cast ((x > 0.0) ? (x + 0.5) : (x - 0.5)); - } +int +nint (double x) +{ + if (x > std::numeric_limits::max ()) + return std::numeric_limits::max (); + else if (x < std::numeric_limits::min ()) + return std::numeric_limits::min (); + else + return static_cast ((x > 0.0) ? (x + 0.5) : (x - 0.5)); +} - int - nint (float x) - { - static const float out_of_range_top - = static_cast(std::numeric_limits::max ()) + 1.; - if (x >= out_of_range_top) - return std::numeric_limits::max (); - else if (x < std::numeric_limits::min ()) - return std::numeric_limits::min (); - else - return static_cast ((x > 0.0f) ? (x + 0.5f) : (x - 0.5f)); - } +int +nint (float x) +{ + static const float out_of_range_top + = static_cast(std::numeric_limits::max ()) + 1.; + if (x >= out_of_range_top) + return std::numeric_limits::max (); + else if (x < std::numeric_limits::min ()) + return std::numeric_limits::min (); + else + return static_cast ((x > 0.0f) ? (x + 0.5f) : (x - 0.5f)); +} - Complex - rc_acos (double x) - { - return fabs (x) > 1.0 ? acos (Complex (x)) : Complex (std::acos (x)); - } +Complex +rc_acos (double x) +{ + return fabs (x) > 1.0 ? acos (Complex (x)) : Complex (std::acos (x)); +} - FloatComplex - rc_acos (float x) - { - return fabsf (x) > 1.0f ? acos (FloatComplex (x)) - : FloatComplex (std::acos (x)); - } +FloatComplex +rc_acos (float x) +{ + return fabsf (x) > 1.0f ? acos (FloatComplex (x)) + : FloatComplex (std::acos (x)); +} - Complex - rc_acosh (double x) - { - return x < 1.0 ? acosh (Complex (x)) : Complex (acosh (x)); - } +Complex +rc_acosh (double x) +{ + return x < 1.0 ? acosh (Complex (x)) : Complex (acosh (x)); +} - FloatComplex - rc_acosh (float x) - { - return x < 1.0f ? acosh (FloatComplex (x)) : FloatComplex (acosh (x)); - } +FloatComplex +rc_acosh (float x) +{ + return x < 1.0f ? acosh (FloatComplex (x)) : FloatComplex (acosh (x)); +} - Complex - rc_asin (double x) - { - return fabs (x) > 1.0 ? asin (Complex (x)) : Complex (std::asin (x)); - } +Complex +rc_asin (double x) +{ + return fabs (x) > 1.0 ? asin (Complex (x)) : Complex (std::asin (x)); +} - FloatComplex - rc_asin (float x) - { - return fabsf (x) > 1.0f ? asin (FloatComplex (x)) - : FloatComplex (::asinf (x)); - } +FloatComplex +rc_asin (float x) +{ + return fabsf (x) > 1.0f ? asin (FloatComplex (x)) + : FloatComplex (::asinf (x)); +} - Complex - rc_atanh (double x) - { - return fabs (x) > 1.0 ? atanh (Complex (x)) : Complex (atanh (x)); - } +Complex +rc_atanh (double x) +{ + return fabs (x) > 1.0 ? atanh (Complex (x)) : Complex (atanh (x)); +} - FloatComplex - rc_atanh (float x) - { - return fabsf (x) > 1.0f ? atanh (FloatComplex (x)) - : FloatComplex (atanh (x)); - } +FloatComplex +rc_atanh (float x) +{ + return fabsf (x) > 1.0f ? atanh (FloatComplex (x)) + : FloatComplex (atanh (x)); +} - Complex - rc_log (double x) - { - return x < 0.0 ? Complex (std::log (-x), M_PI) : Complex (std::log (x)); - } +Complex +rc_log (double x) +{ + return x < 0.0 ? Complex (std::log (-x), M_PI) : Complex (std::log (x)); +} - FloatComplex - rc_log (float x) - { - return x < 0.0f ? FloatComplex (std::log (-x), static_cast (M_PI)) - : FloatComplex (std::log (x)); - } +FloatComplex +rc_log (float x) +{ + return x < 0.0f ? FloatComplex (std::log (-x), static_cast (M_PI)) + : FloatComplex (std::log (x)); +} - Complex - rc_log2 (double x) - { - constexpr double PI_LN2 = 4.53236014182719380962; // = pi / log(2) - return x < 0.0 ? Complex (log2 (-x), PI_LN2) : Complex (log2 (x)); - } +Complex +rc_log2 (double x) +{ + constexpr double PI_LN2 = 4.53236014182719380962; // = pi / log(2) + return x < 0.0 ? Complex (log2 (-x), PI_LN2) : Complex (log2 (x)); +} - FloatComplex - rc_log2 (float x) - { - constexpr float PI_LN2 = 4.53236014182719380962f; // = pi / log(2) - return x < 0.0f ? FloatComplex (log2 (-x), PI_LN2) - : FloatComplex (log2 (x)); - } +FloatComplex +rc_log2 (float x) +{ + constexpr float PI_LN2 = 4.53236014182719380962f; // = pi / log(2) + return x < 0.0f ? FloatComplex (log2 (-x), PI_LN2) + : FloatComplex (log2 (x)); +} - Complex - rc_log10 (double x) - { - constexpr double PI_LN10 = 1.36437635384184134748; // = pi / log(10) - return x < 0.0 ? Complex (log10 (-x), PI_LN10) : Complex (log10 (x)); - } +Complex +rc_log10 (double x) +{ + constexpr double PI_LN10 = 1.36437635384184134748; // = pi / log(10) + return x < 0.0 ? Complex (log10 (-x), PI_LN10) : Complex (log10 (x)); +} - FloatComplex - rc_log10 (float x) - { - constexpr float PI_LN10 = 1.36437635384184134748f; // = pi / log(10) - return x < 0.0f ? FloatComplex (log10 (-x), PI_LN10) - : FloatComplex (log10f (x)); - } +FloatComplex +rc_log10 (float x) +{ + constexpr float PI_LN10 = 1.36437635384184134748f; // = pi / log(10) + return x < 0.0f ? FloatComplex (log10 (-x), PI_LN10) + : FloatComplex (log10f (x)); +} - Complex - rc_sqrt (double x) - { - return x < 0.0 ? Complex (0.0, std::sqrt (-x)) : Complex (std::sqrt (x)); - } +Complex +rc_sqrt (double x) +{ + return x < 0.0 ? Complex (0.0, std::sqrt (-x)) : Complex (std::sqrt (x)); +} - FloatComplex - rc_sqrt (float x) - { - return x < 0.0f ? FloatComplex (0.0f, std::sqrt (-x)) - : FloatComplex (std::sqrt (x)); - } +FloatComplex +rc_sqrt (float x) +{ + return x < 0.0f ? FloatComplex (0.0f, std::sqrt (-x)) + : FloatComplex (std::sqrt (x)); +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/lo-mappers.h --- a/liboctave/numeric/lo-mappers.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/lo-mappers.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,427 +40,427 @@ OCTAVE_BEGIN_NAMESPACE(math) - extern OCTAVE_API bool isna (double x); - extern OCTAVE_API bool isna (float x); - extern OCTAVE_API bool isna (const Complex& x); - extern OCTAVE_API bool isna (const FloatComplex& x); +extern OCTAVE_API bool isna (double x); +extern OCTAVE_API bool isna (float x); +extern OCTAVE_API bool isna (const Complex& x); +extern OCTAVE_API bool isna (const FloatComplex& x); - extern OCTAVE_API bool is_NaN_or_NA (const Complex& x); - extern OCTAVE_API bool is_NaN_or_NA (const FloatComplex& x); +extern OCTAVE_API bool is_NaN_or_NA (const Complex& x); +extern OCTAVE_API bool is_NaN_or_NA (const FloatComplex& x); - inline double copysign (double x, double y) { return std::copysign (x, y); } - inline float copysign (float x, float y) { return std::copysignf (x, y); } +inline double copysign (double x, double y) { return std::copysign (x, y); } +inline float copysign (float x, float y) { return std::copysignf (x, y); } + +inline double signbit (double x) { return std::signbit (x); } +inline float signbit (float x) { return std::signbit (x); } - inline double signbit (double x) { return std::signbit (x); } - inline float signbit (float x) { return std::signbit (x); } +// Test for negative sign. +extern OCTAVE_API bool negative_sign (double x); +extern OCTAVE_API bool negative_sign (float x); + +// Test for positive sign. +inline bool positive_sign (double x) { return ! negative_sign (x); } +inline bool positive_sign (float x) { return ! negative_sign (x); } - // Test for negative sign. - extern OCTAVE_API bool negative_sign (double x); - extern OCTAVE_API bool negative_sign (float x); +extern OCTAVE_API Complex acos (const Complex& x); +extern OCTAVE_API FloatComplex acos (const FloatComplex& x); - // Test for positive sign. - inline bool positive_sign (double x) { return ! negative_sign (x); } - inline bool positive_sign (float x) { return ! negative_sign (x); } +extern OCTAVE_API Complex asin (const Complex& x); +extern OCTAVE_API FloatComplex asin (const FloatComplex& x); + +inline Complex atan (const Complex& x) { return std::atan (x); } +inline FloatComplex atan (const FloatComplex& x) { return std::atan (x); } - extern OCTAVE_API Complex acos (const Complex& x); - extern OCTAVE_API FloatComplex acos (const FloatComplex& x); +// The C++ standard would normally return a std::complex value for conj +// even when the input is fully real. Octave overrides this. +inline double conj (double x) { return x; } +inline float conj (float x) { return x; } - extern OCTAVE_API Complex asin (const Complex& x); - extern OCTAVE_API FloatComplex asin (const FloatComplex& x); +template +std::complex +conj (const std::complex& x) +{ + return std::conj (x); +} - inline Complex atan (const Complex& x) { return std::atan (x); } - inline FloatComplex atan (const FloatComplex& x) { return std::atan (x); } +inline double log2 (double x) { return std::log2 (x); } +inline float log2 (float x) { return std::log2f (x); } - // The C++ standard would normally return a std::complex value for conj - // even when the input is fully real. Octave overrides this. - inline double conj (double x) { return x; } - inline float conj (float x) { return x; } +extern OCTAVE_API Complex log2 (const Complex& x); +extern OCTAVE_API FloatComplex log2 (const FloatComplex& x); + +extern OCTAVE_API double log2 (double x, int& exp); +extern OCTAVE_API float log2 (float x, int& exp); + +extern OCTAVE_API Complex log2 (const Complex& x, int& exp); +extern OCTAVE_API FloatComplex log2 (const FloatComplex& x, int& exp); - template - std::complex - conj (const std::complex& x) - { - return std::conj (x); - } +inline double exp2 (double x) { return std::exp2 (x); } +inline float exp2 (float x) { return std::exp2f (x); } - inline double log2 (double x) { return std::log2 (x); } - inline float log2 (float x) { return std::log2f (x); } - - extern OCTAVE_API Complex log2 (const Complex& x); - extern OCTAVE_API FloatComplex log2 (const FloatComplex& x); +template +std::complex +ceil (const std::complex& x) +{ + return std::complex (std::ceil (std::real (x)), + std::ceil (std::imag (x))); +} - extern OCTAVE_API double log2 (double x, int& exp); - extern OCTAVE_API float log2 (float x, int& exp); +template +std::complex +trunc (const std::complex& x) +{ + return std::complex (std::trunc (std::real (x)), + std::trunc (std::imag (x))); +} - extern OCTAVE_API Complex log2 (const Complex& x, int& exp); - extern OCTAVE_API FloatComplex log2 (const FloatComplex& x, int& exp); - - inline double exp2 (double x) { return std::exp2 (x); } - inline float exp2 (float x) { return std::exp2f (x); } +// Provide alias for trunc under the more familiar name of fix. +inline double fix (double x) { return std::trunc (x); } +inline float fix (float x) { return std::trunc (x); } - template - std::complex - ceil (const std::complex& x) - { - return std::complex (std::ceil (std::real (x)), - std::ceil (std::imag (x))); - } +template +std::complex +fix (const std::complex& x) +{ + return trunc (x); +} - template - std::complex - trunc (const std::complex& x) - { - return std::complex (std::trunc (std::real (x)), - std::trunc (std::imag (x))); - } +template +std::complex +floor (const std::complex& x) +{ + return std::complex (std::floor (std::real (x)), + std::floor (std::imag (x))); +} + +inline double round (double x) { return std::round (x); } +inline float round (float x) { return std::roundf (x); } - // Provide alias for trunc under the more familiar name of fix. - inline double fix (double x) { return std::trunc (x); } - inline float fix (float x) { return std::trunc (x); } +template +std::complex +round (const std::complex& x) +{ + return std::complex (round (std::real (x)), round (std::imag (x))); +} - template - std::complex - fix (const std::complex& x) - { - return trunc (x); - } +inline double +roundb (double x) +{ + double t = round (x); + + if (fabs (x - t) == 0.5) + t = 2 * std::trunc (0.5 * t); + + return t; +} - template - std::complex - floor (const std::complex& x) - { - return std::complex (std::floor (std::real (x)), - std::floor (std::imag (x))); - } +inline float +roundb (float x) +{ + float t = round (x); + + if (fabsf (x - t) == 0.5f) + t = 2 * std::trunc (0.5f * t); - inline double round (double x) { return std::round (x); } - inline float round (float x) { return std::roundf (x); } + return t; +} - template - std::complex - round (const std::complex& x) - { - return std::complex (round (std::real (x)), round (std::imag (x))); - } +template +std::complex +roundb (const std::complex& x) +{ + return std::complex (roundb (std::real (x)), roundb (std::imag (x))); +} + +extern OCTAVE_API double frexp (double x, int *expptr); +extern OCTAVE_API float frexp (float x, int *expptr); - inline double - roundb (double x) - { - double t = round (x); +inline bool isnan (bool) { return false; } +inline bool isnan (char) { return false; } + +inline bool isnan (double x) { return std::isnan (x); } +inline bool isnan (float x) { return std::isnan (x); } - if (fabs (x - t) == 0.5) - t = 2 * std::trunc (0.5 * t); - - return t; - } +// FIXME: Do we need the isnan overload for complex? +template +bool +isnan (const std::complex& x) +{ + return (isnan (std::real (x)) || isnan (std::imag (x))); +} - inline float - roundb (float x) - { - float t = round (x); +inline bool isfinite (double x) { return std::isfinite (x); } +inline bool isfinite (float x) { return std::isfinite (x); } - if (fabsf (x - t) == 0.5f) - t = 2 * std::trunc (0.5f * t); +// FIXME: Do we need isfinite overload for complex? +template +bool +isfinite (const std::complex& x) +{ + return (isfinite (std::real (x)) && isfinite (std::imag (x))); +} - return t; - } +inline bool isinf (double x) { return std::isinf (x); } +inline bool isinf (float x) { return std::isinf (x); } - template - std::complex - roundb (const std::complex& x) - { - return std::complex (roundb (std::real (x)), roundb (std::imag (x))); - } +template +bool +isinf (const octave_int&) +{ + return false; +} - extern OCTAVE_API double frexp (double x, int *expptr); - extern OCTAVE_API float frexp (float x, int *expptr); +// FIXME: Do we need isinf overload for complex? +template +bool +isinf (const std::complex& x) +{ + return (isinf (std::real (x)) || isinf (std::imag (x))); +} - inline bool isnan (bool) { return false; } - inline bool isnan (char) { return false; } +// Some useful tests, that are commonly repeated. +// Test for a finite integer. - inline bool isnan (double x) { return std::isnan (x); } - inline bool isnan (float x) { return std::isnan (x); } +// FIXME: Benchmark whether trunc might be faster than round here. +inline bool isinteger (double x) { return isfinite (x) && x == round (x); } +inline bool isinteger (float x) { return isfinite (x) && x == round (x); } + +inline double +signum (double x) +{ + double tmp = 0.0; - // FIXME: Do we need the isnan overload for complex? - template - bool - isnan (const std::complex& x) - { - return (isnan (std::real (x)) || isnan (std::imag (x))); - } + if (x < 0.0) + tmp = -1.0; + else if (x > 0.0) + tmp = 1.0; - inline bool isfinite (double x) { return std::isfinite (x); } - inline bool isfinite (float x) { return std::isfinite (x); } + return isnan (x) ? numeric_limits::NaN () : tmp; +} + +inline float +signum (float x) +{ + float tmp = 0.0f; - // FIXME: Do we need isfinite overload for complex? - template - bool - isfinite (const std::complex& x) - { - return (isfinite (std::real (x)) && isfinite (std::imag (x))); - } + if (x < 0.0f) + tmp = -1.0f; + else if (x > 0.0f) + tmp = 1.0f; + + return isnan (x) ? numeric_limits::NaN () : tmp; +} - inline bool isinf (double x) { return std::isinf (x); } - inline bool isinf (float x) { return std::isinf (x); } +template +std::complex +signum (const std::complex& x) +{ + T tmp = abs (x); + + return tmp == 0 ? 0.0 : x / tmp; +} - template - bool - isinf (const octave_int&) - { - return false; - } +// Convert X to the nearest integer value. Should not pass NaN to +// this function. - // FIXME: Do we need isinf overload for complex? - template - bool - isinf (const std::complex& x) - { - return (isinf (std::real (x)) || isinf (std::imag (x))); - } +// For integer types? Hmm. Need to be sure T is an integer type... +template +T +x_nint (T x) +{ + return x; +} - // Some useful tests, that are commonly repeated. - // Test for a finite integer. +template <> +inline double x_nint (double x) +{ + return (isfinite (x) ? std::floor (x + 0.5) : x); +} - // FIXME: Benchmark whether trunc might be faster than round here. - inline bool isinteger (double x) { return isfinite (x) && x == round (x); } - inline bool isinteger (float x) { return isfinite (x) && x == round (x); } +template <> +inline float x_nint (float x) +{ + return (isfinite (x) ? std::floor (x + 0.5f) : x); +} + +extern OCTAVE_API octave_idx_type nint_big (double x); +extern OCTAVE_API octave_idx_type nint_big (float x); - inline double - signum (double x) - { - double tmp = 0.0; +extern OCTAVE_API int nint (double x); +extern OCTAVE_API int nint (float x); - if (x < 0.0) - tmp = -1.0; - else if (x > 0.0) - tmp = 1.0; +template +T +mod (T x, T y) +{ + T retval; - return isnan (x) ? numeric_limits::NaN () : tmp; - } - - inline float - signum (float x) + if (y == 0) + retval = x; + else { - float tmp = 0.0f; + T q = x / y; - if (x < 0.0f) - tmp = -1.0f; - else if (x > 0.0f) - tmp = 1.0f; + if (x_nint (y) != y + && (std::abs ((q - x_nint (q)) / x_nint (q)) + < std::numeric_limits::epsilon ())) + retval = 0; + else + { + T n = std::floor (q); - return isnan (x) ? numeric_limits::NaN () : tmp; + // Prevent use of extra precision. + volatile T tmp = y * n; + + retval = x - tmp; + } } - template - std::complex - signum (const std::complex& x) - { - T tmp = abs (x); + if (x != y && y != 0) + retval = copysign (retval, y); - return tmp == 0 ? 0.0 : x / tmp; - } + return retval; +} - // Convert X to the nearest integer value. Should not pass NaN to - // this function. +template +T +rem (T x, T y) +{ + T retval; - // For integer types? Hmm. Need to be sure T is an integer type... - template - T - x_nint (T x) - { - return x; - } - - template <> - inline double x_nint (double x) + if (y == 0) + retval = numeric_limits::NaN (); + else { - return (isfinite (x) ? std::floor (x + 0.5) : x); - } - - template <> - inline float x_nint (float x) - { - return (isfinite (x) ? std::floor (x + 0.5f) : x); - } - - extern OCTAVE_API octave_idx_type nint_big (double x); - extern OCTAVE_API octave_idx_type nint_big (float x); + T q = x / y; - extern OCTAVE_API int nint (double x); - extern OCTAVE_API int nint (float x); - - template - T - mod (T x, T y) - { - T retval; - - if (y == 0) - retval = x; + if (x_nint (y) != y + && (std::abs ((q - x_nint (q)) / x_nint (q)) + < std::numeric_limits::epsilon ())) + retval = 0; else { - T q = x / y; - - if (x_nint (y) != y - && (std::abs ((q - x_nint (q)) / x_nint (q)) - < std::numeric_limits::epsilon ())) - retval = 0; - else - { - T n = std::floor (q); - - // Prevent use of extra precision. - volatile T tmp = y * n; - - retval = x - tmp; - } - } - - if (x != y && y != 0) - retval = copysign (retval, y); - - return retval; - } + T n = std::trunc (q); - template - T - rem (T x, T y) - { - T retval; - - if (y == 0) - retval = numeric_limits::NaN (); - else - { - T q = x / y; + // Prevent use of extra precision. + volatile T tmp = y * n; - if (x_nint (y) != y - && (std::abs ((q - x_nint (q)) / x_nint (q)) - < std::numeric_limits::epsilon ())) - retval = 0; - else - { - T n = std::trunc (q); - - // Prevent use of extra precision. - volatile T tmp = y * n; - - retval = x - tmp; - } + retval = x - tmp; } - - if (x != y && y != 0) - retval = copysign (retval, x); - - return retval; } - // Generic min, max definitions - template - T - min (T x, T y) - { - return x <= y ? x : y; - } + if (x != y && y != 0) + retval = copysign (retval, x); + + return retval; +} - template - T - max (T x, T y) - { - return x >= y ? x : y; - } +// Generic min, max definitions +template +T +min (T x, T y) +{ + return x <= y ? x : y; +} - // This form is favorable. GCC will translate (x <= y ? x : y) without a - // jump, hence the only conditional jump involved will be the first - // (isnan), infrequent and hence friendly to branch prediction. +template +T +max (T x, T y) +{ + return x >= y ? x : y; +} + +// This form is favorable. GCC will translate (x <= y ? x : y) without a +// jump, hence the only conditional jump involved will be the first +// (isnan), infrequent and hence friendly to branch prediction. - inline double - min (double x, double y) - { - return isnan (y) ? x : (x <= y ? x : y); - } +inline double +min (double x, double y) +{ + return isnan (y) ? x : (x <= y ? x : y); +} - inline double - max (double x, double y) - { - return isnan (y) ? x : (x >= y ? x : y); - } +inline double +max (double x, double y) +{ + return isnan (y) ? x : (x >= y ? x : y); +} - inline float - min (float x, float y) - { - return isnan (y) ? x : (x <= y ? x : y); - } +inline float +min (float x, float y) +{ + return isnan (y) ? x : (x <= y ? x : y); +} - inline float - max (float x, float y) - { - return isnan (y) ? x : (x >= y ? x : y); - } +inline float +max (float x, float y) +{ + return isnan (y) ? x : (x >= y ? x : y); +} - inline std::complex - min (const std::complex& x, const std::complex& y) - { - return abs (x) <= abs (y) ? x : (isnan (x) ? x : y); - } +inline std::complex +min (const std::complex& x, const std::complex& y) +{ + return abs (x) <= abs (y) ? x : (isnan (x) ? x : y); +} - inline std::complex - min (const std::complex& x, const std::complex& y) - { - return abs (x) <= abs (y) ? x : (isnan (x) ? x : y); - } +inline std::complex +min (const std::complex& x, const std::complex& y) +{ + return abs (x) <= abs (y) ? x : (isnan (x) ? x : y); +} - inline std::complex - max (const std::complex& x, const std::complex& y) - { - return abs (x) >= abs (y) ? x : (isnan (x) ? x : y); - } +inline std::complex +max (const std::complex& x, const std::complex& y) +{ + return abs (x) >= abs (y) ? x : (isnan (x) ? x : y); +} - inline std::complex - max (const std::complex& x, const std::complex& y) - { - return abs (x) >= abs (y) ? x : (isnan (x) ? x : y); - } +inline std::complex +max (const std::complex& x, const std::complex& y) +{ + return abs (x) >= abs (y) ? x : (isnan (x) ? x : y); +} - template - inline octave_int - min (const octave_int& x, const octave_int& y) - { - return xmin (x, y); - } +template +inline octave_int +min (const octave_int& x, const octave_int& y) +{ + return xmin (x, y); +} - template - inline octave_int - max (const octave_int& x, const octave_int& y) - { - return xmax (x, y); - } +template +inline octave_int +max (const octave_int& x, const octave_int& y) +{ + return xmax (x, y); +} - // These map reals to Complex. +// These map reals to Complex. - extern OCTAVE_API Complex rc_acos (double); - extern OCTAVE_API FloatComplex rc_acos (float); +extern OCTAVE_API Complex rc_acos (double); +extern OCTAVE_API FloatComplex rc_acos (float); - extern OCTAVE_API Complex rc_acosh (double); - extern OCTAVE_API FloatComplex rc_acosh (float); +extern OCTAVE_API Complex rc_acosh (double); +extern OCTAVE_API FloatComplex rc_acosh (float); - extern OCTAVE_API Complex rc_asin (double); - extern OCTAVE_API FloatComplex rc_asin (float); +extern OCTAVE_API Complex rc_asin (double); +extern OCTAVE_API FloatComplex rc_asin (float); - extern OCTAVE_API Complex rc_atanh (double); - extern OCTAVE_API FloatComplex rc_atanh (float); +extern OCTAVE_API Complex rc_atanh (double); +extern OCTAVE_API FloatComplex rc_atanh (float); - extern OCTAVE_API Complex rc_log (double); - extern OCTAVE_API FloatComplex rc_log (float); +extern OCTAVE_API Complex rc_log (double); +extern OCTAVE_API FloatComplex rc_log (float); - extern OCTAVE_API Complex rc_log2 (double); - extern OCTAVE_API FloatComplex rc_log2 (float); +extern OCTAVE_API Complex rc_log2 (double); +extern OCTAVE_API FloatComplex rc_log2 (float); - extern OCTAVE_API Complex rc_log10 (double); - extern OCTAVE_API FloatComplex rc_log10 (float); +extern OCTAVE_API Complex rc_log10 (double); +extern OCTAVE_API FloatComplex rc_log10 (float); - extern OCTAVE_API Complex rc_sqrt (double); - extern OCTAVE_API FloatComplex rc_sqrt (float); +extern OCTAVE_API Complex rc_sqrt (double); +extern OCTAVE_API FloatComplex rc_sqrt (float); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/lo-specfun.cc --- a/liboctave/numeric/lo-specfun.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/lo-specfun.cc Thu Dec 01 20:05:44 2022 -0800 @@ -59,658 +59,658 @@ OCTAVE_BEGIN_NAMESPACE(math) - static inline Complex - bessel_return_value (const Complex& val, octave_idx_type ierr) +static inline Complex +bessel_return_value (const Complex& val, octave_idx_type ierr) +{ + static const Complex inf_val + = Complex (numeric_limits::Inf (), + numeric_limits::Inf ()); + + static const Complex nan_val + = Complex (numeric_limits::NaN (), + numeric_limits::NaN ()); + + Complex retval; + + switch (ierr) { - static const Complex inf_val - = Complex (numeric_limits::Inf (), - numeric_limits::Inf ()); + case 0: + case 3: + case 4: + retval = val; + break; - static const Complex nan_val - = Complex (numeric_limits::NaN (), - numeric_limits::NaN ()); + case 2: + retval = inf_val; + break; - Complex retval; + default: + retval = nan_val; + break; + } - switch (ierr) - { - case 0: - case 3: - case 4: - retval = val; - break; + return retval; +} + +static inline FloatComplex +bessel_return_value (const FloatComplex& val, octave_idx_type ierr) +{ + static const FloatComplex inf_val + = FloatComplex (numeric_limits::Inf (), + numeric_limits::Inf ()); + + static const FloatComplex nan_val + = FloatComplex (numeric_limits::NaN (), + numeric_limits::NaN ()); + + FloatComplex retval; - case 2: - retval = inf_val; - break; + switch (ierr) + { + case 0: + case 3: + case 4: + retval = val; + break; - default: - retval = nan_val; - break; - } + case 2: + retval = inf_val; + break; - return retval; + default: + retval = nan_val; + break; } - static inline FloatComplex - bessel_return_value (const FloatComplex& val, octave_idx_type ierr) - { - static const FloatComplex inf_val - = FloatComplex (numeric_limits::Inf (), - numeric_limits::Inf ()); + return retval; +} + +Complex +airy (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr) +{ + double ar = 0.0; + double ai = 0.0; + + double zr = z.real (); + double zi = z.imag (); + + F77_INT id = (deriv ? 1 : 0); + F77_INT nz, t_ierr; + F77_INT sc = (scaled ? 2 : 1); + + F77_FUNC (zairy, ZAIRY) (zr, zi, id, sc, ar, ai, nz, t_ierr); + + ierr = t_ierr; + + if (zi == 0.0 && (! scaled || zr >= 0.0)) + ai = 0.0; + + return bessel_return_value (Complex (ar, ai), ierr); +} + +ComplexMatrix +airy (const ComplexMatrix& z, bool deriv, bool scaled, + Array& ierr) +{ + octave_idx_type nr = z.rows (); + octave_idx_type nc = z.cols (); + + ComplexMatrix retval (nr, nc); + + ierr.resize (dim_vector (nr, nc)); - static const FloatComplex nan_val - = FloatComplex (numeric_limits::NaN (), - numeric_limits::NaN ()); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = airy (z(i, j), deriv, scaled, ierr(i, j)); + + return retval; +} + +ComplexNDArray +airy (const ComplexNDArray& z, bool deriv, bool scaled, + Array& ierr) +{ + dim_vector dv = z.dims (); + octave_idx_type nel = dv.numel (); + ComplexNDArray retval (dv); + + ierr.resize (dv); - FloatComplex retval; + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = airy (z(i), deriv, scaled, ierr(i)); + + return retval; +} + +FloatComplex +airy (const FloatComplex& z, bool deriv, bool scaled, + octave_idx_type& ierr) +{ + FloatComplex a; + + F77_INT id = (deriv ? 1 : 0); + F77_INT nz, t_ierr; + F77_INT sc = (scaled ? 2 : 1); + + F77_FUNC (cairy, CAIRY) (F77_CONST_CMPLX_ARG (&z), id, sc, + F77_CMPLX_ARG (&a), nz, t_ierr); + + ierr = t_ierr; - switch (ierr) - { - case 0: - case 3: - case 4: - retval = val; - break; + float ar = a.real (); + float ai = a.imag (); + + if (z.imag () == 0.0 && (! scaled || z.real () >= 0.0)) + ai = 0.0; + + return bessel_return_value (FloatComplex (ar, ai), ierr); +} + +FloatComplexMatrix +airy (const FloatComplexMatrix& z, bool deriv, bool scaled, + Array& ierr) +{ + octave_idx_type nr = z.rows (); + octave_idx_type nc = z.cols (); + + FloatComplexMatrix retval (nr, nc); - case 2: - retval = inf_val; - break; + ierr.resize (dim_vector (nr, nc)); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = airy (z(i, j), deriv, scaled, ierr(i, j)); + + return retval; +} + +FloatComplexNDArray +airy (const FloatComplexNDArray& z, bool deriv, bool scaled, + Array& ierr) +{ + dim_vector dv = z.dims (); + octave_idx_type nel = dv.numel (); + FloatComplexNDArray retval (dv); + + ierr.resize (dv); - default: - retval = nan_val; - break; - } + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = airy (z(i), deriv, scaled, ierr(i)); + + return retval; +} + +static inline bool +is_integer_value (double x) +{ + return x == static_cast (static_cast (x)); +} + +static inline Complex +zbesj (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + +static inline Complex +zbesy (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + +static inline Complex +zbesi (const Complex& z, double alpha, int kode, octave_idx_type& ierr); - return retval; - } +static inline Complex +zbesk (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + +static inline Complex +zbesh1 (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + +static inline Complex +zbesh2 (const Complex& z, double alpha, int kode, octave_idx_type& ierr); - Complex - airy (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr) +static inline Complex +zbesj (const Complex& z, double alpha, int kode, octave_idx_type& ierr) +{ + Complex retval; + + if (alpha >= 0.0) { - double ar = 0.0; - double ai = 0.0; + double yr = 0.0; + double yi = 0.0; + + F77_INT nz, t_ierr; double zr = z.real (); double zi = z.imag (); - F77_INT id = (deriv ? 1 : 0); - F77_INT nz, t_ierr; - F77_INT sc = (scaled ? 2 : 1); - - F77_FUNC (zairy, ZAIRY) (zr, zi, id, sc, ar, ai, nz, t_ierr); - - ierr = t_ierr; - - if (zi == 0.0 && (! scaled || zr >= 0.0)) - ai = 0.0; - - return bessel_return_value (Complex (ar, ai), ierr); - } - - ComplexMatrix - airy (const ComplexMatrix& z, bool deriv, bool scaled, - Array& ierr) - { - octave_idx_type nr = z.rows (); - octave_idx_type nc = z.cols (); - - ComplexMatrix retval (nr, nc); - - ierr.resize (dim_vector (nr, nc)); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = airy (z(i, j), deriv, scaled, ierr(i, j)); - - return retval; - } - - ComplexNDArray - airy (const ComplexNDArray& z, bool deriv, bool scaled, - Array& ierr) - { - dim_vector dv = z.dims (); - octave_idx_type nel = dv.numel (); - ComplexNDArray retval (dv); - - ierr.resize (dv); - - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = airy (z(i), deriv, scaled, ierr(i)); - - return retval; - } - - FloatComplex - airy (const FloatComplex& z, bool deriv, bool scaled, - octave_idx_type& ierr) - { - FloatComplex a; - - F77_INT id = (deriv ? 1 : 0); - F77_INT nz, t_ierr; - F77_INT sc = (scaled ? 2 : 1); - - F77_FUNC (cairy, CAIRY) (F77_CONST_CMPLX_ARG (&z), id, sc, - F77_CMPLX_ARG (&a), nz, t_ierr); + F77_FUNC (zbesj, ZBESJ) (zr, zi, alpha, kode, 1, &yr, &yi, nz, t_ierr); ierr = t_ierr; - float ar = a.real (); - float ai = a.imag (); - - if (z.imag () == 0.0 && (! scaled || z.real () >= 0.0)) - ai = 0.0; + if (zi == 0.0 && zr >= 0.0) + yi = 0.0; - return bessel_return_value (FloatComplex (ar, ai), ierr); + retval = bessel_return_value (Complex (yr, yi), ierr); } - - FloatComplexMatrix - airy (const FloatComplexMatrix& z, bool deriv, bool scaled, - Array& ierr) + else if (is_integer_value (alpha)) { - octave_idx_type nr = z.rows (); - octave_idx_type nc = z.cols (); - - FloatComplexMatrix retval (nr, nc); + // zbesy can overflow as z->0, and cause troubles for generic case below + alpha = -alpha; + Complex tmp = zbesj (z, alpha, kode, ierr); + if ((static_cast (alpha)) & 1) + tmp = - tmp; + retval = bessel_return_value (tmp, ierr); + } + else + { + alpha = -alpha; - ierr.resize (dim_vector (nr, nc)); + Complex tmp = cos (M_PI * alpha) * zbesj (z, alpha, kode, ierr); + + if (ierr == 0 || ierr == 3) + { + tmp -= sin (M_PI * alpha) * zbesy (z, alpha, kode, ierr); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = airy (z(i, j), deriv, scaled, ierr(i, j)); - - return retval; + retval = bessel_return_value (tmp, ierr); + } + else + retval = Complex (numeric_limits::NaN (), + numeric_limits::NaN ()); } - FloatComplexNDArray - airy (const FloatComplexNDArray& z, bool deriv, bool scaled, - Array& ierr) - { - dim_vector dv = z.dims (); - octave_idx_type nel = dv.numel (); - FloatComplexNDArray retval (dv); - - ierr.resize (dv); - - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = airy (z(i), deriv, scaled, ierr(i)); + return retval; +} - return retval; - } +static inline Complex +zbesy (const Complex& z, double alpha, int kode, octave_idx_type& ierr) +{ + Complex retval; - static inline bool - is_integer_value (double x) + if (alpha >= 0.0) { - return x == static_cast (static_cast (x)); - } + double yr = 0.0; + double yi = 0.0; - static inline Complex - zbesj (const Complex& z, double alpha, int kode, octave_idx_type& ierr); - - static inline Complex - zbesy (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + F77_INT nz, t_ierr; - static inline Complex - zbesi (const Complex& z, double alpha, int kode, octave_idx_type& ierr); - - static inline Complex - zbesk (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + double wr, wi; - static inline Complex - zbesh1 (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + double zr = z.real (); + double zi = z.imag (); - static inline Complex - zbesh2 (const Complex& z, double alpha, int kode, octave_idx_type& ierr); + ierr = 0; - static inline Complex - zbesj (const Complex& z, double alpha, int kode, octave_idx_type& ierr) - { - Complex retval; - - if (alpha >= 0.0) + if (zr == 0.0 && zi == 0.0) { - double yr = 0.0; - double yi = 0.0; - - F77_INT nz, t_ierr; - - double zr = z.real (); - double zi = z.imag (); - - F77_FUNC (zbesj, ZBESJ) (zr, zi, alpha, kode, 1, &yr, &yi, nz, t_ierr); + yr = -numeric_limits::Inf (); + yi = 0.0; + } + else + { + F77_FUNC (zbesy, ZBESY) (zr, zi, alpha, kode, 1, &yr, &yi, nz, + &wr, &wi, t_ierr); ierr = t_ierr; if (zi == 0.0 && zr >= 0.0) yi = 0.0; + } - retval = bessel_return_value (Complex (yr, yi), ierr); - } - else if (is_integer_value (alpha)) + return bessel_return_value (Complex (yr, yi), ierr); + } + else if (is_integer_value (alpha - 0.5)) + { + // zbesy can overflow as z->0, and cause troubles for generic case below + alpha = -alpha; + Complex tmp = zbesj (z, alpha, kode, ierr); + if ((static_cast (alpha - 0.5)) & 1) + tmp = - tmp; + retval = bessel_return_value (tmp, ierr); + } + else + { + alpha = -alpha; + + Complex tmp = cos (M_PI * alpha) * zbesy (z, alpha, kode, ierr); + + if (ierr == 0 || ierr == 3) { - // zbesy can overflow as z->0, and cause troubles for generic case below - alpha = -alpha; - Complex tmp = zbesj (z, alpha, kode, ierr); - if ((static_cast (alpha)) & 1) - tmp = - tmp; + tmp += sin (M_PI * alpha) * zbesj (z, alpha, kode, ierr); + retval = bessel_return_value (tmp, ierr); } else + retval = Complex (numeric_limits::NaN (), + numeric_limits::NaN ()); + } + + return retval; +} + +static inline Complex +zbesi (const Complex& z, double alpha, int kode, octave_idx_type& ierr) +{ + Complex retval; + + if (alpha >= 0.0) + { + double yr = 0.0; + double yi = 0.0; + + F77_INT nz, t_ierr; + + double zr = z.real (); + double zi = z.imag (); + + F77_FUNC (zbesi, ZBESI) (zr, zi, alpha, kode, 1, &yr, &yi, nz, t_ierr); + + ierr = t_ierr; + + if (zi == 0.0 && zr >= 0.0) + yi = 0.0; + + retval = bessel_return_value (Complex (yr, yi), ierr); + } + else if (is_integer_value (alpha)) + { + // zbesi can overflow as z->0, and cause troubles for generic case below + alpha = -alpha; + Complex tmp = zbesi (z, alpha, kode, ierr); + retval = bessel_return_value (tmp, ierr); + } + else + { + alpha = -alpha; + + Complex tmp = zbesi (z, alpha, kode, ierr); + + if (ierr == 0 || ierr == 3) + { + Complex tmp2 = (2.0 / M_PI) * sin (M_PI * alpha) + * zbesk (z, alpha, kode, ierr); + + if (kode == 2) + { + // Compensate for different scaling factor of besk. + tmp2 *= exp (-z - std::abs (z.real ())); + } + + tmp += tmp2; + + retval = bessel_return_value (tmp, ierr); + } + else + retval = Complex (numeric_limits::NaN (), + numeric_limits::NaN ()); + } + + return retval; +} + +static inline Complex +zbesk (const Complex& z, double alpha, int kode, octave_idx_type& ierr) +{ + Complex retval; + + if (alpha >= 0.0) + { + double yr = 0.0; + double yi = 0.0; + + F77_INT nz, t_ierr; + + double zr = z.real (); + double zi = z.imag (); + + ierr = 0; + + if (zr == 0.0 && zi == 0.0) + { + yr = numeric_limits::Inf (); + yi = 0.0; + } + else { - alpha = -alpha; - - Complex tmp = cos (M_PI * alpha) * zbesj (z, alpha, kode, ierr); - - if (ierr == 0 || ierr == 3) - { - tmp -= sin (M_PI * alpha) * zbesy (z, alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); - } - else - retval = Complex (numeric_limits::NaN (), - numeric_limits::NaN ()); - } - - return retval; - } - - static inline Complex - zbesy (const Complex& z, double alpha, int kode, octave_idx_type& ierr) - { - Complex retval; - - if (alpha >= 0.0) - { - double yr = 0.0; - double yi = 0.0; - - F77_INT nz, t_ierr; - - double wr, wi; - - double zr = z.real (); - double zi = z.imag (); - - ierr = 0; - - if (zr == 0.0 && zi == 0.0) - { - yr = -numeric_limits::Inf (); - yi = 0.0; - } - else - { - F77_FUNC (zbesy, ZBESY) (zr, zi, alpha, kode, 1, &yr, &yi, nz, - &wr, &wi, t_ierr); - - ierr = t_ierr; - - if (zi == 0.0 && zr >= 0.0) - yi = 0.0; - } - - return bessel_return_value (Complex (yr, yi), ierr); - } - else if (is_integer_value (alpha - 0.5)) - { - // zbesy can overflow as z->0, and cause troubles for generic case below - alpha = -alpha; - Complex tmp = zbesj (z, alpha, kode, ierr); - if ((static_cast (alpha - 0.5)) & 1) - tmp = - tmp; - retval = bessel_return_value (tmp, ierr); - } - else - { - alpha = -alpha; - - Complex tmp = cos (M_PI * alpha) * zbesy (z, alpha, kode, ierr); - - if (ierr == 0 || ierr == 3) - { - tmp += sin (M_PI * alpha) * zbesj (z, alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); - } - else - retval = Complex (numeric_limits::NaN (), - numeric_limits::NaN ()); - } - - return retval; - } - - static inline Complex - zbesi (const Complex& z, double alpha, int kode, octave_idx_type& ierr) - { - Complex retval; - - if (alpha >= 0.0) - { - double yr = 0.0; - double yi = 0.0; - - F77_INT nz, t_ierr; - - double zr = z.real (); - double zi = z.imag (); - - F77_FUNC (zbesi, ZBESI) (zr, zi, alpha, kode, 1, &yr, &yi, nz, t_ierr); + F77_FUNC (zbesk, ZBESK) (zr, zi, alpha, kode, 1, &yr, &yi, nz, + t_ierr); ierr = t_ierr; if (zi == 0.0 && zr >= 0.0) yi = 0.0; - - retval = bessel_return_value (Complex (yr, yi), ierr); - } - else if (is_integer_value (alpha)) - { - // zbesi can overflow as z->0, and cause troubles for generic case below - alpha = -alpha; - Complex tmp = zbesi (z, alpha, kode, ierr); - retval = bessel_return_value (tmp, ierr); - } - else - { - alpha = -alpha; - - Complex tmp = zbesi (z, alpha, kode, ierr); - - if (ierr == 0 || ierr == 3) - { - Complex tmp2 = (2.0 / M_PI) * sin (M_PI * alpha) - * zbesk (z, alpha, kode, ierr); - - if (kode == 2) - { - // Compensate for different scaling factor of besk. - tmp2 *= exp (-z - std::abs (z.real ())); - } - - tmp += tmp2; - - retval = bessel_return_value (tmp, ierr); - } - else - retval = Complex (numeric_limits::NaN (), - numeric_limits::NaN ()); - } - - return retval; - } - - static inline Complex - zbesk (const Complex& z, double alpha, int kode, octave_idx_type& ierr) - { - Complex retval; - - if (alpha >= 0.0) - { - double yr = 0.0; - double yi = 0.0; - - F77_INT nz, t_ierr; - - double zr = z.real (); - double zi = z.imag (); - - ierr = 0; - - if (zr == 0.0 && zi == 0.0) - { - yr = numeric_limits::Inf (); - yi = 0.0; - } - else - { - F77_FUNC (zbesk, ZBESK) (zr, zi, alpha, kode, 1, &yr, &yi, nz, - t_ierr); - - ierr = t_ierr; - - if (zi == 0.0 && zr >= 0.0) - yi = 0.0; - } - - retval = bessel_return_value (Complex (yr, yi), ierr); - } - else - { - Complex tmp = zbesk (z, -alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); - } - - return retval; - } - - static inline Complex - zbesh1 (const Complex& z, double alpha, int kode, octave_idx_type& ierr) - { - Complex retval; - - if (alpha >= 0.0) - { - double yr = 0.0; - double yi = 0.0; - - F77_INT nz, t_ierr; - - double zr = z.real (); - double zi = z.imag (); - - F77_FUNC (zbesh, ZBESH) (zr, zi, alpha, kode, 1, 1, &yr, &yi, nz, - t_ierr); - - ierr = t_ierr; - - retval = bessel_return_value (Complex (yr, yi), ierr); - } - else - { - alpha = -alpha; - - static const Complex eye = Complex (0.0, 1.0); - - Complex tmp = exp (M_PI * alpha * eye) * zbesh1 (z, alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); - } - - return retval; - } - - static inline Complex - zbesh2 (const Complex& z, double alpha, int kode, octave_idx_type& ierr) - { - Complex retval; - - if (alpha >= 0.0) - { - double yr = 0.0; - double yi = 0.0; - - F77_INT nz, t_ierr; - - double zr = z.real (); - double zi = z.imag (); - - F77_FUNC (zbesh, ZBESH) (zr, zi, alpha, kode, 2, 1, &yr, &yi, nz, - t_ierr); - - ierr = t_ierr; - - retval = bessel_return_value (Complex (yr, yi), ierr); - } - else - { - alpha = -alpha; - - static const Complex eye = Complex (0.0, 1.0); - - Complex tmp = exp (-M_PI * alpha * eye) * zbesh2 (z, alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); } - return retval; + retval = bessel_return_value (Complex (yr, yi), ierr); } - - typedef Complex (*dptr) (const Complex&, double, int, octave_idx_type&); + else + { + Complex tmp = zbesk (z, -alpha, kode, ierr); - static inline Complex - do_bessel (dptr f, const char *, double alpha, const Complex& x, - bool scaled, octave_idx_type& ierr) - { - Complex retval; - - retval = f (x, alpha, (scaled ? 2 : 1), ierr); - - return retval; + retval = bessel_return_value (tmp, ierr); } - static inline ComplexMatrix - do_bessel (dptr f, const char *, double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr) + return retval; +} + +static inline Complex +zbesh1 (const Complex& z, double alpha, int kode, octave_idx_type& ierr) +{ + Complex retval; + + if (alpha >= 0.0) { - octave_idx_type nr = x.rows (); - octave_idx_type nc = x.cols (); + double yr = 0.0; + double yi = 0.0; + + F77_INT nz, t_ierr; - ComplexMatrix retval (nr, nc); + double zr = z.real (); + double zi = z.imag (); - ierr.resize (dim_vector (nr, nc)); + F77_FUNC (zbesh, ZBESH) (zr, zi, alpha, kode, 1, 1, &yr, &yi, nz, + t_ierr); + + ierr = t_ierr; - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x(i, j), alpha, (scaled ? 2 : 1), ierr(i, j)); + retval = bessel_return_value (Complex (yr, yi), ierr); + } + else + { + alpha = -alpha; - return retval; + static const Complex eye = Complex (0.0, 1.0); + + Complex tmp = exp (M_PI * alpha * eye) * zbesh1 (z, alpha, kode, ierr); + + retval = bessel_return_value (tmp, ierr); } - static inline ComplexMatrix - do_bessel (dptr f, const char *, const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr) + return retval; +} + +static inline Complex +zbesh2 (const Complex& z, double alpha, int kode, octave_idx_type& ierr) +{ + Complex retval; + + if (alpha >= 0.0) { - octave_idx_type nr = alpha.rows (); - octave_idx_type nc = alpha.cols (); + double yr = 0.0; + double yi = 0.0; + + F77_INT nz, t_ierr; - ComplexMatrix retval (nr, nc); + double zr = z.real (); + double zi = z.imag (); - ierr.resize (dim_vector (nr, nc)); + F77_FUNC (zbesh, ZBESH) (zr, zi, alpha, kode, 2, 1, &yr, &yi, nz, + t_ierr); + + ierr = t_ierr; - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x, alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); + retval = bessel_return_value (Complex (yr, yi), ierr); + } + else + { + alpha = -alpha; - return retval; + static const Complex eye = Complex (0.0, 1.0); + + Complex tmp = exp (-M_PI * alpha * eye) * zbesh2 (z, alpha, kode, ierr); + + retval = bessel_return_value (tmp, ierr); } - static inline ComplexMatrix - do_bessel (dptr f, const char *fn, const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr) - { - ComplexMatrix retval; + return retval; +} + +typedef Complex (*dptr) (const Complex&, double, int, octave_idx_type&); - octave_idx_type x_nr = x.rows (); - octave_idx_type x_nc = x.cols (); +static inline Complex +do_bessel (dptr f, const char *, double alpha, const Complex& x, + bool scaled, octave_idx_type& ierr) +{ + Complex retval; + + retval = f (x, alpha, (scaled ? 2 : 1), ierr); + + return retval; +} - octave_idx_type alpha_nr = alpha.rows (); - octave_idx_type alpha_nc = alpha.cols (); +static inline ComplexMatrix +do_bessel (dptr f, const char *, double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr) +{ + octave_idx_type nr = x.rows (); + octave_idx_type nc = x.cols (); - if (x_nr != alpha_nr || x_nc != alpha_nc) - (*current_liboctave_error_handler) - ("%s: the sizes of alpha and x must conform", fn); + ComplexMatrix retval (nr, nc); - octave_idx_type nr = x_nr; - octave_idx_type nc = x_nc; + ierr.resize (dim_vector (nr, nc)); - retval.resize (nr, nc); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x(i, j), alpha, (scaled ? 2 : 1), ierr(i, j)); - ierr.resize (dim_vector (nr, nc)); + return retval; +} - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x(i, j), alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); +static inline ComplexMatrix +do_bessel (dptr f, const char *, const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr) +{ + octave_idx_type nr = alpha.rows (); + octave_idx_type nc = alpha.cols (); + + ComplexMatrix retval (nr, nc); - return retval; - } + ierr.resize (dim_vector (nr, nc)); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x, alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); + + return retval; +} - static inline ComplexNDArray - do_bessel (dptr f, const char *, double alpha, const ComplexNDArray& x, - bool scaled, Array& ierr) - { - dim_vector dv = x.dims (); - octave_idx_type nel = dv.numel (); - ComplexNDArray retval (dv); +static inline ComplexMatrix +do_bessel (dptr f, const char *fn, const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr) +{ + ComplexMatrix retval; + + octave_idx_type x_nr = x.rows (); + octave_idx_type x_nc = x.cols (); - ierr.resize (dv); + octave_idx_type alpha_nr = alpha.rows (); + octave_idx_type alpha_nc = alpha.cols (); + + if (x_nr != alpha_nr || x_nc != alpha_nc) + (*current_liboctave_error_handler) + ("%s: the sizes of alpha and x must conform", fn); - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = f (x(i), alpha, (scaled ? 2 : 1), ierr(i)); + octave_idx_type nr = x_nr; + octave_idx_type nc = x_nc; - return retval; - } + retval.resize (nr, nc); + + ierr.resize (dim_vector (nr, nc)); - static inline ComplexNDArray - do_bessel (dptr f, const char *, const NDArray& alpha, const Complex& x, - bool scaled, Array& ierr) - { - dim_vector dv = alpha.dims (); - octave_idx_type nel = dv.numel (); - ComplexNDArray retval (dv); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x(i, j), alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); + + return retval; +} - ierr.resize (dv); +static inline ComplexNDArray +do_bessel (dptr f, const char *, double alpha, const ComplexNDArray& x, + bool scaled, Array& ierr) +{ + dim_vector dv = x.dims (); + octave_idx_type nel = dv.numel (); + ComplexNDArray retval (dv); - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = f (x, alpha(i), (scaled ? 2 : 1), ierr(i)); + ierr.resize (dv); - return retval; - } + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = f (x(i), alpha, (scaled ? 2 : 1), ierr(i)); + + return retval; +} - static inline ComplexNDArray - do_bessel (dptr f, const char *fn, const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr) - { - dim_vector dv = x.dims (); - ComplexNDArray retval; +static inline ComplexNDArray +do_bessel (dptr f, const char *, const NDArray& alpha, const Complex& x, + bool scaled, Array& ierr) +{ + dim_vector dv = alpha.dims (); + octave_idx_type nel = dv.numel (); + ComplexNDArray retval (dv); - if (dv != alpha.dims ()) - (*current_liboctave_error_handler) - ("%s: the sizes of alpha and x must conform", fn); + ierr.resize (dv); + + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = f (x, alpha(i), (scaled ? 2 : 1), ierr(i)); + + return retval; +} - octave_idx_type nel = dv.numel (); - - retval.resize (dv); - ierr.resize (dv); +static inline ComplexNDArray +do_bessel (dptr f, const char *fn, const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr) +{ + dim_vector dv = x.dims (); + ComplexNDArray retval; - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = f (x(i), alpha(i), (scaled ? 2 : 1), ierr(i)); + if (dv != alpha.dims ()) + (*current_liboctave_error_handler) + ("%s: the sizes of alpha and x must conform", fn); + + octave_idx_type nel = dv.numel (); - return retval; - } + retval.resize (dv); + ierr.resize (dv); + + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = f (x(i), alpha(i), (scaled ? 2 : 1), ierr(i)); - static inline ComplexMatrix - do_bessel (dptr f, const char *, const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, - Array& ierr) - { - octave_idx_type nr = x.numel (); - octave_idx_type nc = alpha.numel (); + return retval; +} + +static inline ComplexMatrix +do_bessel (dptr f, const char *, const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, + Array& ierr) +{ + octave_idx_type nr = x.numel (); + octave_idx_type nc = alpha.numel (); - ComplexMatrix retval (nr, nc); + ComplexMatrix retval (nr, nc); - ierr.resize (dim_vector (nr, nc)); + ierr.resize (dim_vector (nr, nc)); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x(i), alpha(j), (scaled ? 2 : 1), ierr(i, j)); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x(i), alpha(j), (scaled ? 2 : 1), ierr(i, j)); - return retval; - } + return retval; +} #define SS_BESSEL(name, fcn) \ Complex \ @@ -785,12 +785,12 @@ NN_BESSEL (name, fcn) \ RC_BESSEL (name, fcn) - ALL_BESSEL (besselj, zbesj) - ALL_BESSEL (bessely, zbesy) - ALL_BESSEL (besseli, zbesi) - ALL_BESSEL (besselk, zbesk) - ALL_BESSEL (besselh1, zbesh1) - ALL_BESSEL (besselh2, zbesh2) +ALL_BESSEL (besselj, zbesj) +ALL_BESSEL (bessely, zbesy) +ALL_BESSEL (besseli, zbesi) +ALL_BESSEL (besselk, zbesk) +ALL_BESSEL (besselh1, zbesh1) +ALL_BESSEL (besselh2, zbesh2) #undef ALL_BESSEL #undef SS_BESSEL @@ -802,458 +802,458 @@ #undef NN_BESSEL #undef RC_BESSEL - static inline FloatComplex - cbesj (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); +static inline FloatComplex +cbesj (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + +static inline FloatComplex +cbesy (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + +static inline FloatComplex +cbesi (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + +static inline FloatComplex +cbesk (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + +static inline FloatComplex +cbesh1 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); - static inline FloatComplex - cbesy (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); +static inline FloatComplex +cbesh2 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + +static inline bool +is_integer_value (float x) +{ + return x == static_cast (static_cast (x)); +} - static inline FloatComplex - cbesi (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); +static inline FloatComplex +cbesj (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) +{ + FloatComplex retval; + + if (alpha >= 0.0) + { + FloatComplex y = 0.0; + + F77_INT nz, t_ierr; - static inline FloatComplex - cbesk (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + F77_FUNC (cbesj, CBESJ) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, + F77_CMPLX_ARG (&y), nz, t_ierr); - static inline FloatComplex - cbesh1 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + ierr = t_ierr; + + if (z.imag () == 0.0 && z.real () >= 0.0) + y = FloatComplex (y.real (), 0.0); - static inline FloatComplex - cbesh2 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr); + retval = bessel_return_value (y, ierr); + } + else if (is_integer_value (alpha)) + { + // zbesy can overflow as z->0, and cause troubles for generic case below + alpha = -alpha; + FloatComplex tmp = cbesj (z, alpha, kode, ierr); + if ((static_cast (alpha)) & 1) + tmp = - tmp; + retval = bessel_return_value (tmp, ierr); + } + else + { + alpha = -alpha; - static inline bool - is_integer_value (float x) - { - return x == static_cast (static_cast (x)); + FloatComplex tmp = cosf (static_cast (M_PI) * alpha) + * cbesj (z, alpha, kode, ierr); + + if (ierr == 0 || ierr == 3) + { + tmp -= sinf (static_cast (M_PI) * alpha) + * cbesy (z, alpha, kode, ierr); + + retval = bessel_return_value (tmp, ierr); + } + else + retval = FloatComplex (numeric_limits::NaN (), + numeric_limits::NaN ()); } - static inline FloatComplex - cbesj (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) + return retval; +} + +static inline FloatComplex +cbesy (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) +{ + FloatComplex retval; + + if (alpha >= 0.0) { - FloatComplex retval; + FloatComplex y = 0.0; + + F77_INT nz, t_ierr; - if (alpha >= 0.0) + FloatComplex w; + + ierr = 0; + + if (z.real () == 0.0 && z.imag () == 0.0) { - FloatComplex y = 0.0; - - F77_INT nz, t_ierr; - - F77_FUNC (cbesj, CBESJ) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, - F77_CMPLX_ARG (&y), nz, t_ierr); + y = FloatComplex (-numeric_limits::Inf (), 0.0); + } + else + { + F77_FUNC (cbesy, CBESY) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, + F77_CMPLX_ARG (&y), nz, + F77_CMPLX_ARG (&w), t_ierr); ierr = t_ierr; if (z.imag () == 0.0 && z.real () >= 0.0) y = FloatComplex (y.real (), 0.0); + } - retval = bessel_return_value (y, ierr); - } - else if (is_integer_value (alpha)) + return bessel_return_value (y, ierr); + } + else if (is_integer_value (alpha - 0.5)) + { + // zbesy can overflow as z->0, and cause troubles for generic case below + alpha = -alpha; + FloatComplex tmp = cbesj (z, alpha, kode, ierr); + if ((static_cast (alpha - 0.5)) & 1) + tmp = - tmp; + retval = bessel_return_value (tmp, ierr); + } + else + { + alpha = -alpha; + + FloatComplex tmp = cosf (static_cast (M_PI) * alpha) + * cbesy (z, alpha, kode, ierr); + + if (ierr == 0 || ierr == 3) { - // zbesy can overflow as z->0, and cause troubles for generic case below - alpha = -alpha; - FloatComplex tmp = cbesj (z, alpha, kode, ierr); - if ((static_cast (alpha)) & 1) - tmp = - tmp; + tmp += sinf (static_cast (M_PI) * alpha) + * cbesj (z, alpha, kode, ierr); + retval = bessel_return_value (tmp, ierr); } else + retval = FloatComplex (numeric_limits::NaN (), + numeric_limits::NaN ()); + } + + return retval; +} + +static inline FloatComplex +cbesi (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) +{ + FloatComplex retval; + + if (alpha >= 0.0) + { + FloatComplex y = 0.0; + + F77_INT nz, t_ierr; + + F77_FUNC (cbesi, CBESI) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, + F77_CMPLX_ARG (&y), nz, t_ierr); + + ierr = t_ierr; + + if (z.imag () == 0.0 && z.real () >= 0.0) + y = FloatComplex (y.real (), 0.0); + + retval = bessel_return_value (y, ierr); + } + else + { + alpha = -alpha; + + FloatComplex tmp = cbesi (z, alpha, kode, ierr); + + if (ierr == 0 || ierr == 3) + { + FloatComplex tmp2 = static_cast (2.0 / M_PI) + * sinf (static_cast (M_PI) * alpha) + * cbesk (z, alpha, kode, ierr); + + if (kode == 2) + { + // Compensate for different scaling factor of besk. + tmp2 *= exp (-z - std::abs (z.real ())); + } + + tmp += tmp2; + + retval = bessel_return_value (tmp, ierr); + } + else + retval = FloatComplex (numeric_limits::NaN (), + numeric_limits::NaN ()); + } + + return retval; +} + +static inline FloatComplex +cbesk (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) +{ + FloatComplex retval; + + if (alpha >= 0.0) + { + FloatComplex y = 0.0; + + F77_INT nz, t_ierr; + + ierr = 0; + + if (z.real () == 0.0 && z.imag () == 0.0) + { + y = FloatComplex (numeric_limits::Inf (), 0.0); + } + else { - alpha = -alpha; - - FloatComplex tmp = cosf (static_cast (M_PI) * alpha) - * cbesj (z, alpha, kode, ierr); - - if (ierr == 0 || ierr == 3) - { - tmp -= sinf (static_cast (M_PI) * alpha) - * cbesy (z, alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); - } - else - retval = FloatComplex (numeric_limits::NaN (), - numeric_limits::NaN ()); - } - - return retval; - } - - static inline FloatComplex - cbesy (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) - { - FloatComplex retval; - - if (alpha >= 0.0) - { - FloatComplex y = 0.0; - - F77_INT nz, t_ierr; - - FloatComplex w; - - ierr = 0; - - if (z.real () == 0.0 && z.imag () == 0.0) - { - y = FloatComplex (-numeric_limits::Inf (), 0.0); - } - else - { - F77_FUNC (cbesy, CBESY) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, - F77_CMPLX_ARG (&y), nz, - F77_CMPLX_ARG (&w), t_ierr); - - ierr = t_ierr; - - if (z.imag () == 0.0 && z.real () >= 0.0) - y = FloatComplex (y.real (), 0.0); - } - - return bessel_return_value (y, ierr); - } - else if (is_integer_value (alpha - 0.5)) - { - // zbesy can overflow as z->0, and cause troubles for generic case below - alpha = -alpha; - FloatComplex tmp = cbesj (z, alpha, kode, ierr); - if ((static_cast (alpha - 0.5)) & 1) - tmp = - tmp; - retval = bessel_return_value (tmp, ierr); - } - else - { - alpha = -alpha; - - FloatComplex tmp = cosf (static_cast (M_PI) * alpha) - * cbesy (z, alpha, kode, ierr); - - if (ierr == 0 || ierr == 3) - { - tmp += sinf (static_cast (M_PI) * alpha) - * cbesj (z, alpha, kode, ierr); - - retval = bessel_return_value (tmp, ierr); - } - else - retval = FloatComplex (numeric_limits::NaN (), - numeric_limits::NaN ()); - } - - return retval; - } - - static inline FloatComplex - cbesi (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) - { - FloatComplex retval; - - if (alpha >= 0.0) - { - FloatComplex y = 0.0; - - F77_INT nz, t_ierr; - - F77_FUNC (cbesi, CBESI) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, + F77_FUNC (cbesk, CBESK) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, F77_CMPLX_ARG (&y), nz, t_ierr); ierr = t_ierr; if (z.imag () == 0.0 && z.real () >= 0.0) y = FloatComplex (y.real (), 0.0); - - retval = bessel_return_value (y, ierr); - } - else - { - alpha = -alpha; - - FloatComplex tmp = cbesi (z, alpha, kode, ierr); - - if (ierr == 0 || ierr == 3) - { - FloatComplex tmp2 = static_cast (2.0 / M_PI) - * sinf (static_cast (M_PI) * alpha) - * cbesk (z, alpha, kode, ierr); - - if (kode == 2) - { - // Compensate for different scaling factor of besk. - tmp2 *= exp (-z - std::abs (z.real ())); - } - - tmp += tmp2; - - retval = bessel_return_value (tmp, ierr); - } - else - retval = FloatComplex (numeric_limits::NaN (), - numeric_limits::NaN ()); } - return retval; + retval = bessel_return_value (y, ierr); + } + else + { + FloatComplex tmp = cbesk (z, -alpha, kode, ierr); + + retval = bessel_return_value (tmp, ierr); } - static inline FloatComplex - cbesk (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) - { - FloatComplex retval; + return retval; +} - if (alpha >= 0.0) - { - FloatComplex y = 0.0; +static inline FloatComplex +cbesh1 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) +{ + FloatComplex retval; - F77_INT nz, t_ierr; + if (alpha >= 0.0) + { + FloatComplex y = 0.0; - ierr = 0; + F77_INT nz, t_ierr; - if (z.real () == 0.0 && z.imag () == 0.0) - { - y = FloatComplex (numeric_limits::Inf (), 0.0); - } - else - { - F77_FUNC (cbesk, CBESK) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, - F77_CMPLX_ARG (&y), nz, t_ierr); + F77_FUNC (cbesh, CBESH) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, 1, + F77_CMPLX_ARG (&y), nz, t_ierr); - ierr = t_ierr; + ierr = t_ierr; - if (z.imag () == 0.0 && z.real () >= 0.0) - y = FloatComplex (y.real (), 0.0); - } + retval = bessel_return_value (y, ierr); + } + else + { + alpha = -alpha; - retval = bessel_return_value (y, ierr); - } - else - { - FloatComplex tmp = cbesk (z, -alpha, kode, ierr); + static const FloatComplex eye = FloatComplex (0.0, 1.0); - retval = bessel_return_value (tmp, ierr); - } + FloatComplex tmp = exp (static_cast (M_PI) * alpha * eye) + * cbesh1 (z, alpha, kode, ierr); - return retval; + retval = bessel_return_value (tmp, ierr); } - static inline FloatComplex - cbesh1 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) - { - FloatComplex retval; + return retval; +} - if (alpha >= 0.0) - { - FloatComplex y = 0.0; - - F77_INT nz, t_ierr; - - F77_FUNC (cbesh, CBESH) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 1, 1, - F77_CMPLX_ARG (&y), nz, t_ierr); - - ierr = t_ierr; +static inline FloatComplex +cbesh2 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) +{ + FloatComplex retval; - retval = bessel_return_value (y, ierr); - } - else - { - alpha = -alpha; + if (alpha >= 0.0) + { + FloatComplex y = 0.0;; - static const FloatComplex eye = FloatComplex (0.0, 1.0); + F77_INT nz, t_ierr; - FloatComplex tmp = exp (static_cast (M_PI) * alpha * eye) - * cbesh1 (z, alpha, kode, ierr); + F77_FUNC (cbesh, CBESH) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 2, 1, + F77_CMPLX_ARG (&y), nz, t_ierr); - retval = bessel_return_value (tmp, ierr); - } + ierr = t_ierr; - return retval; + retval = bessel_return_value (y, ierr); } - - static inline FloatComplex - cbesh2 (const FloatComplex& z, float alpha, int kode, octave_idx_type& ierr) + else { - FloatComplex retval; - - if (alpha >= 0.0) - { - FloatComplex y = 0.0;; - - F77_INT nz, t_ierr; - - F77_FUNC (cbesh, CBESH) (F77_CONST_CMPLX_ARG (&z), alpha, kode, 2, 1, - F77_CMPLX_ARG (&y), nz, t_ierr); + alpha = -alpha; - ierr = t_ierr; - - retval = bessel_return_value (y, ierr); - } - else - { - alpha = -alpha; + static const FloatComplex eye = FloatComplex (0.0, 1.0); - static const FloatComplex eye = FloatComplex (0.0, 1.0); - - FloatComplex tmp = exp (-static_cast (M_PI) * alpha * eye) - * cbesh2 (z, alpha, kode, ierr); + FloatComplex tmp = exp (-static_cast (M_PI) * alpha * eye) + * cbesh2 (z, alpha, kode, ierr); - retval = bessel_return_value (tmp, ierr); - } - - return retval; + retval = bessel_return_value (tmp, ierr); } - typedef FloatComplex (*fptr) (const FloatComplex&, float, int, - octave_idx_type&); + return retval; +} + +typedef FloatComplex (*fptr) (const FloatComplex&, float, int, + octave_idx_type&); - static inline FloatComplex - do_bessel (fptr f, const char *, float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr) - { - FloatComplex retval; +static inline FloatComplex +do_bessel (fptr f, const char *, float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr) +{ + FloatComplex retval; - retval = f (x, alpha, (scaled ? 2 : 1), ierr); + retval = f (x, alpha, (scaled ? 2 : 1), ierr); - return retval; - } + return retval; +} - static inline FloatComplexMatrix - do_bessel (fptr f, const char *, float alpha, const FloatComplexMatrix& x, - bool scaled, Array& ierr) - { - octave_idx_type nr = x.rows (); - octave_idx_type nc = x.cols (); +static inline FloatComplexMatrix +do_bessel (fptr f, const char *, float alpha, const FloatComplexMatrix& x, + bool scaled, Array& ierr) +{ + octave_idx_type nr = x.rows (); + octave_idx_type nc = x.cols (); - FloatComplexMatrix retval (nr, nc); + FloatComplexMatrix retval (nr, nc); - ierr.resize (dim_vector (nr, nc)); + ierr.resize (dim_vector (nr, nc)); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x(i, j), alpha, (scaled ? 2 : 1), ierr(i, j)); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x(i, j), alpha, (scaled ? 2 : 1), ierr(i, j)); - return retval; - } + return retval; +} - static inline FloatComplexMatrix - do_bessel (fptr f, const char *, const FloatMatrix& alpha, - const FloatComplex& x, - bool scaled, Array& ierr) - { - octave_idx_type nr = alpha.rows (); - octave_idx_type nc = alpha.cols (); +static inline FloatComplexMatrix +do_bessel (fptr f, const char *, const FloatMatrix& alpha, + const FloatComplex& x, + bool scaled, Array& ierr) +{ + octave_idx_type nr = alpha.rows (); + octave_idx_type nc = alpha.cols (); - FloatComplexMatrix retval (nr, nc); + FloatComplexMatrix retval (nr, nc); - ierr.resize (dim_vector (nr, nc)); + ierr.resize (dim_vector (nr, nc)); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x, alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x, alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); - return retval; - } + return retval; +} - static inline FloatComplexMatrix - do_bessel (fptr f, const char *fn, const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, - Array& ierr) - { - FloatComplexMatrix retval; +static inline FloatComplexMatrix +do_bessel (fptr f, const char *fn, const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, + Array& ierr) +{ + FloatComplexMatrix retval; - octave_idx_type x_nr = x.rows (); - octave_idx_type x_nc = x.cols (); + octave_idx_type x_nr = x.rows (); + octave_idx_type x_nc = x.cols (); - octave_idx_type alpha_nr = alpha.rows (); - octave_idx_type alpha_nc = alpha.cols (); + octave_idx_type alpha_nr = alpha.rows (); + octave_idx_type alpha_nc = alpha.cols (); - if (x_nr != alpha_nr || x_nc != alpha_nc) - (*current_liboctave_error_handler) - ("%s: the sizes of alpha and x must conform", fn); + if (x_nr != alpha_nr || x_nc != alpha_nc) + (*current_liboctave_error_handler) + ("%s: the sizes of alpha and x must conform", fn); - octave_idx_type nr = x_nr; - octave_idx_type nc = x_nc; + octave_idx_type nr = x_nr; + octave_idx_type nc = x_nc; - retval.resize (nr, nc); + retval.resize (nr, nc); - ierr.resize (dim_vector (nr, nc)); + ierr.resize (dim_vector (nr, nc)); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x(i, j), alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x(i, j), alpha(i, j), (scaled ? 2 : 1), ierr(i, j)); - return retval; - } + return retval; +} - static inline FloatComplexNDArray - do_bessel (fptr f, const char *, float alpha, const FloatComplexNDArray& x, - bool scaled, Array& ierr) - { - dim_vector dv = x.dims (); - octave_idx_type nel = dv.numel (); - FloatComplexNDArray retval (dv); +static inline FloatComplexNDArray +do_bessel (fptr f, const char *, float alpha, const FloatComplexNDArray& x, + bool scaled, Array& ierr) +{ + dim_vector dv = x.dims (); + octave_idx_type nel = dv.numel (); + FloatComplexNDArray retval (dv); - ierr.resize (dv); + ierr.resize (dv); - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = f (x(i), alpha, (scaled ? 2 : 1), ierr(i)); + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = f (x(i), alpha, (scaled ? 2 : 1), ierr(i)); - return retval; - } + return retval; +} - static inline FloatComplexNDArray - do_bessel (fptr f, const char *, const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr) - { - dim_vector dv = alpha.dims (); - octave_idx_type nel = dv.numel (); - FloatComplexNDArray retval (dv); +static inline FloatComplexNDArray +do_bessel (fptr f, const char *, const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr) +{ + dim_vector dv = alpha.dims (); + octave_idx_type nel = dv.numel (); + FloatComplexNDArray retval (dv); - ierr.resize (dv); + ierr.resize (dv); - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = f (x, alpha(i), (scaled ? 2 : 1), ierr(i)); + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = f (x, alpha(i), (scaled ? 2 : 1), ierr(i)); - return retval; - } + return retval; +} - static inline FloatComplexNDArray - do_bessel (fptr f, const char *fn, const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, - Array& ierr) - { - dim_vector dv = x.dims (); - FloatComplexNDArray retval; +static inline FloatComplexNDArray +do_bessel (fptr f, const char *fn, const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, + Array& ierr) +{ + dim_vector dv = x.dims (); + FloatComplexNDArray retval; - if (dv != alpha.dims ()) - (*current_liboctave_error_handler) - ("%s: the sizes of alpha and x must conform", fn); + if (dv != alpha.dims ()) + (*current_liboctave_error_handler) + ("%s: the sizes of alpha and x must conform", fn); - octave_idx_type nel = dv.numel (); + octave_idx_type nel = dv.numel (); - retval.resize (dv); - ierr.resize (dv); + retval.resize (dv); + ierr.resize (dv); - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = f (x(i), alpha(i), (scaled ? 2 : 1), ierr(i)); + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = f (x(i), alpha(i), (scaled ? 2 : 1), ierr(i)); - return retval; - } + return retval; +} - static inline FloatComplexMatrix - do_bessel (fptr f, const char *, const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, - Array& ierr) - { - octave_idx_type nr = x.numel (); - octave_idx_type nc = alpha.numel (); +static inline FloatComplexMatrix +do_bessel (fptr f, const char *, const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, + Array& ierr) +{ + octave_idx_type nr = x.numel (); + octave_idx_type nc = alpha.numel (); - FloatComplexMatrix retval (nr, nc); + FloatComplexMatrix retval (nr, nc); - ierr.resize (dim_vector (nr, nc)); + ierr.resize (dim_vector (nr, nc)); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = f (x(i), alpha(j), (scaled ? 2 : 1), ierr(i, j)); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = f (x(i), alpha(j), (scaled ? 2 : 1), ierr(i, j)); - return retval; - } + return retval; +} #define SS_BESSEL(name, fcn) \ FloatComplex \ @@ -1330,12 +1330,12 @@ NN_BESSEL (name, fcn) \ RC_BESSEL (name, fcn) - ALL_BESSEL (besselj, cbesj) - ALL_BESSEL (bessely, cbesy) - ALL_BESSEL (besseli, cbesi) - ALL_BESSEL (besselk, cbesk) - ALL_BESSEL (besselh1, cbesh1) - ALL_BESSEL (besselh2, cbesh2) +ALL_BESSEL (besselj, cbesj) +ALL_BESSEL (bessely, cbesy) +ALL_BESSEL (besseli, cbesi) +ALL_BESSEL (besselk, cbesk) +ALL_BESSEL (besselh1, cbesh1) +ALL_BESSEL (besselh2, cbesh2) #undef ALL_BESSEL #undef SS_BESSEL @@ -1347,865 +1347,865 @@ #undef NN_BESSEL #undef RC_BESSEL - Complex - biry (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr) - { - double ar = 0.0; - double ai = 0.0; +Complex +biry (const Complex& z, bool deriv, bool scaled, octave_idx_type& ierr) +{ + double ar = 0.0; + double ai = 0.0; + + double zr = z.real (); + double zi = z.imag (); + + F77_INT id = (deriv ? 1 : 0); + F77_INT t_ierr; + F77_INT sc = (scaled ? 2 : 1); + + F77_FUNC (zbiry, ZBIRY) (zr, zi, id, sc, ar, ai, t_ierr); + + ierr = t_ierr; + + if (zi == 0.0 && (! scaled || zr >= 0.0)) + ai = 0.0; + + return bessel_return_value (Complex (ar, ai), ierr); +} + +ComplexMatrix +biry (const ComplexMatrix& z, bool deriv, bool scaled, + Array& ierr) +{ + octave_idx_type nr = z.rows (); + octave_idx_type nc = z.cols (); + + ComplexMatrix retval (nr, nc); + + ierr.resize (dim_vector (nr, nc)); - double zr = z.real (); - double zi = z.imag (); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = biry (z(i, j), deriv, scaled, ierr(i, j)); + + return retval; +} + +ComplexNDArray +biry (const ComplexNDArray& z, bool deriv, bool scaled, + Array& ierr) +{ + dim_vector dv = z.dims (); + octave_idx_type nel = dv.numel (); + ComplexNDArray retval (dv); + + ierr.resize (dv); - F77_INT id = (deriv ? 1 : 0); - F77_INT t_ierr; - F77_INT sc = (scaled ? 2 : 1); + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = biry (z(i), deriv, scaled, ierr(i)); + + return retval; +} + +FloatComplex +biry (const FloatComplex& z, bool deriv, bool scaled, + octave_idx_type& ierr) +{ + FloatComplex a; + + F77_INT id = (deriv ? 1 : 0); + F77_INT t_ierr; + F77_INT sc = (scaled ? 2 : 1); + + F77_FUNC (cbiry, CBIRY) (F77_CONST_CMPLX_ARG (&z), id, sc, + F77_CMPLX_ARG (&a), t_ierr); - F77_FUNC (zbiry, ZBIRY) (zr, zi, id, sc, ar, ai, t_ierr); + ierr = t_ierr; + + float ar = a.real (); + float ai = a.imag (); + + if (z.imag () == 0.0 && (! scaled || z.real () >= 0.0)) + ai = 0.0; + + return bessel_return_value (FloatComplex (ar, ai), ierr); +} - ierr = t_ierr; +FloatComplexMatrix +biry (const FloatComplexMatrix& z, bool deriv, bool scaled, + Array& ierr) +{ + octave_idx_type nr = z.rows (); + octave_idx_type nc = z.cols (); + + FloatComplexMatrix retval (nr, nc); - if (zi == 0.0 && (! scaled || zr >= 0.0)) - ai = 0.0; + ierr.resize (dim_vector (nr, nc)); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + retval(i, j) = biry (z(i, j), deriv, scaled, ierr(i, j)); + + return retval; +} - return bessel_return_value (Complex (ar, ai), ierr); - } +FloatComplexNDArray +biry (const FloatComplexNDArray& z, bool deriv, bool scaled, + Array& ierr) +{ + dim_vector dv = z.dims (); + octave_idx_type nel = dv.numel (); + FloatComplexNDArray retval (dv); + + ierr.resize (dv); + + for (octave_idx_type i = 0; i < nel; i++) + retval(i) = biry (z(i), deriv, scaled, ierr(i)); + + return retval; +} + +// Real and complex Dawson function (= scaled erfi) from Faddeeva package +double dawson (double x) { return Faddeeva::Dawson (x); } +float dawson (float x) { return Faddeeva::Dawson (x); } - ComplexMatrix - biry (const ComplexMatrix& z, bool deriv, bool scaled, - Array& ierr) +Complex +dawson (const Complex& x) +{ + return Faddeeva::Dawson (x); +} + +FloatComplex +dawson (const FloatComplex& x) +{ + Complex xd (x.real (), x.imag ()); + Complex ret; + ret = Faddeeva::Dawson (xd, std::numeric_limits::epsilon ()); + return FloatComplex (ret.real (), ret.imag ()); +} + +void +ellipj (double u, double m, double& sn, double& cn, double& dn, double& err) +{ + static const int Nmax = 16; + double m1, t=0, si_u, co_u, se_u, ta_u, b, c[Nmax], a[Nmax], phi; + int n, Nn, ii; + + if (m < 0 || m > 1) { - octave_idx_type nr = z.rows (); - octave_idx_type nc = z.cols (); - - ComplexMatrix retval (nr, nc); - - ierr.resize (dim_vector (nr, nc)); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = biry (z(i, j), deriv, scaled, ierr(i, j)); - - return retval; - } + (*current_liboctave_warning_with_id_handler) + ("Octave:ellipj-invalid-m", + "ellipj: invalid M value, required value 0 <= M <= 1"); - ComplexNDArray - biry (const ComplexNDArray& z, bool deriv, bool scaled, - Array& ierr) - { - dim_vector dv = z.dims (); - octave_idx_type nel = dv.numel (); - ComplexNDArray retval (dv); + sn = cn = dn = lo_ieee_nan_value (); - ierr.resize (dv); - - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = biry (z(i), deriv, scaled, ierr(i)); - - return retval; + return; } - FloatComplex - biry (const FloatComplex& z, bool deriv, bool scaled, - octave_idx_type& ierr) + double sqrt_eps = std::sqrt (std::numeric_limits::epsilon ()); + if (m < sqrt_eps) { - FloatComplex a; - - F77_INT id = (deriv ? 1 : 0); - F77_INT t_ierr; - F77_INT sc = (scaled ? 2 : 1); - - F77_FUNC (cbiry, CBIRY) (F77_CONST_CMPLX_ARG (&z), id, sc, - F77_CMPLX_ARG (&a), t_ierr); - - ierr = t_ierr; - - float ar = a.real (); - float ai = a.imag (); - - if (z.imag () == 0.0 && (! scaled || z.real () >= 0.0)) - ai = 0.0; - - return bessel_return_value (FloatComplex (ar, ai), ierr); + // For small m, (Abramowitz and Stegun, Section 16.13) + si_u = sin (u); + co_u = cos (u); + t = 0.25*m*(u - si_u*co_u); + sn = si_u - t * co_u; + cn = co_u + t * si_u; + dn = 1 - 0.5*m*si_u*si_u; } - - FloatComplexMatrix - biry (const FloatComplexMatrix& z, bool deriv, bool scaled, - Array& ierr) - { - octave_idx_type nr = z.rows (); - octave_idx_type nc = z.cols (); - - FloatComplexMatrix retval (nr, nc); - - ierr.resize (dim_vector (nr, nc)); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - retval(i, j) = biry (z(i, j), deriv, scaled, ierr(i, j)); - - return retval; - } - - FloatComplexNDArray - biry (const FloatComplexNDArray& z, bool deriv, bool scaled, - Array& ierr) + else if ((1 - m) < sqrt_eps) { - dim_vector dv = z.dims (); - octave_idx_type nel = dv.numel (); - FloatComplexNDArray retval (dv); - - ierr.resize (dv); - - for (octave_idx_type i = 0; i < nel; i++) - retval(i) = biry (z(i), deriv, scaled, ierr(i)); - - return retval; - } - - // Real and complex Dawson function (= scaled erfi) from Faddeeva package - double dawson (double x) { return Faddeeva::Dawson (x); } - float dawson (float x) { return Faddeeva::Dawson (x); } - - Complex - dawson (const Complex& x) - { - return Faddeeva::Dawson (x); + // For m1 = (1-m) small (Abramowitz and Stegun, Section 16.15) + m1 = 1 - m; + si_u = sinh (u); + co_u = cosh (u); + ta_u = tanh (u); + se_u = 1/co_u; + sn = ta_u + 0.25*m1*(si_u*co_u - u)*se_u*se_u; + cn = se_u - 0.25*m1*(si_u*co_u - u)*ta_u*se_u; + dn = se_u + 0.25*m1*(si_u*co_u + u)*ta_u*se_u; } - - FloatComplex - dawson (const FloatComplex& x) - { - Complex xd (x.real (), x.imag ()); - Complex ret; - ret = Faddeeva::Dawson (xd, std::numeric_limits::epsilon ()); - return FloatComplex (ret.real (), ret.imag ()); - } - - void - ellipj (double u, double m, double& sn, double& cn, double& dn, double& err) + else { - static const int Nmax = 16; - double m1, t=0, si_u, co_u, se_u, ta_u, b, c[Nmax], a[Nmax], phi; - int n, Nn, ii; - - if (m < 0 || m > 1) + // Arithmetic-Geometric Mean (AGM) algorithm + // (Abramowitz and Stegun, Section 16.4) + a[0] = 1; + b = std::sqrt (1 - m); + c[0] = std::sqrt (m); + for (n = 1; n < Nmax; ++n) { - (*current_liboctave_warning_with_id_handler) - ("Octave:ellipj-invalid-m", - "ellipj: invalid M value, required value 0 <= M <= 1"); - - sn = cn = dn = lo_ieee_nan_value (); - + a[n] = (a[n - 1] + b)/2; + c[n] = (a[n - 1] - b)/2; + b = std::sqrt (a[n - 1]*b); + if (c[n]/a[n] < std::numeric_limits::epsilon ()) break; + } + if (n >= Nmax - 1) + { + err = 1; return; } - - double sqrt_eps = std::sqrt (std::numeric_limits::epsilon ()); - if (m < sqrt_eps) - { - // For small m, (Abramowitz and Stegun, Section 16.13) - si_u = sin (u); - co_u = cos (u); - t = 0.25*m*(u - si_u*co_u); - sn = si_u - t * co_u; - cn = co_u + t * si_u; - dn = 1 - 0.5*m*si_u*si_u; - } - else if ((1 - m) < sqrt_eps) - { - // For m1 = (1-m) small (Abramowitz and Stegun, Section 16.15) - m1 = 1 - m; - si_u = sinh (u); - co_u = cosh (u); - ta_u = tanh (u); - se_u = 1/co_u; - sn = ta_u + 0.25*m1*(si_u*co_u - u)*se_u*se_u; - cn = se_u - 0.25*m1*(si_u*co_u - u)*ta_u*se_u; - dn = se_u + 0.25*m1*(si_u*co_u + u)*ta_u*se_u; - } - else + Nn = n; + for (ii = 1; n > 0; ii *= 2, --n) {} // ii = pow(2,Nn) + phi = ii*a[Nn]*u; + for (n = Nn; n > 0; --n) { - // Arithmetic-Geometric Mean (AGM) algorithm - // (Abramowitz and Stegun, Section 16.4) - a[0] = 1; - b = std::sqrt (1 - m); - c[0] = std::sqrt (m); - for (n = 1; n < Nmax; ++n) - { - a[n] = (a[n - 1] + b)/2; - c[n] = (a[n - 1] - b)/2; - b = std::sqrt (a[n - 1]*b); - if (c[n]/a[n] < std::numeric_limits::epsilon ()) break; - } - if (n >= Nmax - 1) - { - err = 1; - return; - } - Nn = n; - for (ii = 1; n > 0; ii *= 2, --n) {} // ii = pow(2,Nn) - phi = ii*a[Nn]*u; - for (n = Nn; n > 0; --n) - { - phi = (std::asin ((c[n]/a[n])* sin (phi)) + phi)/2; - } - sn = sin (phi); - cn = cos (phi); - dn = std::sqrt (1 - m*sn*sn); + phi = (std::asin ((c[n]/a[n])* sin (phi)) + phi)/2; } + sn = sin (phi); + cn = cos (phi); + dn = std::sqrt (1 - m*sn*sn); } +} + +void +ellipj (const Complex& u, double m, Complex& sn, Complex& cn, Complex& dn, + double& err) +{ + double m1 = 1 - m, ss1, cc1, dd1; - void - ellipj (const Complex& u, double m, Complex& sn, Complex& cn, Complex& dn, - double& err) + ellipj (u.imag (), m1, ss1, cc1, dd1, err); + if (u.real () == 0) { - double m1 = 1 - m, ss1, cc1, dd1; + // u is pure imag: Jacoby imag. transf. + sn = Complex (0, ss1/cc1); + cn = 1/cc1; // cn.imag = 0; + dn = dd1/cc1; // dn.imag = 0; + } + else + { + // u is generic complex + double ss, cc, dd, ddd; - ellipj (u.imag (), m1, ss1, cc1, dd1, err); - if (u.real () == 0) - { - // u is pure imag: Jacoby imag. transf. - sn = Complex (0, ss1/cc1); - cn = 1/cc1; // cn.imag = 0; - dn = dd1/cc1; // dn.imag = 0; - } - else - { - // u is generic complex - double ss, cc, dd, ddd; + ellipj (u.real (), m, ss, cc, dd, err); + ddd = cc1*cc1 + m*ss*ss*ss1*ss1; + sn = Complex (ss*dd1/ddd, cc*dd*ss1*cc1/ddd); + cn = Complex (cc*cc1/ddd, -ss*dd*ss1*dd1/ddd); + dn = Complex (dd*cc1*dd1/ddd, -m*ss*cc*ss1/ddd); + } +} + +// Complex error function from the Faddeeva package +Complex +erf (const Complex& x) +{ + return Faddeeva::erf (x); +} - ellipj (u.real (), m, ss, cc, dd, err); - ddd = cc1*cc1 + m*ss*ss*ss1*ss1; - sn = Complex (ss*dd1/ddd, cc*dd*ss1*cc1/ddd); - cn = Complex (cc*cc1/ddd, -ss*dd*ss1*dd1/ddd); - dn = Complex (dd*cc1*dd1/ddd, -m*ss*cc*ss1/ddd); - } - } +FloatComplex +erf (const FloatComplex& x) +{ + Complex xd (x.real (), x.imag ()); + Complex ret = Faddeeva::erf (xd, std::numeric_limits::epsilon ()); + return FloatComplex (ret.real (), ret.imag ()); +} - // Complex error function from the Faddeeva package - Complex - erf (const Complex& x) - { - return Faddeeva::erf (x); - } +// Complex complementary error function from the Faddeeva package +Complex +erfc (const Complex& x) +{ + return Faddeeva::erfc (x); +} - FloatComplex - erf (const FloatComplex& x) - { - Complex xd (x.real (), x.imag ()); - Complex ret = Faddeeva::erf (xd, std::numeric_limits::epsilon ()); - return FloatComplex (ret.real (), ret.imag ()); - } +FloatComplex +erfc (const FloatComplex& x) +{ + Complex xd (x.real (), x.imag ()); + Complex ret = Faddeeva::erfc (xd, std::numeric_limits::epsilon ()); + return FloatComplex (ret.real (), ret.imag ()); +} - // Complex complementary error function from the Faddeeva package - Complex - erfc (const Complex& x) - { - return Faddeeva::erfc (x); - } - - FloatComplex - erfc (const FloatComplex& x) - { - Complex xd (x.real (), x.imag ()); - Complex ret = Faddeeva::erfc (xd, std::numeric_limits::epsilon ()); - return FloatComplex (ret.real (), ret.imag ()); - } - - // The algorithm for erfcinv is an adaptation of the erfinv algorithm - // above from P. J. Acklam. It has been modified to run over the - // different input domain of erfcinv. See the notes for erfinv for an - // explanation. +// The algorithm for erfcinv is an adaptation of the erfinv algorithm +// above from P. J. Acklam. It has been modified to run over the +// different input domain of erfcinv. See the notes for erfinv for an +// explanation. - static double do_erfcinv (double x, bool refine) - { - // Coefficients of rational approximation. - static const double a[] = - { - -2.806989788730439e+01, 1.562324844726888e+02, - -1.951109208597547e+02, 9.783370457507161e+01, - -2.168328665628878e+01, 1.772453852905383e+00 - }; - static const double b[] = - { - -5.447609879822406e+01, 1.615858368580409e+02, - -1.556989798598866e+02, 6.680131188771972e+01, - -1.328068155288572e+01 - }; - static const double c[] = - { - -5.504751339936943e-03, -2.279687217114118e-01, - -1.697592457770869e+00, -1.802933168781950e+00, - 3.093354679843505e+00, 2.077595676404383e+00 - }; - static const double d[] = - { - 7.784695709041462e-03, 3.224671290700398e-01, - 2.445134137142996e+00, 3.754408661907416e+00 - }; +static double do_erfcinv (double x, bool refine) +{ + // Coefficients of rational approximation. + static const double a[] = + { + -2.806989788730439e+01, 1.562324844726888e+02, + -1.951109208597547e+02, 9.783370457507161e+01, + -2.168328665628878e+01, 1.772453852905383e+00 + }; + static const double b[] = + { + -5.447609879822406e+01, 1.615858368580409e+02, + -1.556989798598866e+02, 6.680131188771972e+01, + -1.328068155288572e+01 + }; + static const double c[] = + { + -5.504751339936943e-03, -2.279687217114118e-01, + -1.697592457770869e+00, -1.802933168781950e+00, + 3.093354679843505e+00, 2.077595676404383e+00 + }; + static const double d[] = + { + 7.784695709041462e-03, 3.224671290700398e-01, + 2.445134137142996e+00, 3.754408661907416e+00 + }; + + static const double spi2 = 8.862269254527579e-01; // sqrt(pi)/2. + static const double pbreak_lo = 0.04850; // 1-pbreak + static const double pbreak_hi = 1.95150; // 1+pbreak + double y; - static const double spi2 = 8.862269254527579e-01; // sqrt(pi)/2. - static const double pbreak_lo = 0.04850; // 1-pbreak - static const double pbreak_hi = 1.95150; // 1+pbreak - double y; + // Select case. + if (x >= pbreak_lo && x <= pbreak_hi) + { + // Middle region. + const double q = 0.5*(1-x), r = q*q; + const double yn = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q; + const double yd = ((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0; + y = yn / yd; + } + else if (x > 0.0 && x < 2.0) + { + // Tail region. + const double q = (x < 1 + ? std::sqrt (-2*std::log (0.5*x)) + : std::sqrt (-2*std::log (0.5*(2-x)))); - // Select case. - if (x >= pbreak_lo && x <= pbreak_hi) - { - // Middle region. - const double q = 0.5*(1-x), r = q*q; - const double yn = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q; - const double yd = ((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0; - y = yn / yd; - } - else if (x > 0.0 && x < 2.0) - { - // Tail region. - const double q = (x < 1 - ? std::sqrt (-2*std::log (0.5*x)) - : std::sqrt (-2*std::log (0.5*(2-x)))); - - const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]; - - const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0; + const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]; - y = yn / yd; + const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0; - if (x < pbreak_lo) - y = -y; - } - else if (x == 0.0) - return numeric_limits::Inf (); - else if (x == 2.0) - return -numeric_limits::Inf (); - else - return numeric_limits::NaN (); + y = yn / yd; - if (refine) - { - // One iteration of Halley's method gives full precision. - double u = (erf (y) - (1-x)) * spi2 * exp (y*y); - y -= u / (1 + y*u); - } + if (x < pbreak_lo) + y = -y; + } + else if (x == 0.0) + return numeric_limits::Inf (); + else if (x == 2.0) + return -numeric_limits::Inf (); + else + return numeric_limits::NaN (); - return y; - } - - double erfcinv (double x) + if (refine) { - return do_erfcinv (x, true); + // One iteration of Halley's method gives full precision. + double u = (erf (y) - (1-x)) * spi2 * exp (y*y); + y -= u / (1 + y*u); } - float erfcinv (float x) - { - return do_erfcinv (x, false); - } + return y; +} - // Real and complex scaled complementary error function from Faddeeva pkg. - double erfcx (double x) { return Faddeeva::erfcx (x); } - float erfcx (float x) { return Faddeeva::erfcx (x); } - - Complex - erfcx (const Complex& x) - { - return Faddeeva::erfcx (x); - } +double erfcinv (double x) +{ + return do_erfcinv (x, true); +} - FloatComplex - erfcx (const FloatComplex& x) - { - Complex xd (x.real (), x.imag ()); - Complex ret; - ret = Faddeeva::erfcx (xd, std::numeric_limits::epsilon ()); - return FloatComplex (ret.real (), ret.imag ()); - } +float erfcinv (float x) +{ + return do_erfcinv (x, false); +} - // Real and complex imaginary error function from Faddeeva package - double erfi (double x) { return Faddeeva::erfi (x); } - float erfi (float x) { return Faddeeva::erfi (x); } +// Real and complex scaled complementary error function from Faddeeva pkg. +double erfcx (double x) { return Faddeeva::erfcx (x); } +float erfcx (float x) { return Faddeeva::erfcx (x); } - Complex - erfi (const Complex& x) - { - return Faddeeva::erfi (x); - } +Complex +erfcx (const Complex& x) +{ + return Faddeeva::erfcx (x); +} - FloatComplex - erfi (const FloatComplex& x) - { - Complex xd (x.real (), x.imag ()); - Complex ret = Faddeeva::erfi (xd, std::numeric_limits::epsilon ()); - return FloatComplex (ret.real (), ret.imag ()); - } +FloatComplex +erfcx (const FloatComplex& x) +{ + Complex xd (x.real (), x.imag ()); + Complex ret; + ret = Faddeeva::erfcx (xd, std::numeric_limits::epsilon ()); + return FloatComplex (ret.real (), ret.imag ()); +} - // This algorithm is due to P. J. Acklam. - // - // See http://home.online.no/~pjacklam/notes/invnorm/ - // - // The rational approximation has relative accuracy 1.15e-9 in the whole - // region. For doubles, it is refined by a single step of Halley's 3rd - // order method. For single precision, the accuracy is already OK, so - // we skip it to get faster evaluation. +// Real and complex imaginary error function from Faddeeva package +double erfi (double x) { return Faddeeva::erfi (x); } +float erfi (float x) { return Faddeeva::erfi (x); } - static double do_erfinv (double x, bool refine) - { - // Coefficients of rational approximation. - static const double a[] = - { - -2.806989788730439e+01, 1.562324844726888e+02, - -1.951109208597547e+02, 9.783370457507161e+01, - -2.168328665628878e+01, 1.772453852905383e+00 - }; - static const double b[] = - { - -5.447609879822406e+01, 1.615858368580409e+02, - -1.556989798598866e+02, 6.680131188771972e+01, - -1.328068155288572e+01 - }; - static const double c[] = - { - -5.504751339936943e-03, -2.279687217114118e-01, - -1.697592457770869e+00, -1.802933168781950e+00, - 3.093354679843505e+00, 2.077595676404383e+00 - }; - static const double d[] = - { - 7.784695709041462e-03, 3.224671290700398e-01, - 2.445134137142996e+00, 3.754408661907416e+00 - }; +Complex +erfi (const Complex& x) +{ + return Faddeeva::erfi (x); +} + +FloatComplex +erfi (const FloatComplex& x) +{ + Complex xd (x.real (), x.imag ()); + Complex ret = Faddeeva::erfi (xd, std::numeric_limits::epsilon ()); + return FloatComplex (ret.real (), ret.imag ()); +} + +// This algorithm is due to P. J. Acklam. +// +// See http://home.online.no/~pjacklam/notes/invnorm/ +// +// The rational approximation has relative accuracy 1.15e-9 in the whole +// region. For doubles, it is refined by a single step of Halley's 3rd +// order method. For single precision, the accuracy is already OK, so +// we skip it to get faster evaluation. - static const double spi2 = 8.862269254527579e-01; // sqrt(pi)/2. - static const double pbreak = 0.95150; - double ax = fabs (x), y; - - // Select case. - if (ax <= pbreak) - { - // Middle region. - const double q = 0.5 * x, r = q*q; - const double yn = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q; - const double yd = ((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0; - y = yn / yd; - } - else if (ax < 1.0) - { - // Tail region. - const double q = std::sqrt (-2*std::log (0.5*(1-ax))); - const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]; - const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0; - y = yn / yd * math::signum (-x); - } - else if (ax == 1.0) - return numeric_limits::Inf () * math::signum (x); - else - return numeric_limits::NaN (); - - if (refine) - { - // One iteration of Halley's method gives full precision. - double u = (erf (y) - x) * spi2 * exp (y*y); - y -= u / (1 + y*u); - } - - return y; - } - - double erfinv (double x) - { - return do_erfinv (x, true); - } +static double do_erfinv (double x, bool refine) +{ + // Coefficients of rational approximation. + static const double a[] = + { + -2.806989788730439e+01, 1.562324844726888e+02, + -1.951109208597547e+02, 9.783370457507161e+01, + -2.168328665628878e+01, 1.772453852905383e+00 + }; + static const double b[] = + { + -5.447609879822406e+01, 1.615858368580409e+02, + -1.556989798598866e+02, 6.680131188771972e+01, + -1.328068155288572e+01 + }; + static const double c[] = + { + -5.504751339936943e-03, -2.279687217114118e-01, + -1.697592457770869e+00, -1.802933168781950e+00, + 3.093354679843505e+00, 2.077595676404383e+00 + }; + static const double d[] = + { + 7.784695709041462e-03, 3.224671290700398e-01, + 2.445134137142996e+00, 3.754408661907416e+00 + }; - float erfinv (float x) - { - return do_erfinv (x, false); - } - - Complex - expm1 (const Complex& x) - { - Complex retval; - - if (std::abs (x) < 1) - { - double im = x.imag (); - double u = expm1 (x.real ()); - double v = sin (im/2); - v = -2*v*v; - retval = Complex (u*v + u + v, (u+1) * sin (im)); - } - else - retval = std::exp (x) - Complex (1); + static const double spi2 = 8.862269254527579e-01; // sqrt(pi)/2. + static const double pbreak = 0.95150; + double ax = fabs (x), y; - return retval; + // Select case. + if (ax <= pbreak) + { + // Middle region. + const double q = 0.5 * x, r = q*q; + const double yn = (((((a[0]*r + a[1])*r + a[2])*r + a[3])*r + a[4])*r + a[5])*q; + const double yd = ((((b[0]*r + b[1])*r + b[2])*r + b[3])*r + b[4])*r + 1.0; + y = yn / yd; } - - FloatComplex - expm1 (const FloatComplex& x) + else if (ax < 1.0) { - FloatComplex retval; + // Tail region. + const double q = std::sqrt (-2*std::log (0.5*(1-ax))); + const double yn = ((((c[0]*q + c[1])*q + c[2])*q + c[3])*q + c[4])*q + c[5]; + const double yd = (((d[0]*q + d[1])*q + d[2])*q + d[3])*q + 1.0; + y = yn / yd * math::signum (-x); + } + else if (ax == 1.0) + return numeric_limits::Inf () * math::signum (x); + else + return numeric_limits::NaN (); - if (std::abs (x) < 1) - { - float im = x.imag (); - float u = expm1 (x.real ()); - float v = sin (im/2); - v = -2*v*v; - retval = FloatComplex (u*v + u + v, (u+1) * sin (im)); - } - else - retval = std::exp (x) - FloatComplex (1); - - return retval; + if (refine) + { + // One iteration of Halley's method gives full precision. + double u = (erf (y) - x) * spi2 * exp (y*y); + y -= u / (1 + y*u); } - double - gamma (double x) - { - double result; + return y; +} - // Special cases for (near) compatibility with Matlab instead of tgamma. - // Matlab does not have -0. +double erfinv (double x) +{ + return do_erfinv (x, true); +} - if (x == 0) - result = (math::negative_sign (x) - ? -numeric_limits::Inf () - : numeric_limits::Inf ()); - else if ((x < 0 && math::x_nint (x) == x) - || math::isinf (x)) - result = numeric_limits::Inf (); - else if (math::isnan (x)) - result = numeric_limits::NaN (); - else - result = std::tgamma (x); +float erfinv (float x) +{ + return do_erfinv (x, false); +} - return result; - } +Complex +expm1 (const Complex& x) +{ + Complex retval; - float - gamma (float x) + if (std::abs (x) < 1) { - float result; + double im = x.imag (); + double u = expm1 (x.real ()); + double v = sin (im/2); + v = -2*v*v; + retval = Complex (u*v + u + v, (u+1) * sin (im)); + } + else + retval = std::exp (x) - Complex (1); - // Special cases for (near) compatibility with Matlab instead of tgamma. - // Matlab does not have -0. + return retval; +} - if (x == 0) - result = (math::negative_sign (x) - ? -numeric_limits::Inf () - : numeric_limits::Inf ()); - else if ((x < 0 && math::x_nint (x) == x) - || math::isinf (x)) - result = numeric_limits::Inf (); - else if (math::isnan (x)) - result = numeric_limits::NaN (); - else - result = std::tgammaf (x); +FloatComplex +expm1 (const FloatComplex& x) +{ + FloatComplex retval; - return result; + if (std::abs (x) < 1) + { + float im = x.imag (); + float u = expm1 (x.real ()); + float v = sin (im/2); + v = -2*v*v; + retval = FloatComplex (u*v + u + v, (u+1) * sin (im)); } + else + retval = std::exp (x) - FloatComplex (1); + + return retval; +} - Complex - log1p (const Complex& x) - { - Complex retval; +double +gamma (double x) +{ + double result; - double r = x.real (), i = x.imag (); + // Special cases for (near) compatibility with Matlab instead of tgamma. + // Matlab does not have -0. - if (fabs (r) < 0.5 && fabs (i) < 0.5) - { - double u = 2*r + r*r + i*i; - retval = Complex (log1p (u / (1+std::sqrt (u+1))), - atan2 (i, 1 + r)); - } - else - retval = std::log (Complex (1) + x); + if (x == 0) + result = (math::negative_sign (x) + ? -numeric_limits::Inf () + : numeric_limits::Inf ()); + else if ((x < 0 && math::x_nint (x) == x) + || math::isinf (x)) + result = numeric_limits::Inf (); + else if (math::isnan (x)) + result = numeric_limits::NaN (); + else + result = std::tgamma (x); - return retval; - } - - FloatComplex - log1p (const FloatComplex& x) - { - FloatComplex retval; + return result; +} - float r = x.real (), i = x.imag (); +float +gamma (float x) +{ + float result; - if (fabs (r) < 0.5 && fabs (i) < 0.5) - { - float u = 2*r + r*r + i*i; - retval = FloatComplex (log1p (u / (1+std::sqrt (u+1))), - atan2 (i, 1 + r)); - } - else - retval = std::log (FloatComplex (1) + x); + // Special cases for (near) compatibility with Matlab instead of tgamma. + // Matlab does not have -0. - return retval; - } - - static const double pi = 3.14159265358979323846; + if (x == 0) + result = (math::negative_sign (x) + ? -numeric_limits::Inf () + : numeric_limits::Inf ()); + else if ((x < 0 && math::x_nint (x) == x) + || math::isinf (x)) + result = numeric_limits::Inf (); + else if (math::isnan (x)) + result = numeric_limits::NaN (); + else + result = std::tgammaf (x); - template - static inline T - xlog (const T& x) - { - return log (x); - } + return result; +} - template <> - inline double - xlog (const double& x) +Complex +log1p (const Complex& x) +{ + Complex retval; + + double r = x.real (), i = x.imag (); + + if (fabs (r) < 0.5 && fabs (i) < 0.5) { - return std::log (x); + double u = 2*r + r*r + i*i; + retval = Complex (log1p (u / (1+std::sqrt (u+1))), + atan2 (i, 1 + r)); } + else + retval = std::log (Complex (1) + x); - template <> - inline float - xlog (const float& x) - { - return std::log (x); - } + return retval; +} - template - static T - lanczos_approximation_psi (const T zc) +FloatComplex +log1p (const FloatComplex& x) +{ + FloatComplex retval; + + float r = x.real (), i = x.imag (); + + if (fabs (r) < 0.5 && fabs (i) < 0.5) { - // Coefficients for C.Lanczos expansion of psi function from XLiFE++ - // gammaFunctions psi_coef[k] = - (2k+1) * lg_coef[k] (see melina++ - // gamma functions -1/12, 3/360,-5/1260, 7/1680,-9/1188, - // 11*691/360360,-13/156, 15*3617/122400, ? , ? - static const T dg_coeff[10] = - { - -0.83333333333333333e-1, 0.83333333333333333e-2, - -0.39682539682539683e-2, 0.41666666666666667e-2, - -0.75757575757575758e-2, 0.21092796092796093e-1, - -0.83333333333333333e-1, 0.4432598039215686, - -0.3053954330270122e+1, 0.125318899521531e+2 - }; + float u = 2*r + r*r + i*i; + retval = FloatComplex (log1p (u / (1+std::sqrt (u+1))), + atan2 (i, 1 + r)); + } + else + retval = std::log (FloatComplex (1) + x); - T overz2 = T (1.0) / (zc * zc); - T overz2k = overz2; + return retval; +} + +static const double pi = 3.14159265358979323846; - T p = 0; - for (octave_idx_type k = 0; k < 10; k++, overz2k *= overz2) - p += dg_coeff[k] * overz2k; - p += xlog (zc) - T (0.5) / zc; - return p; - } +template +static inline T +xlog (const T& x) +{ + return log (x); +} - template - T - xpsi (T z) - { - static const double euler_mascheroni - = 0.577215664901532860606512090082402431042; +template <> +inline double +xlog (const double& x) +{ + return std::log (x); +} - const bool is_int = (std::floor (z) == z); +template <> +inline float +xlog (const float& x) +{ + return std::log (x); +} - T p = 0; - if (z <= 0) - { - // limits - zeros of the gamma function - if (is_int) - p = -numeric_limits::Inf (); // Matlab returns -Inf for psi (0) - else - // Abramowitz and Stegun, page 259, eq 6.3.7 - p = psi (1 - z) - (pi / tan (pi * z)); - } - else if (is_int) - { - // Abramowitz and Stegun, page 258, eq 6.3.2 - p = - euler_mascheroni; - for (octave_idx_type k = z - 1; k > 0; k--) - p += 1.0 / k; - } - else if (std::floor (z + 0.5) == z + 0.5) - { - // Abramowitz and Stegun, page 258, eq 6.3.3 and 6.3.4 - for (octave_idx_type k = z; k > 0; k--) - p += 1.0 / (2 * k - 1); +template +static T +lanczos_approximation_psi (const T zc) +{ + // Coefficients for C.Lanczos expansion of psi function from XLiFE++ + // gammaFunctions psi_coef[k] = - (2k+1) * lg_coef[k] (see melina++ + // gamma functions -1/12, 3/360,-5/1260, 7/1680,-9/1188, + // 11*691/360360,-13/156, 15*3617/122400, ? , ? + static const T dg_coeff[10] = + { + -0.83333333333333333e-1, 0.83333333333333333e-2, + -0.39682539682539683e-2, 0.41666666666666667e-2, + -0.75757575757575758e-2, 0.21092796092796093e-1, + -0.83333333333333333e-1, 0.4432598039215686, + -0.3053954330270122e+1, 0.125318899521531e+2 + }; + + T overz2 = T (1.0) / (zc * zc); + T overz2k = overz2; - p = - euler_mascheroni - 2 * std::log (2) + 2 * (p); - } + T p = 0; + for (octave_idx_type k = 0; k < 10; k++, overz2k *= overz2) + p += dg_coeff[k] * overz2k; + p += xlog (zc) - T (0.5) / zc; + return p; +} + +template +T +xpsi (T z) +{ + static const double euler_mascheroni + = 0.577215664901532860606512090082402431042; + + const bool is_int = (std::floor (z) == z); + + T p = 0; + if (z <= 0) + { + // limits - zeros of the gamma function + if (is_int) + p = -numeric_limits::Inf (); // Matlab returns -Inf for psi (0) else - { - // adapted from XLiFE++ gammaFunctions + // Abramowitz and Stegun, page 259, eq 6.3.7 + p = psi (1 - z) - (pi / tan (pi * z)); + } + else if (is_int) + { + // Abramowitz and Stegun, page 258, eq 6.3.2 + p = - euler_mascheroni; + for (octave_idx_type k = z - 1; k > 0; k--) + p += 1.0 / k; + } + else if (std::floor (z + 0.5) == z + 0.5) + { + // Abramowitz and Stegun, page 258, eq 6.3.3 and 6.3.4 + for (octave_idx_type k = z; k > 0; k--) + p += 1.0 / (2 * k - 1); - T zc = z; - // Use formula for derivative of LogGamma(z) - if (z < 10) - { - const signed char n = 10 - z; - for (signed char k = n - 1; k >= 0; k--) - p -= 1.0 / (k + z); - zc += n; - } - p += lanczos_approximation_psi (zc); - } - - return p; + p = - euler_mascheroni - 2 * std::log (2) + 2 * (p); } - - // explicit instantiations - double psi (double z) { return xpsi (z); } - float psi (float z) { return xpsi (z); } - - template - std::complex - xpsi (const std::complex& z) + else { // adapted from XLiFE++ gammaFunctions - typedef typename std::complex::value_type P; - - P z_r = z.real (); - P z_ra = z_r; - - std::complex dgam (0.0, 0.0); - if (z.imag () == 0) - dgam = std::complex (psi (z_r), 0.0); - else if (z_r < 0) - dgam = psi (P (1.0) - z)- (P (pi) / tan (P (pi) * z)); - else + T zc = z; + // Use formula for derivative of LogGamma(z) + if (z < 10) { - // Use formula for derivative of LogGamma(z) - std::complex z_m = z; - if (z_ra < 8) - { - unsigned char n = 8 - z_ra; - z_m = z + std::complex (n, 0.0); - - // Recurrence formula. For | Re(z) | < 8, use recursively - // - // DiGamma(z) = DiGamma(z+1) - 1/z - std::complex z_p = z + P (n - 1); - for (unsigned char k = n; k > 0; k--, z_p -= 1.0) - dgam -= P (1.0) / z_p; - } - - // for | Re(z) | > 8, use derivative of C.Lanczos expansion for - // LogGamma - // - // psi(z) = log(z) - 1/(2z) - 1/12z^2 + 3/360z^4 - 5/1260z^6 - // + 7/1680z^8 - 9/1188z^10 + ... - // - // (Abramowitz&Stegun, page 259, formula 6.3.18 - dgam += lanczos_approximation_psi (z_m); + const signed char n = 10 - z; + for (signed char k = n - 1; k >= 0; k--) + p -= 1.0 / (k + z); + zc += n; } - return dgam; - } - - // explicit instantiations - Complex psi (const Complex& z) { return xpsi (z); } - FloatComplex psi (const FloatComplex& z) { return xpsi (z); } - - template - static inline void - fortran_psifn (T z, octave_idx_type n, T& ans, octave_idx_type& ierr); - - template <> - inline void - fortran_psifn (double z, octave_idx_type n_arg, - double& ans, octave_idx_type& ierr) - { - F77_INT n = to_f77_int (n_arg); - F77_INT flag = 0; - F77_INT t_ierr; - F77_XFCN (dpsifn, DPSIFN, (z, n, 1, 1, ans, flag, t_ierr)); - ierr = t_ierr; - } - - template <> - inline void - fortran_psifn (float z, octave_idx_type n_arg, - float& ans, octave_idx_type& ierr) - { - F77_INT n = to_f77_int (n_arg); - F77_INT flag = 0; - F77_INT t_ierr; - F77_XFCN (psifn, PSIFN, (z, n, 1, 1, ans, flag, t_ierr)); - ierr = t_ierr; + p += lanczos_approximation_psi (zc); } - template - T - xpsi (octave_idx_type n, T z) + return p; +} + +// explicit instantiations +double psi (double z) { return xpsi (z); } +float psi (float z) { return xpsi (z); } + +template +std::complex +xpsi (const std::complex& z) +{ + // adapted from XLiFE++ gammaFunctions + + typedef typename std::complex::value_type P; + + P z_r = z.real (); + P z_ra = z_r; + + std::complex dgam (0.0, 0.0); + if (z.imag () == 0) + dgam = std::complex (psi (z_r), 0.0); + else if (z_r < 0) + dgam = psi (P (1.0) - z)- (P (pi) / tan (P (pi) * z)); + else { - T ans; - octave_idx_type ierr = 0; - fortran_psifn (z, n, ans, ierr); - if (ierr == 0) + // Use formula for derivative of LogGamma(z) + std::complex z_m = z; + if (z_ra < 8) { - // Remember that psifn and dpsifn return scales values - // When n is 1: do nothing since ((-1)**(n+1)/gamma(n+1)) == 1 - // When n is 0: change sign since ((-1)**(n+1)/gamma(n+1)) == -1 - if (n > 1) - // FIXME: xgamma here is a killer for our precision since it grows - // way too fast. - ans = ans / (std::pow (-1.0, n + 1) / gamma (double (n+1))); - else if (n == 0) - ans = -ans; + unsigned char n = 8 - z_ra; + z_m = z + std::complex (n, 0.0); + + // Recurrence formula. For | Re(z) | < 8, use recursively + // + // DiGamma(z) = DiGamma(z+1) - 1/z + std::complex z_p = z + P (n - 1); + for (unsigned char k = n; k > 0; k--, z_p -= 1.0) + dgam -= P (1.0) / z_p; } - else if (ierr == 2) - ans = - numeric_limits::Inf (); - else // we probably never get here - ans = numeric_limits::NaN (); + + // for | Re(z) | > 8, use derivative of C.Lanczos expansion for + // LogGamma + // + // psi(z) = log(z) - 1/(2z) - 1/12z^2 + 3/360z^4 - 5/1260z^6 + // + 7/1680z^8 - 9/1188z^10 + ... + // + // (Abramowitz&Stegun, page 259, formula 6.3.18 + dgam += lanczos_approximation_psi (z_m); + } + return dgam; +} - return ans; - } +// explicit instantiations +Complex psi (const Complex& z) { return xpsi (z); } +FloatComplex psi (const FloatComplex& z) { return xpsi (z); } + +template +static inline void +fortran_psifn (T z, octave_idx_type n, T& ans, octave_idx_type& ierr); + +template <> +inline void +fortran_psifn (double z, octave_idx_type n_arg, + double& ans, octave_idx_type& ierr) +{ + F77_INT n = to_f77_int (n_arg); + F77_INT flag = 0; + F77_INT t_ierr; + F77_XFCN (dpsifn, DPSIFN, (z, n, 1, 1, ans, flag, t_ierr)); + ierr = t_ierr; +} - double psi (octave_idx_type n, double z) { return xpsi (n, z); } - float psi (octave_idx_type n, float z) { return xpsi (n, z); } +template <> +inline void +fortran_psifn (float z, octave_idx_type n_arg, + float& ans, octave_idx_type& ierr) +{ + F77_INT n = to_f77_int (n_arg); + F77_INT flag = 0; + F77_INT t_ierr; + F77_XFCN (psifn, PSIFN, (z, n, 1, 1, ans, flag, t_ierr)); + ierr = t_ierr; +} - Complex - rc_lgamma (double x) +template +T +xpsi (octave_idx_type n, T z) +{ + T ans; + octave_idx_type ierr = 0; + fortran_psifn (z, n, ans, ierr); + if (ierr == 0) { - double result; + // Remember that psifn and dpsifn return scales values + // When n is 1: do nothing since ((-1)**(n+1)/gamma(n+1)) == 1 + // When n is 0: change sign since ((-1)**(n+1)/gamma(n+1)) == -1 + if (n > 1) + // FIXME: xgamma here is a killer for our precision since it grows + // way too fast. + ans = ans / (std::pow (-1.0, n + 1) / gamma (double (n+1))); + else if (n == 0) + ans = -ans; + } + else if (ierr == 2) + ans = - numeric_limits::Inf (); + else // we probably never get here + ans = numeric_limits::NaN (); + + return ans; +} + +double psi (octave_idx_type n, double z) { return xpsi (n, z); } +float psi (octave_idx_type n, float z) { return xpsi (n, z); } + +Complex +rc_lgamma (double x) +{ + double result; #if defined (HAVE_LGAMMA_R) - int sgngam; - result = lgamma_r (x, &sgngam); + int sgngam; + result = lgamma_r (x, &sgngam); #else - result = std::lgamma (x); - int sgngam = signgam; + result = std::lgamma (x); + int sgngam = signgam; #endif - if (sgngam < 0) - return result + Complex (0., M_PI); - else - return result; - } + if (sgngam < 0) + return result + Complex (0., M_PI); + else + return result; +} - FloatComplex - rc_lgamma (float x) - { - float result; +FloatComplex +rc_lgamma (float x) +{ + float result; #if defined (HAVE_LGAMMAF_R) - int sgngam; - result = lgammaf_r (x, &sgngam); + int sgngam; + result = lgammaf_r (x, &sgngam); #else - result = std::lgammaf (x); - int sgngam = signgam; + result = std::lgammaf (x); + int sgngam = signgam; #endif - if (sgngam < 0) - return result + FloatComplex (0., M_PI); - else - return result; - } + if (sgngam < 0) + return result + FloatComplex (0., M_PI); + else + return result; +} - Complex rc_log1p (double x) - { - return (x < -1.0 - ? Complex (std::log (-(1.0 + x)), M_PI) - : Complex (log1p (x))); - } +Complex rc_log1p (double x) +{ + return (x < -1.0 + ? Complex (std::log (-(1.0 + x)), M_PI) + : Complex (log1p (x))); +} - FloatComplex rc_log1p (float x) - { - return (x < -1.0f - ? FloatComplex (std::log (-(1.0f + x)), M_PI) - : FloatComplex (log1p (x))); - } +FloatComplex rc_log1p (float x) +{ + return (x < -1.0f + ? FloatComplex (std::log (-(1.0f + x)), M_PI) + : FloatComplex (log1p (x))); +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/lo-specfun.h --- a/liboctave/numeric/lo-specfun.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/lo-specfun.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,322 +37,322 @@ OCTAVE_BEGIN_NAMESPACE(math) - inline double acosh (double x) { return std::acosh (x); } - inline float acosh (float x) { return std::acoshf (x); } - inline Complex acosh (const Complex& x) { return std::acosh (x); } - inline FloatComplex acosh (const FloatComplex& x) { return std::acosh (x); } +inline double acosh (double x) { return std::acosh (x); } +inline float acosh (float x) { return std::acoshf (x); } +inline Complex acosh (const Complex& x) { return std::acosh (x); } +inline FloatComplex acosh (const FloatComplex& x) { return std::acosh (x); } - extern OCTAVE_API Complex airy (const Complex& z, bool deriv, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API ComplexMatrix airy (const ComplexMatrix& z, bool deriv, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray airy (const ComplexNDArray& z, bool deriv, - bool scaled, Array& ierr); - extern OCTAVE_API FloatComplex airy (const FloatComplex& z, bool deriv, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplexMatrix airy (const FloatComplexMatrix& z, - bool deriv, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray airy (const FloatComplexNDArray& z, - bool deriv, bool scaled, Array& ierr); +extern OCTAVE_API Complex airy (const Complex& z, bool deriv, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API ComplexMatrix airy (const ComplexMatrix& z, bool deriv, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray airy (const ComplexNDArray& z, bool deriv, + bool scaled, Array& ierr); +extern OCTAVE_API FloatComplex airy (const FloatComplex& z, bool deriv, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplexMatrix airy (const FloatComplexMatrix& z, + bool deriv, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray airy (const FloatComplexNDArray& z, + bool deriv, bool scaled, Array& ierr); - inline double asinh (double x) { return std::asinh (x); } - inline float asinh (float x) { return std::asinhf (x); } - inline Complex asinh (const Complex& x) { return std::asinh (x); } - inline FloatComplex asinh (const FloatComplex& x) { return std::asinh (x); } +inline double asinh (double x) { return std::asinh (x); } +inline float asinh (float x) { return std::asinhf (x); } +inline Complex asinh (const Complex& x) { return std::asinh (x); } +inline FloatComplex asinh (const FloatComplex& x) { return std::asinh (x); } - inline double atanh (double x) { return std::atanh (x); } - inline float atanh (float x) { return std::atanhf (x); } - inline Complex atanh (const Complex& x) { return std::atanh (x); } - inline FloatComplex atanh (const FloatComplex& x) { return std::atanh (x); } +inline double atanh (double x) { return std::atanh (x); } +inline float atanh (float x) { return std::atanhf (x); } +inline Complex atanh (const Complex& x) { return std::atanh (x); } +inline FloatComplex atanh (const FloatComplex& x) { return std::atanh (x); } - extern OCTAVE_API Complex besselj (double alpha, const Complex& x, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API Complex bessely (double alpha, const Complex& x, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API Complex besseli (double alpha, const Complex& x, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API Complex besselk (double alpha, const Complex& x, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API Complex besselh1 (double alpha, const Complex& x, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API Complex besselh2 (double alpha, const Complex& x, bool scaled, - octave_idx_type& ierr); +extern OCTAVE_API Complex besselj (double alpha, const Complex& x, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API Complex bessely (double alpha, const Complex& x, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API Complex besseli (double alpha, const Complex& x, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API Complex besselk (double alpha, const Complex& x, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API Complex besselh1 (double alpha, const Complex& x, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API Complex besselh2 (double alpha, const Complex& x, bool scaled, + octave_idx_type& ierr); - extern OCTAVE_API ComplexMatrix besselj (double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix bessely (double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besseli (double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselk (double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh1 (double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh2 (double alpha, const ComplexMatrix& x, - bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselj (double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix bessely (double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besseli (double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselk (double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh1 (double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh2 (double alpha, const ComplexMatrix& x, + bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, const Complex& x, - bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, const Complex& x, + bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, - const ComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselj (const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix bessely (const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besseli (const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselk (const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh1 (const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh2 (const Matrix& alpha, + const ComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselj (double alpha, const ComplexNDArray& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray bessely (double alpha, const ComplexNDArray& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besseli (double alpha, const ComplexNDArray& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselk (double alpha, const ComplexNDArray& x, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselh1 (double alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselh2 (double alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselj (double alpha, const ComplexNDArray& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray bessely (double alpha, const ComplexNDArray& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besseli (double alpha, const ComplexNDArray& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselk (double alpha, const ComplexNDArray& x, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselh1 (double alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselh2 (double alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha, - const Complex& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha, - const Complex& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha, - const Complex& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha, - const Complex& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha, - const Complex& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha, - const Complex& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha, + const Complex& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha, + const Complex& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha, + const Complex& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha, + const Complex& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha, + const Complex& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha, + const Complex& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha, - const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselj (const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray bessely (const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besseli (const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselk (const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselh1 (const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray besselh2 (const NDArray& alpha, + const ComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselj (const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix bessely (const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besseli (const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselk (const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh1 (const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API ComplexMatrix besselh2 (const RowVector& alpha, - const ComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselj (const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix bessely (const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besseli (const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselk (const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh1 (const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API ComplexMatrix besselh2 (const RowVector& alpha, + const ComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplex besselj (float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplex bessely (float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplex besseli (float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplex besselk (float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplex besselh1 (float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplex besselh2 (float alpha, const FloatComplex& x, - bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplex besselj (float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplex bessely (float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplex besseli (float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplex besselk (float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplex besselh1 (float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplex besselh2 (float alpha, const FloatComplex& x, + bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplexMatrix besselj (float alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix bessely (float alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besseli (float alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselk (float alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh1 (float alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh2 (float alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselj (float alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix bessely (float alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besseli (float alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselk (float alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh1 (float alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh2 (float alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha, - const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha, + const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha, - const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselj (const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix bessely (const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besseli (const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselk (const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatMatrix& alpha, + const FloatComplexMatrix& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselj (float alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray bessely (float alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besseli (float alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselk (float alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselh1 (float alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselh2 (float alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselj (float alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray bessely (float alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besseli (float alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselk (float alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselh1 (float alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselh2 (float alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha, - const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha, + const FloatComplex& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha, - const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselj (const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray bessely (const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besseli (const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselk (const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselh1 (const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray besselh2 (const FloatNDArray& alpha, + const FloatComplexNDArray& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselj (const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix bessely (const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besseli (const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselk (const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatRowVector& alpha, - const FloatComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselj (const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix bessely (const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besseli (const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselk (const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh1 (const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexMatrix besselh2 (const FloatRowVector& alpha, + const FloatComplexColumnVector& x, bool scaled, Array& ierr); - extern OCTAVE_API Complex biry (const Complex& z, bool deriv, bool scaled, - octave_idx_type& ierr); - extern OCTAVE_API ComplexMatrix biry (const ComplexMatrix& z, bool deriv, - bool scaled, Array& ierr); - extern OCTAVE_API ComplexNDArray biry (const ComplexNDArray& z, bool deriv, - bool scaled, Array& ierr); - extern OCTAVE_API FloatComplex biry (const FloatComplex& z, bool deriv, - bool scaled, octave_idx_type& ierr); - extern OCTAVE_API FloatComplexMatrix biry (const FloatComplexMatrix& z, - bool deriv, bool scaled, Array& ierr); - extern OCTAVE_API FloatComplexNDArray biry (const FloatComplexNDArray& z, - bool deriv, bool scaled, Array& ierr); +extern OCTAVE_API Complex biry (const Complex& z, bool deriv, bool scaled, + octave_idx_type& ierr); +extern OCTAVE_API ComplexMatrix biry (const ComplexMatrix& z, bool deriv, + bool scaled, Array& ierr); +extern OCTAVE_API ComplexNDArray biry (const ComplexNDArray& z, bool deriv, + bool scaled, Array& ierr); +extern OCTAVE_API FloatComplex biry (const FloatComplex& z, bool deriv, + bool scaled, octave_idx_type& ierr); +extern OCTAVE_API FloatComplexMatrix biry (const FloatComplexMatrix& z, + bool deriv, bool scaled, Array& ierr); +extern OCTAVE_API FloatComplexNDArray biry (const FloatComplexNDArray& z, + bool deriv, bool scaled, Array& ierr); - inline double cbrt (double x) { return std::cbrt (x); } - inline float cbrt (float x) { return std::cbrtf (x); } +inline double cbrt (double x) { return std::cbrt (x); } +inline float cbrt (float x) { return std::cbrtf (x); } - extern OCTAVE_API double dawson (double x); - extern OCTAVE_API float dawson (float x); - extern OCTAVE_API Complex dawson (const Complex& x); - extern OCTAVE_API FloatComplex dawson (const FloatComplex& x); +extern OCTAVE_API double dawson (double x); +extern OCTAVE_API float dawson (float x); +extern OCTAVE_API Complex dawson (const Complex& x); +extern OCTAVE_API FloatComplex dawson (const FloatComplex& x); - extern OCTAVE_API void ellipj (double u, double m, double& sn, double& cn, - double& dn, double& err); - extern OCTAVE_API void ellipj (const Complex& u, double m, Complex& sn, - Complex& cn, Complex& dn, double& err); +extern OCTAVE_API void ellipj (double u, double m, double& sn, double& cn, + double& dn, double& err); +extern OCTAVE_API void ellipj (const Complex& u, double m, Complex& sn, + Complex& cn, Complex& dn, double& err); - inline double erf (double x) { return std::erf (x); } - inline float erf (float x) { return std::erff (x); } - extern OCTAVE_API Complex erf (const Complex& x); - extern OCTAVE_API FloatComplex erf (const FloatComplex& x); +inline double erf (double x) { return std::erf (x); } +inline float erf (float x) { return std::erff (x); } +extern OCTAVE_API Complex erf (const Complex& x); +extern OCTAVE_API FloatComplex erf (const FloatComplex& x); - inline double erfc (double x) { return std::erfc (x); } - inline float erfc (float x) { return std::erfcf (x); } - extern OCTAVE_API Complex erfc (const Complex& x); - extern OCTAVE_API FloatComplex erfc (const FloatComplex& x); +inline double erfc (double x) { return std::erfc (x); } +inline float erfc (float x) { return std::erfcf (x); } +extern OCTAVE_API Complex erfc (const Complex& x); +extern OCTAVE_API FloatComplex erfc (const FloatComplex& x); - extern OCTAVE_API double erfcinv (double x); - extern OCTAVE_API float erfcinv (float x); +extern OCTAVE_API double erfcinv (double x); +extern OCTAVE_API float erfcinv (float x); - extern OCTAVE_API double erfcx (double x); - extern OCTAVE_API float erfcx (float x); - extern OCTAVE_API Complex erfcx (const Complex& x); - extern OCTAVE_API FloatComplex erfcx (const FloatComplex& x); +extern OCTAVE_API double erfcx (double x); +extern OCTAVE_API float erfcx (float x); +extern OCTAVE_API Complex erfcx (const Complex& x); +extern OCTAVE_API FloatComplex erfcx (const FloatComplex& x); - extern OCTAVE_API double erfi (double x); - extern OCTAVE_API float erfi (float x); - extern OCTAVE_API Complex erfi (const Complex& x); - extern OCTAVE_API FloatComplex erfi (const FloatComplex& x); +extern OCTAVE_API double erfi (double x); +extern OCTAVE_API float erfi (float x); +extern OCTAVE_API Complex erfi (const Complex& x); +extern OCTAVE_API FloatComplex erfi (const FloatComplex& x); - extern OCTAVE_API double erfinv (double x); - extern OCTAVE_API float erfinv (float x); +extern OCTAVE_API double erfinv (double x); +extern OCTAVE_API float erfinv (float x); - inline double expm1 (double x) { return std::expm1 (x); } - inline float expm1 (float x) { return std::expm1f (x); } - extern OCTAVE_API Complex expm1 (const Complex& x); - extern OCTAVE_API FloatComplex expm1 (const FloatComplex& x); +inline double expm1 (double x) { return std::expm1 (x); } +inline float expm1 (float x) { return std::expm1f (x); } +extern OCTAVE_API Complex expm1 (const Complex& x); +extern OCTAVE_API FloatComplex expm1 (const FloatComplex& x); - extern OCTAVE_API double gamma (double x); - extern OCTAVE_API float gamma (float x); +extern OCTAVE_API double gamma (double x); +extern OCTAVE_API float gamma (float x); - inline double lgamma (double x) { return std::lgamma (x); } - inline float lgamma (float x) { return std::lgammaf (x); } +inline double lgamma (double x) { return std::lgamma (x); } +inline float lgamma (float x) { return std::lgammaf (x); } - inline double log1p (double x) { return std::log1p (x); } - inline float log1p (float x) { return std::log1pf (x); } - extern OCTAVE_API Complex log1p (const Complex& x); - extern OCTAVE_API FloatComplex log1p (const FloatComplex& x); +inline double log1p (double x) { return std::log1p (x); } +inline float log1p (float x) { return std::log1pf (x); } +extern OCTAVE_API Complex log1p (const Complex& x); +extern OCTAVE_API FloatComplex log1p (const FloatComplex& x); - extern OCTAVE_API double psi (double x); - extern OCTAVE_API float psi (float x); - extern OCTAVE_API Complex psi (const Complex& x); - extern OCTAVE_API FloatComplex psi (const FloatComplex& x); - extern OCTAVE_API double psi (octave_idx_type n, double z); - extern OCTAVE_API float psi (octave_idx_type n, float z); +extern OCTAVE_API double psi (double x); +extern OCTAVE_API float psi (float x); +extern OCTAVE_API Complex psi (const Complex& x); +extern OCTAVE_API FloatComplex psi (const FloatComplex& x); +extern OCTAVE_API double psi (octave_idx_type n, double z); +extern OCTAVE_API float psi (octave_idx_type n, float z); - extern OCTAVE_API Complex rc_lgamma (double x); - extern OCTAVE_API FloatComplex rc_lgamma (float x); +extern OCTAVE_API Complex rc_lgamma (double x); +extern OCTAVE_API FloatComplex rc_lgamma (float x); - extern OCTAVE_API Complex rc_log1p (double x); - extern OCTAVE_API FloatComplex rc_log1p (float x); +extern OCTAVE_API Complex rc_log1p (double x); +extern OCTAVE_API FloatComplex rc_log1p (float x); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/lu.cc --- a/liboctave/numeric/lu.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/lu.cc Thu Dec 01 20:05:44 2022 -0800 @@ -48,878 +48,878 @@ OCTAVE_BEGIN_NAMESPACE(math) - // FIXME: PermMatrix::col_perm_vec returns Array - // but m_ipvt is an Array. This could cause - // trouble for large arrays if octave_f77_int_type is 32-bits but - // octave_idx_type is 64. Since this constructor is called from - // Fluupdate, it could be given values that are out of range. We - // should ensure that the values are within range here. - - template - lu::lu (const T& l, const T& u, const PermMatrix& p) - : m_a_fact (u), m_L (l), m_ipvt (p.transpose ().col_perm_vec ()) - { - if (l.columns () != u.rows ()) - (*current_liboctave_error_handler) ("lu: dimension mismatch"); - } +// FIXME: PermMatrix::col_perm_vec returns Array +// but m_ipvt is an Array. This could cause +// trouble for large arrays if octave_f77_int_type is 32-bits but +// octave_idx_type is 64. Since this constructor is called from +// Fluupdate, it could be given values that are out of range. We +// should ensure that the values are within range here. - template - bool - lu::packed (void) const - { - return m_L.dims () == dim_vector (); - } +template +lu::lu (const T& l, const T& u, const PermMatrix& p) + : m_a_fact (u), m_L (l), m_ipvt (p.transpose ().col_perm_vec ()) +{ + if (l.columns () != u.rows ()) + (*current_liboctave_error_handler) ("lu: dimension mismatch"); +} - template - void - lu::unpack (void) - { - if (packed ()) - { - m_L = L (); - m_a_fact = U (); // FIXME: sub-optimal +template +bool +lu::packed (void) const +{ + return m_L.dims () == dim_vector (); +} - // FIXME: getp returns Array but m_ipvt is - // Array. However, getp produces its - // result from a valid m_ipvt array so validation should not be - // necessary. OTOH, it might be better to have a version of - // getp that doesn't cause us to convert from - // Array to Array and - // back again. - - m_ipvt = getp (); - } - } - - template - T - lu::L (void) const +template +void +lu::unpack (void) +{ + if (packed ()) { - if (packed ()) - { - octave_idx_type a_nr = m_a_fact.rows (); - octave_idx_type a_nc = m_a_fact.columns (); - octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc); + m_L = L (); + m_a_fact = U (); // FIXME: sub-optimal - T l (a_nr, mn, ELT_T (0.0)); + // FIXME: getp returns Array but m_ipvt is + // Array. However, getp produces its + // result from a valid m_ipvt array so validation should not be + // necessary. OTOH, it might be better to have a version of + // getp that doesn't cause us to convert from + // Array to Array and + // back again. - for (octave_idx_type i = 0; i < a_nr; i++) - { - if (i < a_nc) - l.xelem (i, i) = 1.0; + m_ipvt = getp (); + } +} - for (octave_idx_type j = 0; j < (i < a_nc ? i : a_nc); j++) - l.xelem (i, j) = m_a_fact.xelem (i, j); - } +template +T +lu::L (void) const +{ + if (packed ()) + { + octave_idx_type a_nr = m_a_fact.rows (); + octave_idx_type a_nc = m_a_fact.columns (); + octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc); - return l; - } - else - return m_L; - } + T l (a_nr, mn, ELT_T (0.0)); - template - T - lu::U (void) const - { - if (packed ()) + for (octave_idx_type i = 0; i < a_nr; i++) { - octave_idx_type a_nr = m_a_fact.rows (); - octave_idx_type a_nc = m_a_fact.columns (); - octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc); + if (i < a_nc) + l.xelem (i, i) = 1.0; - T u (mn, a_nc, ELT_T (0.0)); + for (octave_idx_type j = 0; j < (i < a_nc ? i : a_nc); j++) + l.xelem (i, j) = m_a_fact.xelem (i, j); + } - for (octave_idx_type i = 0; i < mn; i++) - { - for (octave_idx_type j = i; j < a_nc; j++) - u.xelem (i, j) = m_a_fact.xelem (i, j); - } - - return u; - } - else - return m_a_fact; + return l; } + else + return m_L; +} - template - T - lu::Y (void) const +template +T +lu::U (void) const +{ + if (packed ()) { - if (! packed ()) - (*current_liboctave_error_handler) - ("lu: Y () not implemented for unpacked form"); + octave_idx_type a_nr = m_a_fact.rows (); + octave_idx_type a_nc = m_a_fact.columns (); + octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc); - return m_a_fact; - } + T u (mn, a_nc, ELT_T (0.0)); - template - Array - lu::getp (void) const - { - if (packed ()) + for (octave_idx_type i = 0; i < mn; i++) { - octave_idx_type a_nr = m_a_fact.rows (); + for (octave_idx_type j = i; j < a_nc; j++) + u.xelem (i, j) = m_a_fact.xelem (i, j); + } - Array pvt (dim_vector (a_nr, 1)); - - for (octave_idx_type i = 0; i < a_nr; i++) - pvt.xelem (i) = i; - - for (octave_idx_type i = 0; i < m_ipvt.numel (); i++) - { - octave_idx_type k = m_ipvt.xelem (i); + return u; + } + else + return m_a_fact; +} - if (k != i) - { - octave_idx_type tmp = pvt.xelem (k); - pvt.xelem (k) = pvt.xelem (i); - pvt.xelem (i) = tmp; - } - } +template +T +lu::Y (void) const +{ + if (! packed ()) + (*current_liboctave_error_handler) + ("lu: Y () not implemented for unpacked form"); - return pvt; - } - else - return m_ipvt; - } + return m_a_fact; +} - template - PermMatrix - lu::P (void) const - { - return PermMatrix (getp (), false); - } - - template - ColumnVector - lu::P_vec (void) const +template +Array +lu::getp (void) const +{ + if (packed ()) { octave_idx_type a_nr = m_a_fact.rows (); - ColumnVector p (a_nr); - - Array pvt = getp (); + Array pvt (dim_vector (a_nr, 1)); for (octave_idx_type i = 0; i < a_nr; i++) - p.xelem (i) = static_cast (pvt.xelem (i) + 1); + pvt.xelem (i) = i; - return p; - } + for (octave_idx_type i = 0; i < m_ipvt.numel (); i++) + { + octave_idx_type k = m_ipvt.xelem (i); - template - bool - lu::regular (void) const - { - bool retval = true; - - octave_idx_type k = std::min (m_a_fact.rows (), m_a_fact.columns ()); - - for (octave_idx_type i = 0; i < k; i++) - { - if (m_a_fact(i, i) == ELT_T ()) + if (k != i) { - retval = false; - break; + octave_idx_type tmp = pvt.xelem (k); + pvt.xelem (k) = pvt.xelem (i); + pvt.xelem (i) = tmp; } } - return retval; + return pvt; } + else + return m_ipvt; +} + +template +PermMatrix +lu::P (void) const +{ + return PermMatrix (getp (), false); +} + +template +ColumnVector +lu::P_vec (void) const +{ + octave_idx_type a_nr = m_a_fact.rows (); + + ColumnVector p (a_nr); + + Array pvt = getp (); + + for (octave_idx_type i = 0; i < a_nr; i++) + p.xelem (i) = static_cast (pvt.xelem (i) + 1); + + return p; +} + +template +bool +lu::regular (void) const +{ + bool retval = true; + + octave_idx_type k = std::min (m_a_fact.rows (), m_a_fact.columns ()); + + for (octave_idx_type i = 0; i < k; i++) + { + if (m_a_fact(i, i) == ELT_T ()) + { + retval = false; + break; + } + } + + return retval; +} #if ! defined (HAVE_QRUPDATE_LUU) - template - void - lu::update (const VT&, const VT&) - { - (*current_liboctave_error_handler) - ("luupdate: support for qrupdate with LU updates " - "was unavailable or disabled when liboctave was built"); - } +template +void +lu::update (const VT&, const VT&) +{ + (*current_liboctave_error_handler) + ("luupdate: support for qrupdate with LU updates " + "was unavailable or disabled when liboctave was built"); +} - template - void - lu::update (const T&, const T&) - { - (*current_liboctave_error_handler) - ("luupdate: support for qrupdate with LU updates " - "was unavailable or disabled when liboctave was built"); - } +template +void +lu::update (const T&, const T&) +{ + (*current_liboctave_error_handler) + ("luupdate: support for qrupdate with LU updates " + "was unavailable or disabled when liboctave was built"); +} - template - void - lu::update_piv (const VT&, const VT&) - { - (*current_liboctave_error_handler) - ("luupdate: support for qrupdate with LU updates " - "was unavailable or disabled when liboctave was built"); - } +template +void +lu::update_piv (const VT&, const VT&) +{ + (*current_liboctave_error_handler) + ("luupdate: support for qrupdate with LU updates " + "was unavailable or disabled when liboctave was built"); +} - template - void - lu::update_piv (const T&, const T&) - { - (*current_liboctave_error_handler) - ("luupdate: support for qrupdate with LU updates " - "was unavailable or disabled when liboctave was built"); - } +template +void +lu::update_piv (const T&, const T&) +{ + (*current_liboctave_error_handler) + ("luupdate: support for qrupdate with LU updates " + "was unavailable or disabled when liboctave was built"); +} #endif - // Specializations. +// Specializations. - template <> - OCTAVE_API - lu::lu (const Matrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.columns ()); - F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); +template <> +OCTAVE_API +lu::lu (const Matrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.columns ()); + F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); - m_ipvt.resize (dim_vector (mn, 1)); - F77_INT *pipvt = m_ipvt.fortran_vec (); + m_ipvt.resize (dim_vector (mn, 1)); + F77_INT *pipvt = m_ipvt.fortran_vec (); - m_a_fact = a; - double *tmp_data = m_a_fact.fortran_vec (); + m_a_fact = a; + double *tmp_data = m_a_fact.fortran_vec (); - F77_INT info = 0; + F77_INT info = 0; - F77_XFCN (dgetrf, DGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info)); + F77_XFCN (dgetrf, DGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info)); - for (F77_INT i = 0; i < mn; i++) - pipvt[i] -= 1; - } + for (F77_INT i = 0; i < mn; i++) + pipvt[i] -= 1; +} #if defined (HAVE_QRUPDATE_LUU) - template <> - OCTAVE_API void - lu::update (const ColumnVector& u, const ColumnVector& v) - { - if (packed ()) - unpack (); +template <> +OCTAVE_API void +lu::update (const ColumnVector& u, const ColumnVector& v) +{ + if (packed ()) + unpack (); - Matrix& l = m_L; - Matrix& r = m_a_fact; + Matrix& l = m_L; + Matrix& r = m_a_fact; - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + ColumnVector utmp = u; + ColumnVector vtmp = v; + F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (), + k, utmp.fortran_vec (), vtmp.fortran_vec ())); +} - ColumnVector utmp = u; - ColumnVector vtmp = v; - F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (), - k, utmp.fortran_vec (), vtmp.fortran_vec ())); - } +template <> +OCTAVE_API void +lu::update (const Matrix& u, const Matrix& v) +{ + if (packed ()) + unpack (); + + Matrix& l = m_L; + Matrix& r = m_a_fact; - template <> - OCTAVE_API void - lu::update (const Matrix& u, const Matrix& v) + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); + + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); + + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + + for (volatile F77_INT i = 0; i < u_nc; i++) { - if (packed ()) - unpack (); - - Matrix& l = m_L; - Matrix& r = m_a_fact; - - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + ColumnVector utmp = u.column (i); + ColumnVector vtmp = v.column (i); + F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (), + m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec ())); + } +} - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); +template <> +OCTAVE_API void +lu::update_piv (const ColumnVector& u, const ColumnVector& v) +{ + if (packed ()) + unpack (); - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); - - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + Matrix& l = m_L; + Matrix& r = m_a_fact; - for (volatile F77_INT i = 0; i < u_nc; i++) - { - ColumnVector utmp = u.column (i); - ColumnVector vtmp = v.column (i); - F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (), - m, r.fortran_vec (), k, - utmp.fortran_vec (), vtmp.fortran_vec ())); - } - } + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - template <> - OCTAVE_API void - lu::update_piv (const ColumnVector& u, const ColumnVector& v) - { - if (packed ()) - unpack (); + ColumnVector utmp = u; + ColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (double, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (), + m, r.fortran_vec (), k, + m_ipvt.fortran_vec (), + utmp.data (), vtmp.data (), w)); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} - Matrix& l = m_L; - Matrix& r = m_a_fact; +template <> +OCTAVE_API void +lu::update_piv (const Matrix& u, const Matrix& v) +{ + if (packed ()) + unpack (); - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + Matrix& l = m_L; + Matrix& r = m_a_fact; - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); + + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - ColumnVector utmp = u; - ColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (double, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + OCTAVE_LOCAL_BUFFER (double, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + for (volatile F77_INT i = 0; i < u_nc; i++) + { + ColumnVector utmp = u.column (i); + ColumnVector vtmp = v.column (i); F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (), k, m_ipvt.fortran_vec (), utmp.data (), vtmp.data (), w)); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement } - - template <> - OCTAVE_API void - lu::update_piv (const Matrix& u, const Matrix& v) - { - if (packed ()) - unpack (); - - Matrix& l = m_L; - Matrix& r = m_a_fact; - - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); - - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); - - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); - - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - OCTAVE_LOCAL_BUFFER (double, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment - for (volatile F77_INT i = 0; i < u_nc; i++) - { - ColumnVector utmp = u.column (i); - ColumnVector vtmp = v.column (i); - F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (), - m, r.fortran_vec (), k, - m_ipvt.fortran_vec (), - utmp.data (), vtmp.data (), w)); - } - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement - } + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} #endif - template <> - OCTAVE_API - lu::lu (const FloatMatrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.columns ()); - F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); +template <> +OCTAVE_API +lu::lu (const FloatMatrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.columns ()); + F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); - m_ipvt.resize (dim_vector (mn, 1)); - F77_INT *pipvt = m_ipvt.fortran_vec (); + m_ipvt.resize (dim_vector (mn, 1)); + F77_INT *pipvt = m_ipvt.fortran_vec (); - m_a_fact = a; - float *tmp_data = m_a_fact.fortran_vec (); + m_a_fact = a; + float *tmp_data = m_a_fact.fortran_vec (); - F77_INT info = 0; + F77_INT info = 0; - F77_XFCN (sgetrf, SGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info)); + F77_XFCN (sgetrf, SGETRF, (a_nr, a_nc, tmp_data, a_nr, pipvt, info)); - for (F77_INT i = 0; i < mn; i++) - pipvt[i] -= 1; - } + for (F77_INT i = 0; i < mn; i++) + pipvt[i] -= 1; +} #if defined (HAVE_QRUPDATE_LUU) - template <> - OCTAVE_API void - lu::update (const FloatColumnVector& u, - const FloatColumnVector& v) - { - if (packed ()) - unpack (); +template <> +OCTAVE_API void +lu::update (const FloatColumnVector& u, + const FloatColumnVector& v) +{ + if (packed ()) + unpack (); + + FloatMatrix& l = m_L; + FloatMatrix& r = m_a_fact; - FloatMatrix& l = m_L; - FloatMatrix& r = m_a_fact; + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + + FloatColumnVector utmp = u; + FloatColumnVector vtmp = v; + F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (), + m, r.fortran_vec (), k, + utmp.fortran_vec (), vtmp.fortran_vec ())); +} - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); +template <> +OCTAVE_API void +lu::update (const FloatMatrix& u, const FloatMatrix& v) +{ + if (packed ()) + unpack (); + + FloatMatrix& l = m_L; + FloatMatrix& r = m_a_fact; + + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); + + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - FloatColumnVector utmp = u; - FloatColumnVector vtmp = v; + for (volatile F77_INT i = 0; i < u_nc; i++) + { + FloatColumnVector utmp = u.column (i); + FloatColumnVector vtmp = v.column (i); F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (), k, utmp.fortran_vec (), vtmp.fortran_vec ())); } +} - template <> - OCTAVE_API void - lu::update (const FloatMatrix& u, const FloatMatrix& v) - { - if (packed ()) - unpack (); - - FloatMatrix& l = m_L; - FloatMatrix& r = m_a_fact; +template <> +OCTAVE_API void +lu::update_piv (const FloatColumnVector& u, + const FloatColumnVector& v) +{ + if (packed ()) + unpack (); - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + FloatMatrix& l = m_L; + FloatMatrix& r = m_a_fact; - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - for (volatile F77_INT i = 0; i < u_nc; i++) - { - FloatColumnVector utmp = u.column (i); - FloatColumnVector vtmp = v.column (i); - F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (), - m, r.fortran_vec (), k, - utmp.fortran_vec (), vtmp.fortran_vec ())); - } - } + FloatColumnVector utmp = u; + FloatColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (float, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (), + m, r.fortran_vec (), k, + m_ipvt.fortran_vec (), + utmp.data (), vtmp.data (), w)); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} - template <> - OCTAVE_API void - lu::update_piv (const FloatColumnVector& u, - const FloatColumnVector& v) - { - if (packed ()) - unpack (); +template <> +OCTAVE_API void +lu::update_piv (const FloatMatrix& u, const FloatMatrix& v) +{ + if (packed ()) + unpack (); - FloatMatrix& l = m_L; - FloatMatrix& r = m_a_fact; + FloatMatrix& l = m_L; + FloatMatrix& r = m_a_fact; - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); + + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - FloatColumnVector utmp = u; - FloatColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (float, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + OCTAVE_LOCAL_BUFFER (float, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + for (volatile F77_INT i = 0; i < u_nc; i++) + { + FloatColumnVector utmp = u.column (i); + FloatColumnVector vtmp = v.column (i); F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (), k, m_ipvt.fortran_vec (), utmp.data (), vtmp.data (), w)); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement } - - template <> - OCTAVE_API void - lu::update_piv (const FloatMatrix& u, const FloatMatrix& v) - { - if (packed ()) - unpack (); - - FloatMatrix& l = m_L; - FloatMatrix& r = m_a_fact; - - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); - - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); - - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); - - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - OCTAVE_LOCAL_BUFFER (float, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment - for (volatile F77_INT i = 0; i < u_nc; i++) - { - FloatColumnVector utmp = u.column (i); - FloatColumnVector vtmp = v.column (i); - F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (), - m, r.fortran_vec (), k, - m_ipvt.fortran_vec (), - utmp.data (), vtmp.data (), w)); - } - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement - } + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} #endif - template <> - OCTAVE_API - lu::lu (const ComplexMatrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.columns ()); - F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); +template <> +OCTAVE_API +lu::lu (const ComplexMatrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.columns ()); + F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); - m_ipvt.resize (dim_vector (mn, 1)); - F77_INT *pipvt = m_ipvt.fortran_vec (); + m_ipvt.resize (dim_vector (mn, 1)); + F77_INT *pipvt = m_ipvt.fortran_vec (); - m_a_fact = a; - Complex *tmp_data = m_a_fact.fortran_vec (); + m_a_fact = a; + Complex *tmp_data = m_a_fact.fortran_vec (); - F77_INT info = 0; + F77_INT info = 0; - F77_XFCN (zgetrf, ZGETRF, (a_nr, a_nc, F77_DBLE_CMPLX_ARG (tmp_data), - a_nr, pipvt, info)); + F77_XFCN (zgetrf, ZGETRF, (a_nr, a_nc, F77_DBLE_CMPLX_ARG (tmp_data), + a_nr, pipvt, info)); - for (F77_INT i = 0; i < mn; i++) - pipvt[i] -= 1; - } + for (F77_INT i = 0; i < mn; i++) + pipvt[i] -= 1; +} #if defined (HAVE_QRUPDATE_LUU) - template <> - OCTAVE_API void - lu::update (const ComplexColumnVector& u, - const ComplexColumnVector& v) - { - if (packed ()) - unpack (); +template <> +OCTAVE_API void +lu::update (const ComplexColumnVector& u, + const ComplexColumnVector& v) +{ + if (packed ()) + unpack (); + + ComplexMatrix& l = m_L; + ComplexMatrix& r = m_a_fact; - ComplexMatrix& l = m_L; - ComplexMatrix& r = m_a_fact; + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + + ComplexColumnVector utmp = u; + ComplexColumnVector vtmp = v; + F77_XFCN (zlu1up, ZLU1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()), m, + F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k, + F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), + F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()))); +} - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); +template <> +OCTAVE_API void +lu::update (const ComplexMatrix& u, const ComplexMatrix& v) +{ + if (packed ()) + unpack (); - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + ComplexMatrix& l = m_L; + ComplexMatrix& r = m_a_fact; + + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); + + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); + + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - ComplexColumnVector utmp = u; - ComplexColumnVector vtmp = v; - F77_XFCN (zlu1up, ZLU1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()), m, - F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k, + for (volatile F77_INT i = 0; i < u_nc; i++) + { + ComplexColumnVector utmp = u.column (i); + ComplexColumnVector vtmp = v.column (i); + F77_XFCN (zlu1up, ZLU1UP, (m, n, + F77_DBLE_CMPLX_ARG (l.fortran_vec ()), + m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), + k, F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()))); } +} - template <> - OCTAVE_API void - lu::update (const ComplexMatrix& u, const ComplexMatrix& v) - { - if (packed ()) - unpack (); +template <> +OCTAVE_API void +lu::update_piv (const ComplexColumnVector& u, + const ComplexColumnVector& v) +{ + if (packed ()) + unpack (); - ComplexMatrix& l = m_L; - ComplexMatrix& r = m_a_fact; + ComplexMatrix& l = m_L; + ComplexMatrix& r = m_a_fact; + + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); - - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); - - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + ComplexColumnVector utmp = u; + ComplexColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (Complex, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + F77_XFCN (zlup1up, ZLUP1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()), + m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k, + m_ipvt.fortran_vec (), + F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), + F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()), + F77_DBLE_CMPLX_ARG (w))); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} - for (volatile F77_INT i = 0; i < u_nc; i++) - { - ComplexColumnVector utmp = u.column (i); - ComplexColumnVector vtmp = v.column (i); - F77_XFCN (zlu1up, ZLU1UP, (m, n, - F77_DBLE_CMPLX_ARG (l.fortran_vec ()), - m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), - k, - F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), - F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()))); - } - } +template <> +OCTAVE_API void +lu::update_piv (const ComplexMatrix& u, + const ComplexMatrix& v) +{ + if (packed ()) + unpack (); - template <> - OCTAVE_API void - lu::update_piv (const ComplexColumnVector& u, - const ComplexColumnVector& v) - { - if (packed ()) - unpack (); + ComplexMatrix& l = m_L; + ComplexMatrix& r = m_a_fact; + + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); - ComplexMatrix& l = m_L; - ComplexMatrix& r = m_a_fact; + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); - - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - ComplexColumnVector utmp = u; - ComplexColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (Complex, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment - F77_XFCN (zlup1up, ZLUP1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()), - m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k, - m_ipvt.fortran_vec (), + OCTAVE_LOCAL_BUFFER (Complex, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + for (volatile F77_INT i = 0; i < u_nc; i++) + { + ComplexColumnVector utmp = u.column (i); + ComplexColumnVector vtmp = v.column (i); + F77_XFCN (zlup1up, ZLUP1UP, (m, n, + F77_DBLE_CMPLX_ARG (l.fortran_vec ()), + m, + F77_DBLE_CMPLX_ARG (r.fortran_vec ()), + k, m_ipvt.fortran_vec (), F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()), F77_DBLE_CMPLX_ARG (w))); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement } - - template <> - OCTAVE_API void - lu::update_piv (const ComplexMatrix& u, - const ComplexMatrix& v) - { - if (packed ()) - unpack (); - - ComplexMatrix& l = m_L; - ComplexMatrix& r = m_a_fact; - - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); - - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); - - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); - - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - OCTAVE_LOCAL_BUFFER (Complex, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment - for (volatile F77_INT i = 0; i < u_nc; i++) - { - ComplexColumnVector utmp = u.column (i); - ComplexColumnVector vtmp = v.column (i); - F77_XFCN (zlup1up, ZLUP1UP, (m, n, - F77_DBLE_CMPLX_ARG (l.fortran_vec ()), - m, - F77_DBLE_CMPLX_ARG (r.fortran_vec ()), - k, m_ipvt.fortran_vec (), - F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), - F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()), - F77_DBLE_CMPLX_ARG (w))); - } - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement - } + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} #endif - template <> - OCTAVE_API - lu::lu (const FloatComplexMatrix& a) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.columns ()); - F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); +template <> +OCTAVE_API +lu::lu (const FloatComplexMatrix& a) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.columns ()); + F77_INT mn = (a_nr < a_nc ? a_nr : a_nc); - m_ipvt.resize (dim_vector (mn, 1)); - F77_INT *pipvt = m_ipvt.fortran_vec (); + m_ipvt.resize (dim_vector (mn, 1)); + F77_INT *pipvt = m_ipvt.fortran_vec (); - m_a_fact = a; - FloatComplex *tmp_data = m_a_fact.fortran_vec (); + m_a_fact = a; + FloatComplex *tmp_data = m_a_fact.fortran_vec (); - F77_INT info = 0; + F77_INT info = 0; - F77_XFCN (cgetrf, CGETRF, (a_nr, a_nc, F77_CMPLX_ARG (tmp_data), a_nr, - pipvt, info)); + F77_XFCN (cgetrf, CGETRF, (a_nr, a_nc, F77_CMPLX_ARG (tmp_data), a_nr, + pipvt, info)); - for (F77_INT i = 0; i < mn; i++) - pipvt[i] -= 1; - } + for (F77_INT i = 0; i < mn; i++) + pipvt[i] -= 1; +} #if defined (HAVE_QRUPDATE_LUU) - template <> - OCTAVE_API void - lu::update (const FloatComplexColumnVector& u, - const FloatComplexColumnVector& v) - { - if (packed ()) - unpack (); +template <> +OCTAVE_API void +lu::update (const FloatComplexColumnVector& u, + const FloatComplexColumnVector& v) +{ + if (packed ()) + unpack (); + + FloatComplexMatrix& l = m_L; + FloatComplexMatrix& r = m_a_fact; - FloatComplexMatrix& l = m_L; - FloatComplexMatrix& r = m_a_fact; + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + + FloatComplexColumnVector utmp = u; + FloatComplexColumnVector vtmp = v; + F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), m, + F77_CMPLX_ARG (r.fortran_vec ()), k, + F77_CMPLX_ARG (utmp.fortran_vec ()), + F77_CMPLX_ARG (vtmp.fortran_vec ()))); +} - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); +template <> +OCTAVE_API void +lu::update (const FloatComplexMatrix& u, + const FloatComplexMatrix& v) +{ + if (packed ()) + unpack (); - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + FloatComplexMatrix& l = m_L; + FloatComplexMatrix& r = m_a_fact; + + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); + + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); - FloatComplexColumnVector utmp = u; - FloatComplexColumnVector vtmp = v; - F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), m, - F77_CMPLX_ARG (r.fortran_vec ()), k, + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + + for (volatile F77_INT i = 0; i < u_nc; i++) + { + FloatComplexColumnVector utmp = u.column (i); + FloatComplexColumnVector vtmp = v.column (i); + F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), + m, F77_CMPLX_ARG (r.fortran_vec ()), k, F77_CMPLX_ARG (utmp.fortran_vec ()), F77_CMPLX_ARG (vtmp.fortran_vec ()))); } +} - template <> - OCTAVE_API void - lu::update (const FloatComplexMatrix& u, - const FloatComplexMatrix& v) - { - if (packed ()) - unpack (); - - FloatComplexMatrix& l = m_L; - FloatComplexMatrix& r = m_a_fact; +template <> +OCTAVE_API void +lu::update_piv (const FloatComplexColumnVector& u, + const FloatComplexColumnVector& v) +{ + if (packed ()) + unpack (); - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); + FloatComplexMatrix& l = m_L; + FloatComplexMatrix& r = m_a_fact; - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - for (volatile F77_INT i = 0; i < u_nc; i++) - { - FloatComplexColumnVector utmp = u.column (i); - FloatComplexColumnVector vtmp = v.column (i); - F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), - m, F77_CMPLX_ARG (r.fortran_vec ()), k, - F77_CMPLX_ARG (utmp.fortran_vec ()), - F77_CMPLX_ARG (vtmp.fortran_vec ()))); - } - } + FloatComplexColumnVector utmp = u; + FloatComplexColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), + m, F77_CMPLX_ARG (r.fortran_vec ()), k, + m_ipvt.fortran_vec (), + F77_CONST_CMPLX_ARG (utmp.data ()), + F77_CONST_CMPLX_ARG (vtmp.data ()), + F77_CMPLX_ARG (w))); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} - template <> - OCTAVE_API void - lu::update_piv (const FloatComplexColumnVector& u, - const FloatComplexColumnVector& v) +template <> +OCTAVE_API void +lu::update_piv (const FloatComplexMatrix& u, + const FloatComplexMatrix& v) +{ + if (packed ()) + unpack (); + + FloatComplexMatrix& l = m_L; + FloatComplexMatrix& r = m_a_fact; + + F77_INT m = to_f77_int (l.rows ()); + F77_INT n = to_f77_int (r.columns ()); + F77_INT k = to_f77_int (l.columns ()); + + F77_INT u_nr = to_f77_int (u.rows ()); + F77_INT u_nc = to_f77_int (u.columns ()); + + F77_INT v_nr = to_f77_int (v.rows ()); + F77_INT v_nc = to_f77_int (v.columns ()); + + if (u_nr != m || v_nr != n || u_nc != v_nc) + (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); + + OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); + for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + for (volatile F77_INT i = 0; i < u_nc; i++) { - if (packed ()) - unpack (); - - FloatComplexMatrix& l = m_L; - FloatComplexMatrix& r = m_a_fact; - - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); - - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); - - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - FloatComplexColumnVector utmp = u; - FloatComplexColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment + FloatComplexColumnVector utmp = u.column (i); + FloatComplexColumnVector vtmp = v.column (i); F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), m, F77_CMPLX_ARG (r.fortran_vec ()), k, m_ipvt.fortran_vec (), F77_CONST_CMPLX_ARG (utmp.data ()), F77_CONST_CMPLX_ARG (vtmp.data ()), F77_CMPLX_ARG (w))); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement } - - template <> - OCTAVE_API void - lu::update_piv (const FloatComplexMatrix& u, - const FloatComplexMatrix& v) - { - if (packed ()) - unpack (); - - FloatComplexMatrix& l = m_L; - FloatComplexMatrix& r = m_a_fact; - - F77_INT m = to_f77_int (l.rows ()); - F77_INT n = to_f77_int (r.columns ()); - F77_INT k = to_f77_int (l.columns ()); - - F77_INT u_nr = to_f77_int (u.rows ()); - F77_INT u_nc = to_f77_int (u.columns ()); - - F77_INT v_nr = to_f77_int (v.rows ()); - F77_INT v_nc = to_f77_int (v.columns ()); - - if (u_nr != m || v_nr != n || u_nc != v_nc) - (*current_liboctave_error_handler) ("luupdate: dimensions mismatch"); - - OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); - for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment - for (volatile F77_INT i = 0; i < u_nc; i++) - { - FloatComplexColumnVector utmp = u.column (i); - FloatComplexColumnVector vtmp = v.column (i); - F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), - m, F77_CMPLX_ARG (r.fortran_vec ()), k, - m_ipvt.fortran_vec (), - F77_CONST_CMPLX_ARG (utmp.data ()), - F77_CONST_CMPLX_ARG (vtmp.data ()), - F77_CMPLX_ARG (w))); - } - for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement - } + for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement +} #endif - // Instantiations we need. +// Instantiations we need. - template class lu; +template class lu; - template class lu; +template class lu; - template class lu; +template class lu; - template class lu; +template class lu; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/lu.h --- a/liboctave/numeric/lu.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/lu.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,76 +36,76 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - lu - { - public: +template +class +lu +{ +public: - typedef typename T::column_vector_type VT; - typedef typename T::element_type ELT_T; + typedef typename T::column_vector_type VT; + typedef typename T::element_type ELT_T; - lu (void) - : m_a_fact (), m_L (), m_ipvt () { } - - OCTAVE_API lu (const T& a); + lu (void) + : m_a_fact (), m_L (), m_ipvt () { } - lu (const lu& a) - : m_a_fact (a.m_a_fact), m_L (a.m_L), m_ipvt (a.m_ipvt) { } + OCTAVE_API lu (const T& a); + + lu (const lu& a) + : m_a_fact (a.m_a_fact), m_L (a.m_L), m_ipvt (a.m_ipvt) { } - OCTAVE_API lu (const T& l, const T& u, const PermMatrix& p); + OCTAVE_API lu (const T& l, const T& u, const PermMatrix& p); - lu& operator = (const lu& a) + lu& operator = (const lu& a) + { + if (this != &a) { - if (this != &a) - { - m_a_fact = a.m_a_fact; - m_L = a.m_L; - m_ipvt = a.m_ipvt; - } - - return *this; + m_a_fact = a.m_a_fact; + m_L = a.m_L; + m_ipvt = a.m_ipvt; } - virtual ~lu (void) = default; - - OCTAVE_API bool packed (void) const; + return *this; + } - OCTAVE_API void unpack (void); + virtual ~lu (void) = default; - OCTAVE_API T L (void) const; + OCTAVE_API bool packed (void) const; - OCTAVE_API T U (void) const; + OCTAVE_API void unpack (void); - OCTAVE_API T Y (void) const; + OCTAVE_API T L (void) const; - OCTAVE_API PermMatrix P (void) const; + OCTAVE_API T U (void) const; + + OCTAVE_API T Y (void) const; - OCTAVE_API ColumnVector P_vec (void) const; + OCTAVE_API PermMatrix P (void) const; - OCTAVE_API bool regular (void) const; + OCTAVE_API ColumnVector P_vec (void) const; - OCTAVE_API void update (const VT& u, const VT& v); + OCTAVE_API bool regular (void) const; - OCTAVE_API void update (const T& u, const T& v); + OCTAVE_API void update (const VT& u, const VT& v); - OCTAVE_API void update_piv (const VT& u, const VT& v); + OCTAVE_API void update (const T& u, const T& v); - OCTAVE_API void update_piv (const T& u, const T& v); + OCTAVE_API void update_piv (const VT& u, const VT& v); - protected: + OCTAVE_API void update_piv (const T& u, const T& v); + +protected: - // The result of getp is passed to other Octave Matrix functions, - // so we use octave_idx_type. - OCTAVE_API Array getp (void) const; + // The result of getp is passed to other Octave Matrix functions, + // so we use octave_idx_type. + OCTAVE_API Array getp (void) const; - T m_a_fact; - T m_L; + T m_a_fact; + T m_L; - // This is internal storage that is passed to Fortran, - // so we need a Fortran INTEGER. - Array m_ipvt; - }; + // This is internal storage that is passed to Fortran, + // so we need a Fortran INTEGER. + Array m_ipvt; +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-convn.cc --- a/liboctave/numeric/oct-convn.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-convn.cc Thu Dec 01 20:05:44 2022 -0800 @@ -52,14 +52,14 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // 2d convolution with a matrix kernel. - template - static void - convolve_2d (const T *a, F77_INT ma, F77_INT na, - const R *b, F77_INT mb, F77_INT nb, - T *c, bool inner); +// 2d convolution with a matrix kernel. +template +static void +convolve_2d (const T *a, F77_INT ma, F77_INT na, + const R *b, F77_INT mb, F77_INT nb, + T *c, bool inner); - // Forward instances to our Fortran implementations. +// Forward instances to our Fortran implementations. #define FORWARD_IMPL(T_CXX, R_CXX, T, R, T_CAST, T_CONST_CAST, \ R_CONST_CAST, f, F) \ extern "C" \ @@ -89,112 +89,112 @@ T_CAST (c))); \ } - FORWARD_IMPL (double, double, F77_DBLE, F77_DBLE, , , , d, D) - FORWARD_IMPL (float, float, F77_REAL, F77_REAL, , , , s, S) +FORWARD_IMPL (double, double, F77_DBLE, F77_DBLE,,,, d, D) +FORWARD_IMPL (float, float, F77_REAL, F77_REAL,,,, s, S) - FORWARD_IMPL (std::complex, std::complex, - F77_DBLE_CMPLX, F77_DBLE_CMPLX, F77_DBLE_CMPLX_ARG, - F77_CONST_DBLE_CMPLX_ARG, F77_CONST_DBLE_CMPLX_ARG, z, Z) - FORWARD_IMPL (std::complex, std::complex, - F77_CMPLX, F77_CMPLX, F77_CMPLX_ARG, - F77_CONST_CMPLX_ARG, F77_CONST_CMPLX_ARG, c, C) +FORWARD_IMPL (std::complex, std::complex, + F77_DBLE_CMPLX, F77_DBLE_CMPLX, F77_DBLE_CMPLX_ARG, + F77_CONST_DBLE_CMPLX_ARG, F77_CONST_DBLE_CMPLX_ARG, z, Z) +FORWARD_IMPL (std::complex, std::complex, + F77_CMPLX, F77_CMPLX, F77_CMPLX_ARG, + F77_CONST_CMPLX_ARG, F77_CONST_CMPLX_ARG, c, C) - FORWARD_IMPL (std::complex, double, - F77_DBLE_CMPLX, F77_DBLE, F77_DBLE_CMPLX_ARG, - F77_CONST_DBLE_CMPLX_ARG, , zd, ZD) - FORWARD_IMPL (std::complex, float, F77_CMPLX, F77_REAL, F77_CMPLX_ARG, - F77_CONST_CMPLX_ARG, , cs, CS) +FORWARD_IMPL (std::complex, double, + F77_DBLE_CMPLX, F77_DBLE, F77_DBLE_CMPLX_ARG, + F77_CONST_DBLE_CMPLX_ARG,, zd, ZD) +FORWARD_IMPL (std::complex, float, F77_CMPLX, F77_REAL, F77_CMPLX_ARG, + F77_CONST_CMPLX_ARG,, cs, CS) - template - void convolve_nd (const T *a, const dim_vector& ad, const dim_vector& acd, - const R *b, const dim_vector& bd, const dim_vector& bcd, - T *c, const dim_vector& ccd, int nd, bool inner) - { - if (nd == 2) - { - F77_INT ad0 = to_f77_int (ad(0)); - F77_INT ad1 = to_f77_int (ad(1)); +template +void convolve_nd (const T *a, const dim_vector& ad, const dim_vector& acd, + const R *b, const dim_vector& bd, const dim_vector& bcd, + T *c, const dim_vector& ccd, int nd, bool inner) +{ + if (nd == 2) + { + F77_INT ad0 = to_f77_int (ad(0)); + F77_INT ad1 = to_f77_int (ad(1)); - F77_INT bd0 = to_f77_int (bd(0)); - F77_INT bd1 = to_f77_int (bd(1)); + F77_INT bd0 = to_f77_int (bd(0)); + F77_INT bd1 = to_f77_int (bd(1)); - convolve_2d (a, ad0, ad1, b, bd0, bd1, c, inner); - } - else - { - octave_idx_type ma = acd(nd-2); - octave_idx_type na = ad(nd-1); - octave_idx_type mb = bcd(nd-2); - octave_idx_type nb = bd(nd-1); - octave_idx_type ldc = ccd(nd-2); + convolve_2d (a, ad0, ad1, b, bd0, bd1, c, inner); + } + else + { + octave_idx_type ma = acd(nd-2); + octave_idx_type na = ad(nd-1); + octave_idx_type mb = bcd(nd-2); + octave_idx_type nb = bd(nd-1); + octave_idx_type ldc = ccd(nd-2); - if (inner) - { - for (octave_idx_type ja = 0; ja < na - nb + 1; ja++) - for (octave_idx_type jb = 0; jb < nb; jb++) - convolve_nd (a + ma*(ja+jb), ad, acd, - b + mb*(nb-jb-1), bd, bcd, - c + ldc*ja, ccd, nd-1, inner); - } - else - { - for (octave_idx_type ja = 0; ja < na; ja++) - for (octave_idx_type jb = 0; jb < nb; jb++) - convolve_nd (a + ma*ja, ad, acd, b + mb*jb, bd, bcd, - c + ldc*(ja+jb), ccd, nd-1, inner); - } - } - } + if (inner) + { + for (octave_idx_type ja = 0; ja < na - nb + 1; ja++) + for (octave_idx_type jb = 0; jb < nb; jb++) + convolve_nd (a + ma*(ja+jb), ad, acd, + b + mb*(nb-jb-1), bd, bcd, + c + ldc*ja, ccd, nd-1, inner); + } + else + { + for (octave_idx_type ja = 0; ja < na; ja++) + for (octave_idx_type jb = 0; jb < nb; jb++) + convolve_nd (a + ma*ja, ad, acd, b + mb*jb, bd, bcd, + c + ldc*(ja+jb), ccd, nd-1, inner); + } + } +} - // Arbitrary convolutor. - // The 2nd array is assumed to be the smaller one. - template - static MArray - convolve (const MArray& a, const MArray& b, - convn_type ct) - { - if (a.isempty () || b.isempty ()) - return MArray (); +// Arbitrary convolutor. +// The 2nd array is assumed to be the smaller one. +template +static MArray +convolve (const MArray& a, const MArray& b, + convn_type ct) +{ + if (a.isempty () || b.isempty ()) + return MArray (); - int nd = std::max (a.ndims (), b.ndims ()); - const dim_vector adims = a.dims ().redim (nd); - const dim_vector bdims = b.dims ().redim (nd); - dim_vector cdims = dim_vector::alloc (nd); + int nd = std::max (a.ndims (), b.ndims ()); + const dim_vector adims = a.dims ().redim (nd); + const dim_vector bdims = b.dims ().redim (nd); + dim_vector cdims = dim_vector::alloc (nd); - for (int i = 0; i < nd; i++) - { - if (ct == convn_valid) - cdims(i) = std::max (adims(i) - bdims(i) + 1, - static_cast (0)); - else - cdims(i) = std::max (adims(i) + bdims(i) - 1, - static_cast (0)); - } + for (int i = 0; i < nd; i++) + { + if (ct == convn_valid) + cdims(i) = std::max (adims(i) - bdims(i) + 1, + static_cast (0)); + else + cdims(i) = std::max (adims(i) + bdims(i) - 1, + static_cast (0)); + } - MArray c (cdims, T ()); + MArray c (cdims, T ()); - // "valid" shape can sometimes result in empty matrices which must avoid - // calling Fortran code which does not expect this (bug #52067) - if (c.isempty ()) - return c; + // "valid" shape can sometimes result in empty matrices which must avoid + // calling Fortran code which does not expect this (bug #52067) + if (c.isempty ()) + return c; - convolve_nd (a.data (), adims, adims.cumulative (), - b.data (), bdims, bdims.cumulative (), - c.fortran_vec (), cdims.cumulative (), - nd, ct == convn_valid); + convolve_nd (a.data (), adims, adims.cumulative (), + b.data (), bdims, bdims.cumulative (), + c.fortran_vec (), cdims.cumulative (), + nd, ct == convn_valid); - if (ct == convn_same) - { - // Pick the relevant part. - Array sidx (dim_vector (nd, 1)); + if (ct == convn_same) + { + // Pick the relevant part. + Array sidx (dim_vector (nd, 1)); - for (int i = 0; i < nd; i++) - sidx(i) = idx_vector::make_range (bdims(i)/2, 1, adims(i)); - c = c.index (sidx); - } + for (int i = 0; i < nd; i++) + sidx(i) = idx_vector::make_range (bdims(i)/2, 1, adims(i)); + c = c.index (sidx); + } - return c; - } + return c; +} #define CONV_DEFS(TPREF, RPREF) \ TPREF ## NDArray \ @@ -216,11 +216,11 @@ return convolve (a, c * r, ct); \ } - CONV_DEFS ( , ) - CONV_DEFS (Complex, ) - CONV_DEFS (Complex, Complex) - CONV_DEFS (Float, Float) - CONV_DEFS (FloatComplex, Float) - CONV_DEFS (FloatComplex, FloatComplex) +CONV_DEFS (, ) +CONV_DEFS (Complex, ) +CONV_DEFS (Complex, Complex) +CONV_DEFS (Float, Float) +CONV_DEFS (FloatComplex, Float) +CONV_DEFS (FloatComplex, FloatComplex) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-convn.h --- a/liboctave/numeric/oct-convn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-convn.h Thu Dec 01 20:05:44 2022 -0800 @@ -57,104 +57,104 @@ OCTAVE_BEGIN_NAMESPACE(octave) - enum convn_type - { - convn_full, - convn_same, - convn_valid - }; +enum convn_type +{ + convn_full, + convn_same, + convn_valid +}; - // double real X double real +// double real X double real - extern OCTAVE_API NDArray - convn (const NDArray& a, const NDArray& b, convn_type ct); +extern OCTAVE_API NDArray +convn (const NDArray& a, const NDArray& b, convn_type ct); - extern OCTAVE_API Matrix - convn (const Matrix& a, const Matrix& b, convn_type ct); +extern OCTAVE_API Matrix +convn (const Matrix& a, const Matrix& b, convn_type ct); - extern OCTAVE_API Matrix - convn (const Matrix& a, const ColumnVector& c, const RowVector& r, - convn_type ct); +extern OCTAVE_API Matrix +convn (const Matrix& a, const ColumnVector& c, const RowVector& r, + convn_type ct); - // double complex X double real +// double complex X double real - extern OCTAVE_API ComplexNDArray - convn (const ComplexNDArray& a, const NDArray& b, convn_type ct); +extern OCTAVE_API ComplexNDArray +convn (const ComplexNDArray& a, const NDArray& b, convn_type ct); - extern OCTAVE_API ComplexMatrix - convn (const ComplexMatrix& a, const Matrix& b, convn_type ct); +extern OCTAVE_API ComplexMatrix +convn (const ComplexMatrix& a, const Matrix& b, convn_type ct); - extern OCTAVE_API ComplexMatrix - convn (const ComplexMatrix& a, const ColumnVector& c, const RowVector& r, - convn_type ct); +extern OCTAVE_API ComplexMatrix +convn (const ComplexMatrix& a, const ColumnVector& c, const RowVector& r, + convn_type ct); - // double complex X double complex +// double complex X double complex - extern OCTAVE_API ComplexNDArray - convn (const ComplexNDArray& a, const ComplexNDArray& b, convn_type ct); +extern OCTAVE_API ComplexNDArray +convn (const ComplexNDArray& a, const ComplexNDArray& b, convn_type ct); - extern OCTAVE_API ComplexMatrix - convn (const ComplexMatrix& a, const ComplexMatrix& b, convn_type ct); +extern OCTAVE_API ComplexMatrix +convn (const ComplexMatrix& a, const ComplexMatrix& b, convn_type ct); - extern OCTAVE_API ComplexMatrix - convn (const ComplexMatrix& a, const ComplexColumnVector& c, - const ComplexRowVector& r, convn_type ct); +extern OCTAVE_API ComplexMatrix +convn (const ComplexMatrix& a, const ComplexColumnVector& c, + const ComplexRowVector& r, convn_type ct); - // float real X float real +// float real X float real - extern OCTAVE_API FloatNDArray - convn (const FloatNDArray& a, const FloatNDArray& b, convn_type ct); +extern OCTAVE_API FloatNDArray +convn (const FloatNDArray& a, const FloatNDArray& b, convn_type ct); - extern OCTAVE_API FloatMatrix - convn (const FloatMatrix& a, const FloatMatrix& b, convn_type ct); +extern OCTAVE_API FloatMatrix +convn (const FloatMatrix& a, const FloatMatrix& b, convn_type ct); - extern OCTAVE_API FloatMatrix - convn (const FloatMatrix& a, const FloatColumnVector& c, - const FloatRowVector& r, convn_type ct); +extern OCTAVE_API FloatMatrix +convn (const FloatMatrix& a, const FloatColumnVector& c, + const FloatRowVector& r, convn_type ct); - // float complex X float real +// float complex X float real - extern OCTAVE_API FloatComplexNDArray - convn (const FloatComplexNDArray& a, const FloatNDArray& b, convn_type ct); +extern OCTAVE_API FloatComplexNDArray +convn (const FloatComplexNDArray& a, const FloatNDArray& b, convn_type ct); - extern OCTAVE_API FloatComplexMatrix - convn (const FloatComplexMatrix& a, const FloatMatrix& b, convn_type ct); +extern OCTAVE_API FloatComplexMatrix +convn (const FloatComplexMatrix& a, const FloatMatrix& b, convn_type ct); - extern OCTAVE_API FloatComplexMatrix - convn (const FloatComplexMatrix& a, const FloatColumnVector& c, - const FloatRowVector& r, convn_type ct); +extern OCTAVE_API FloatComplexMatrix +convn (const FloatComplexMatrix& a, const FloatColumnVector& c, + const FloatRowVector& r, convn_type ct); - // float complex X float complex +// float complex X float complex - extern OCTAVE_API FloatComplexNDArray - convn (const FloatComplexNDArray& a, const FloatComplexNDArray& b, - convn_type ct); +extern OCTAVE_API FloatComplexNDArray +convn (const FloatComplexNDArray& a, const FloatComplexNDArray& b, + convn_type ct); - extern OCTAVE_API FloatComplexMatrix - convn (const FloatComplexMatrix& a, const FloatComplexMatrix& b, - convn_type ct); +extern OCTAVE_API FloatComplexMatrix +convn (const FloatComplexMatrix& a, const FloatComplexMatrix& b, + convn_type ct); - extern OCTAVE_API FloatComplexMatrix - convn (const FloatComplexMatrix& a, const FloatComplexColumnVector& c, - const FloatComplexRowVector& r, convn_type ct); +extern OCTAVE_API FloatComplexMatrix +convn (const FloatComplexMatrix& a, const FloatComplexColumnVector& c, + const FloatComplexRowVector& r, convn_type ct); - convn_type convert_enum (::convn_type ct) - { - switch (ct) - { - case ::convn_full: - return convn_full; +convn_type convert_enum (::convn_type ct) +{ + switch (ct) + { + case ::convn_full: + return convn_full; - case ::convn_same: - return convn_same; + case ::convn_same: + return convn_same; - case ::convn_valid: - return convn_valid; + case ::convn_valid: + return convn_valid; - default: - abort (); - } - } + default: + abort (); + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-fftw.cc --- a/liboctave/numeric/oct-fftw.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-fftw.cc Thu Dec 01 20:05:44 2022 -0800 @@ -45,1113 +45,1113 @@ #if defined (HAVE_FFTW) - fftw_planner *fftw_planner::s_instance = nullptr; +fftw_planner *fftw_planner::s_instance = nullptr; - // Helper class to create and cache FFTW plans for both 1D and - // 2D. This implementation defaults to using FFTW_ESTIMATE to create - // the plans, which in theory is suboptimal, but provides quite - // reasonable performance in practice. +// Helper class to create and cache FFTW plans for both 1D and +// 2D. This implementation defaults to using FFTW_ESTIMATE to create +// the plans, which in theory is suboptimal, but provides quite +// reasonable performance in practice. - // Also note that if FFTW_ESTIMATE is not used then the planner in FFTW3 - // will destroy the input and output arrays. We must, therefore, create a - // temporary input array with the same size and 16-byte alignment as - // the original array when using a different planner strategy. - // Note that we also use any wisdom that is available, either in a - // FFTW3 system wide file or as supplied by the user. +// Also note that if FFTW_ESTIMATE is not used then the planner in FFTW3 +// will destroy the input and output arrays. We must, therefore, create a +// temporary input array with the same size and 16-byte alignment as +// the original array when using a different planner strategy. +// Note that we also use any wisdom that is available, either in a +// FFTW3 system wide file or as supplied by the user. - // FIXME: if we can ensure 16 byte alignment in Array - // ( *data) the FFTW3 can use SIMD instructions for further - // acceleration. +// FIXME: if we can ensure 16 byte alignment in Array +// ( *data) the FFTW3 can use SIMD instructions for further +// acceleration. - // Note that it is profitable to store the FFTW3 plans, for small FFTs. +// Note that it is profitable to store the FFTW3 plans, for small FFTs. - fftw_planner::fftw_planner (void) - : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0), - m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1) - { - m_plan[0] = m_plan[1] = nullptr; - m_d[0] = m_d[1] = m_s[0] = m_s[1] = m_r[0] = m_r[1] = m_h[0] = m_h[1] = 0; - m_simd_align[0] = m_simd_align[1] = false; - m_inplace[0] = m_inplace[1] = false; - m_n[0] = m_n[1] = dim_vector (); +fftw_planner::fftw_planner (void) + : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0), + m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1) +{ + m_plan[0] = m_plan[1] = nullptr; + m_d[0] = m_d[1] = m_s[0] = m_s[1] = m_r[0] = m_r[1] = m_h[0] = m_h[1] = 0; + m_simd_align[0] = m_simd_align[1] = false; + m_inplace[0] = m_inplace[1] = false; + m_n[0] = m_n[1] = dim_vector (); #if defined (HAVE_FFTW3_THREADS) - int init_ret = fftw_init_threads (); - if (! init_ret) - (*current_liboctave_error_handler) ("Error initializing FFTW threads"); + int init_ret = fftw_init_threads (); + if (! init_ret) + (*current_liboctave_error_handler) ("Error initializing FFTW threads"); - // Check number of processors available to the current process - m_nthreads = - octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE); + // Check number of processors available to the current process + m_nthreads = + octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE); - // Limit number of threads to 3 by default - // See: https://octave.discourse.group/t/3121 - // This can be later changed with fftw ("threads", nthreads). - if (m_nthreads > 3) - m_nthreads = 3; + // Limit number of threads to 3 by default + // See: https://octave.discourse.group/t/3121 + // This can be later changed with fftw ("threads", nthreads). + if (m_nthreads > 3) + m_nthreads = 3; - fftw_plan_with_nthreads (m_nthreads); + fftw_plan_with_nthreads (m_nthreads); #endif - // If we have a system wide wisdom file, import it. - fftw_import_system_wisdom (); - } + // If we have a system wide wisdom file, import it. + fftw_import_system_wisdom (); +} - fftw_planner::~fftw_planner (void) - { - fftw_plan *plan_p; +fftw_planner::~fftw_planner (void) +{ + fftw_plan *plan_p; - plan_p = reinterpret_cast (&m_rplan); - if (*plan_p) - fftw_destroy_plan (*plan_p); + plan_p = reinterpret_cast (&m_rplan); + if (*plan_p) + fftw_destroy_plan (*plan_p); - plan_p = reinterpret_cast (&m_plan[0]); - if (*plan_p) - fftw_destroy_plan (*plan_p); + plan_p = reinterpret_cast (&m_plan[0]); + if (*plan_p) + fftw_destroy_plan (*plan_p); - plan_p = reinterpret_cast (&m_plan[1]); - if (*plan_p) - fftw_destroy_plan (*plan_p); - } + plan_p = reinterpret_cast (&m_plan[1]); + if (*plan_p) + fftw_destroy_plan (*plan_p); +} - bool - fftw_planner::instance_ok (void) - { - bool retval = true; +bool +fftw_planner::instance_ok (void) +{ + bool retval = true; - if (! s_instance) - { - s_instance = new fftw_planner (); - singleton_cleanup_list::add (cleanup_instance); - } + if (! s_instance) + { + s_instance = new fftw_planner (); + singleton_cleanup_list::add (cleanup_instance); + } - return retval; - } + return retval; +} - void - fftw_planner::threads (int nt) - { +void +fftw_planner::threads (int nt) +{ #if defined (HAVE_FFTW3_THREADS) - if (instance_ok () && nt != threads ()) - { - s_instance->m_nthreads = nt; - fftw_plan_with_nthreads (nt); - // Clear the current plans. - s_instance->m_rplan = nullptr; - s_instance->m_plan[0] = s_instance->m_plan[1] = nullptr; - } + if (instance_ok () && nt != threads ()) + { + s_instance->m_nthreads = nt; + fftw_plan_with_nthreads (nt); + // Clear the current plans. + s_instance->m_rplan = nullptr; + s_instance->m_plan[0] = s_instance->m_plan[1] = nullptr; + } #else - octave_unused_parameter (nt); + octave_unused_parameter (nt); - (*current_liboctave_warning_handler) - ("unable to change number of threads without FFTW thread support"); + (*current_liboctave_warning_handler) + ("unable to change number of threads without FFTW thread support"); #endif - } +} #define CHECK_SIMD_ALIGNMENT(x) \ (((reinterpret_cast (x)) & 0xF) == 0) - void * - fftw_planner::do_create_plan (int dir, const int rank, - const dim_vector& dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const Complex *in, Complex *out) - { - int which = (dir == FFTW_FORWARD) ? 0 : 1; - fftw_plan *cur_plan_p = reinterpret_cast (&m_plan[which]); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - bool ioinplace = (in == out); - - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. - - if (m_plan[which] == nullptr || m_d[which] != dist || m_s[which] != stride - || m_r[which] != rank || m_h[which] != howmany - || ioinplace != m_inplace[which] - || ((ioalign != m_simd_align[which]) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. - - for (int i = 0; i < rank; i++) - if (dims(i) != m_n[which](i)) - { - create_new_plan = true; - break; - } - } +void * +fftw_planner::do_create_plan (int dir, const int rank, + const dim_vector& dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const Complex *in, Complex *out) +{ + int which = (dir == FFTW_FORWARD) ? 0 : 1; + fftw_plan *cur_plan_p = reinterpret_cast (&m_plan[which]); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + bool ioinplace = (in == out); - if (create_new_plan) - { - m_d[which] = dist; - m_s[which] = stride; - m_r[which] = rank; - m_h[which] = howmany; - m_simd_align[which] = ioalign; - m_inplace[which] = ioinplace; - m_n[which] = dims; - - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); - - for (int i = 0, j = rank-1; i < rank; i++, j--) - { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. - switch (m_meth) + if (m_plan[which] == nullptr || m_d[which] != dist || m_s[which] != stride + || m_r[which] != rank || m_h[which] != howmany + || ioinplace != m_inplace[which] + || ((ioalign != m_simd_align[which]) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. + + for (int i = 0; i < rank; i++) + if (dims(i) != m_n[which](i)) { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } + create_new_plan = true; break; } + } - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + if (create_new_plan) + { + m_d[which] = dist; + m_s[which] = stride; + m_r[which] = rank; + m_h[which] = howmany; + m_simd_align[which] = ioalign; + m_inplace[which] = ioinplace; + m_n[which] = dims; - if (*cur_plan_p) - fftw_destroy_plan (*cur_plan_p); + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (Complex, itmp, nn * howmany + 32); - itmp = reinterpret_cast - (((reinterpret_cast (itmp) + 15) & ~ 0xF) + - ((reinterpret_cast (in)) & 0xF)); + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } + + int plan_flags = 0; + bool plan_destroys_in = true; - *cur_plan_p - = fftw_plan_many_dft (rank, tmp, howmany, - reinterpret_cast (itmp), - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, dir, plan_flags); - } - else - { - *cur_plan_p - = fftw_plan_many_dft (rank, tmp, howmany, - reinterpret_cast (const_cast (in)), - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, dir, plan_flags); - } + switch (m_meth) + { + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } + break; + } - if (*cur_plan_p == nullptr) - (*current_liboctave_error_handler) ("Error creating FFTW plan"); - } - - return *cur_plan_p; - } - - void * - fftw_planner::do_create_plan (const int rank, const dim_vector& dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const double *in, Complex *out) - { - fftw_plan *cur_plan_p = reinterpret_cast (&m_rplan); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - if (m_rplan == nullptr || m_rd != dist || m_rs != stride || m_rr != rank - || m_rh != howmany || ((ioalign != m_rsimd_align) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. + if (*cur_plan_p) + fftw_destroy_plan (*cur_plan_p); + + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (Complex, itmp, nn * howmany + 32); + itmp = reinterpret_cast + (((reinterpret_cast (itmp) + 15) & ~ 0xF) + + ((reinterpret_cast (in)) & 0xF)); - for (int i = 0; i < rank; i++) - if (dims(i) != m_rn(i)) - { - create_new_plan = true; - break; - } - } + *cur_plan_p + = fftw_plan_many_dft (rank, tmp, howmany, + reinterpret_cast (itmp), + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, dir, plan_flags); + } + else + { + *cur_plan_p + = fftw_plan_many_dft (rank, tmp, howmany, + reinterpret_cast (const_cast (in)), + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, dir, plan_flags); + } - if (create_new_plan) - { - m_rd = dist; - m_rs = stride; - m_rr = rank; - m_rh = howmany; - m_rsimd_align = ioalign; - m_rn = dims; + if (*cur_plan_p == nullptr) + (*current_liboctave_error_handler) ("Error creating FFTW plan"); + } + + return *cur_plan_p; +} - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); +void * +fftw_planner::do_create_plan (const int rank, const dim_vector& dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const double *in, Complex *out) +{ + fftw_plan *cur_plan_p = reinterpret_cast (&m_rplan); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - for (int i = 0, j = rank-1; i < rank; i++, j--) + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. + + if (m_rplan == nullptr || m_rd != dist || m_rs != stride || m_rr != rank + || m_rh != howmany || ((ioalign != m_rsimd_align) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. + + for (int i = 0; i < rank; i++) + if (dims(i) != m_rn(i)) { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; - - switch (m_meth) - { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } + create_new_plan = true; break; } + } - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + if (create_new_plan) + { + m_rd = dist; + m_rs = stride; + m_rr = rank; + m_rh = howmany; + m_rsimd_align = ioalign; + m_rn = dims; - if (*cur_plan_p) - fftw_destroy_plan (*cur_plan_p); + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (double, itmp, nn + 32); - itmp = reinterpret_cast - (((reinterpret_cast (itmp) + 15) & ~ 0xF) + - ((reinterpret_cast (in)) & 0xF)); + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } + + int plan_flags = 0; + bool plan_destroys_in = true; - *cur_plan_p - = fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp, - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, plan_flags); - } - else - { - *cur_plan_p - = fftw_plan_many_dft_r2c (rank, tmp, howmany, - (const_cast (in)), - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, plan_flags); - } + switch (m_meth) + { + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } + break; + } - if (*cur_plan_p == nullptr) - (*current_liboctave_error_handler) ("Error creating FFTW plan"); - } + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - return *cur_plan_p; - } + if (*cur_plan_p) + fftw_destroy_plan (*cur_plan_p); - fftw_planner::FftwMethod - fftw_planner::do_method (void) - { - return m_meth; - } + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (double, itmp, nn + 32); + itmp = reinterpret_cast + (((reinterpret_cast (itmp) + 15) & ~ 0xF) + + ((reinterpret_cast (in)) & 0xF)); + + *cur_plan_p + = fftw_plan_many_dft_r2c (rank, tmp, howmany, itmp, + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, plan_flags); + } + else + { + *cur_plan_p + = fftw_plan_many_dft_r2c (rank, tmp, howmany, + (const_cast (in)), + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, plan_flags); + } + + if (*cur_plan_p == nullptr) + (*current_liboctave_error_handler) ("Error creating FFTW plan"); + } + + return *cur_plan_p; +} + +fftw_planner::FftwMethod +fftw_planner::do_method (void) +{ + return m_meth; +} - fftw_planner::FftwMethod - fftw_planner::do_method (FftwMethod _meth) - { - FftwMethod ret = m_meth; - if (_meth == ESTIMATE || _meth == MEASURE - || _meth == PATIENT || _meth == EXHAUSTIVE - || _meth == HYBRID) - { - if (m_meth != _meth) - { - m_meth = _meth; - if (m_rplan) - fftw_destroy_plan (reinterpret_cast (m_rplan)); - if (m_plan[0]) - fftw_destroy_plan (reinterpret_cast (m_plan[0])); - if (m_plan[1]) - fftw_destroy_plan (reinterpret_cast (m_plan[1])); - m_rplan = m_plan[0] = m_plan[1] = nullptr; - } - } - else - ret = UNKNOWN; - return ret; - } +fftw_planner::FftwMethod +fftw_planner::do_method (FftwMethod _meth) +{ + FftwMethod ret = m_meth; + if (_meth == ESTIMATE || _meth == MEASURE + || _meth == PATIENT || _meth == EXHAUSTIVE + || _meth == HYBRID) + { + if (m_meth != _meth) + { + m_meth = _meth; + if (m_rplan) + fftw_destroy_plan (reinterpret_cast (m_rplan)); + if (m_plan[0]) + fftw_destroy_plan (reinterpret_cast (m_plan[0])); + if (m_plan[1]) + fftw_destroy_plan (reinterpret_cast (m_plan[1])); + m_rplan = m_plan[0] = m_plan[1] = nullptr; + } + } + else + ret = UNKNOWN; + return ret; +} - float_fftw_planner *float_fftw_planner::s_instance = nullptr; +float_fftw_planner *float_fftw_planner::s_instance = nullptr; - float_fftw_planner::float_fftw_planner (void) - : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0), - m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1) - { - m_plan[0] = m_plan[1] = nullptr; - m_d[0] = m_d[1] = m_s[0] = m_s[1] = m_r[0] = m_r[1] = m_h[0] = m_h[1] = 0; - m_simd_align[0] = m_simd_align[1] = false; - m_inplace[0] = m_inplace[1] = false; - m_n[0] = m_n[1] = dim_vector (); +float_fftw_planner::float_fftw_planner (void) + : m_meth (ESTIMATE), m_rplan (nullptr), m_rd (0), m_rs (0), m_rr (0), + m_rh (0), m_rn (), m_rsimd_align (false), m_nthreads (1) +{ + m_plan[0] = m_plan[1] = nullptr; + m_d[0] = m_d[1] = m_s[0] = m_s[1] = m_r[0] = m_r[1] = m_h[0] = m_h[1] = 0; + m_simd_align[0] = m_simd_align[1] = false; + m_inplace[0] = m_inplace[1] = false; + m_n[0] = m_n[1] = dim_vector (); #if defined (HAVE_FFTW3F_THREADS) - int init_ret = fftwf_init_threads (); - if (! init_ret) - (*current_liboctave_error_handler) ("Error initializing FFTW3F threads"); + int init_ret = fftwf_init_threads (); + if (! init_ret) + (*current_liboctave_error_handler) ("Error initializing FFTW3F threads"); - // Use number of processors available to the current process - // This can be later changed with fftw ("threads", nthreads). - m_nthreads = - octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE); + // Use number of processors available to the current process + // This can be later changed with fftw ("threads", nthreads). + m_nthreads = + octave_num_processors_wrapper (OCTAVE_NPROC_CURRENT_OVERRIDABLE); - fftwf_plan_with_nthreads (m_nthreads); + fftwf_plan_with_nthreads (m_nthreads); #endif - // If we have a system wide wisdom file, import it. - fftwf_import_system_wisdom (); - } + // If we have a system wide wisdom file, import it. + fftwf_import_system_wisdom (); +} - float_fftw_planner::~float_fftw_planner (void) - { - fftwf_plan *plan_p; - - plan_p = reinterpret_cast (&m_rplan); - if (*plan_p) - fftwf_destroy_plan (*plan_p); +float_fftw_planner::~float_fftw_planner (void) +{ + fftwf_plan *plan_p; - plan_p = reinterpret_cast (&m_plan[0]); - if (*plan_p) - fftwf_destroy_plan (*plan_p); + plan_p = reinterpret_cast (&m_rplan); + if (*plan_p) + fftwf_destroy_plan (*plan_p); - plan_p = reinterpret_cast (&m_plan[1]); - if (*plan_p) - fftwf_destroy_plan (*plan_p); - } - - bool - float_fftw_planner::instance_ok (void) - { - bool retval = true; + plan_p = reinterpret_cast (&m_plan[0]); + if (*plan_p) + fftwf_destroy_plan (*plan_p); - if (! s_instance) - { - s_instance = new float_fftw_planner (); - singleton_cleanup_list::add (cleanup_instance); - } - - return retval; - } + plan_p = reinterpret_cast (&m_plan[1]); + if (*plan_p) + fftwf_destroy_plan (*plan_p); +} - void - float_fftw_planner::threads (int nt) - { -#if defined (HAVE_FFTW3F_THREADS) - if (instance_ok () && nt != threads ()) - { - s_instance->m_nthreads = nt; - fftwf_plan_with_nthreads (nt); - // Clear the current plans. - s_instance->m_rplan = nullptr; - s_instance->m_plan[0] = s_instance->m_plan[1] = nullptr; - } -#else - octave_unused_parameter (nt); +bool +float_fftw_planner::instance_ok (void) +{ + bool retval = true; - (*current_liboctave_warning_handler) - ("unable to change number of threads without FFTW thread support"); -#endif - } + if (! s_instance) + { + s_instance = new float_fftw_planner (); + singleton_cleanup_list::add (cleanup_instance); + } + + return retval; +} - void * - float_fftw_planner::do_create_plan (int dir, const int rank, - const dim_vector& dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const FloatComplex *in, - FloatComplex *out) - { - int which = (dir == FFTW_FORWARD) ? 0 : 1; - fftwf_plan *cur_plan_p = reinterpret_cast (&m_plan[which]); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - bool ioinplace = (in == out); +void +float_fftw_planner::threads (int nt) +{ +#if defined (HAVE_FFTW3F_THREADS) + if (instance_ok () && nt != threads ()) + { + s_instance->m_nthreads = nt; + fftwf_plan_with_nthreads (nt); + // Clear the current plans. + s_instance->m_rplan = nullptr; + s_instance->m_plan[0] = s_instance->m_plan[1] = nullptr; + } +#else + octave_unused_parameter (nt); - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. - - if (m_plan[which] == nullptr || m_d[which] != dist || m_s[which] != stride - || m_r[which] != rank || m_h[which] != howmany - || ioinplace != m_inplace[which] - || ((ioalign != m_simd_align[which]) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. - - for (int i = 0; i < rank; i++) - if (dims(i) != m_n[which](i)) - { - create_new_plan = true; - break; - } - } + (*current_liboctave_warning_handler) + ("unable to change number of threads without FFTW thread support"); +#endif +} - if (create_new_plan) - { - m_d[which] = dist; - m_s[which] = stride; - m_r[which] = rank; - m_h[which] = howmany; - m_simd_align[which] = ioalign; - m_inplace[which] = ioinplace; - m_n[which] = dims; - - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); - - for (int i = 0, j = rank-1; i < rank; i++, j--) - { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; +void * +float_fftw_planner::do_create_plan (int dir, const int rank, + const dim_vector& dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const FloatComplex *in, + FloatComplex *out) +{ + int which = (dir == FFTW_FORWARD) ? 0 : 1; + fftwf_plan *cur_plan_p = reinterpret_cast (&m_plan[which]); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); + bool ioinplace = (in == out); - switch (m_meth) + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. + + if (m_plan[which] == nullptr || m_d[which] != dist || m_s[which] != stride + || m_r[which] != rank || m_h[which] != howmany + || ioinplace != m_inplace[which] + || ((ioalign != m_simd_align[which]) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. + + for (int i = 0; i < rank; i++) + if (dims(i) != m_n[which](i)) { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } + create_new_plan = true; break; } + } - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + if (create_new_plan) + { + m_d[which] = dist; + m_s[which] = stride; + m_r[which] = rank; + m_h[which] = howmany; + m_simd_align[which] = ioalign; + m_inplace[which] = ioinplace; + m_n[which] = dims; - if (*cur_plan_p) - fftwf_destroy_plan (*cur_plan_p); + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (FloatComplex, itmp, nn * howmany + 32); - itmp = reinterpret_cast - (((reinterpret_cast (itmp) + 15) & ~ 0xF) + - ((reinterpret_cast (in)) & 0xF)); + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } + + int plan_flags = 0; + bool plan_destroys_in = true; - *cur_plan_p - = fftwf_plan_many_dft (rank, tmp, howmany, - reinterpret_cast (itmp), - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, dir, plan_flags); - } - else - { - *cur_plan_p - = fftwf_plan_many_dft (rank, tmp, howmany, - reinterpret_cast (const_cast (in)), - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, dir, plan_flags); - } + switch (m_meth) + { + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } + break; + } - if (*cur_plan_p == nullptr) - (*current_liboctave_error_handler) ("Error creating FFTW plan"); - } - - return *cur_plan_p; - } - - void * - float_fftw_planner::do_create_plan (const int rank, const dim_vector& dims, - octave_idx_type howmany, - octave_idx_type stride, - octave_idx_type dist, - const float *in, FloatComplex *out) - { - fftwf_plan *cur_plan_p = reinterpret_cast (&m_rplan); - bool create_new_plan = false; - bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - - // Don't create a new plan if we have a non SIMD plan already but - // can do SIMD. This prevents endlessly recreating plans if we - // change the alignment. + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; - if (m_rplan == nullptr || m_rd != dist || m_rs != stride || m_rr != rank - || m_rh != howmany || ((ioalign != m_rsimd_align) ? ! ioalign : false)) - create_new_plan = true; - else - { - // We still might not have the same shape of array. + if (*cur_plan_p) + fftwf_destroy_plan (*cur_plan_p); + + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (FloatComplex, itmp, nn * howmany + 32); + itmp = reinterpret_cast + (((reinterpret_cast (itmp) + 15) & ~ 0xF) + + ((reinterpret_cast (in)) & 0xF)); - for (int i = 0; i < rank; i++) - if (dims(i) != m_rn(i)) - { - create_new_plan = true; - break; - } - } + *cur_plan_p + = fftwf_plan_many_dft (rank, tmp, howmany, + reinterpret_cast (itmp), + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, dir, plan_flags); + } + else + { + *cur_plan_p + = fftwf_plan_many_dft (rank, tmp, howmany, + reinterpret_cast (const_cast (in)), + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, dir, plan_flags); + } - if (create_new_plan) - { - m_rd = dist; - m_rs = stride; - m_rr = rank; - m_rh = howmany; - m_rsimd_align = ioalign; - m_rn = dims; + if (*cur_plan_p == nullptr) + (*current_liboctave_error_handler) ("Error creating FFTW plan"); + } + + return *cur_plan_p; +} - // Note reversal of dimensions for column major storage in FFTW. - octave_idx_type nn = 1; - OCTAVE_LOCAL_BUFFER (int, tmp, rank); +void * +float_fftw_planner::do_create_plan (const int rank, const dim_vector& dims, + octave_idx_type howmany, + octave_idx_type stride, + octave_idx_type dist, + const float *in, FloatComplex *out) +{ + fftwf_plan *cur_plan_p = reinterpret_cast (&m_rplan); + bool create_new_plan = false; + bool ioalign = CHECK_SIMD_ALIGNMENT (in) && CHECK_SIMD_ALIGNMENT (out); - for (int i = 0, j = rank-1; i < rank; i++, j--) + // Don't create a new plan if we have a non SIMD plan already but + // can do SIMD. This prevents endlessly recreating plans if we + // change the alignment. + + if (m_rplan == nullptr || m_rd != dist || m_rs != stride || m_rr != rank + || m_rh != howmany || ((ioalign != m_rsimd_align) ? ! ioalign : false)) + create_new_plan = true; + else + { + // We still might not have the same shape of array. + + for (int i = 0; i < rank; i++) + if (dims(i) != m_rn(i)) { - tmp[i] = dims(j); - nn *= dims(j); - } - - int plan_flags = 0; - bool plan_destroys_in = true; - - switch (m_meth) - { - case UNKNOWN: - case ESTIMATE: - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - break; - case MEASURE: - plan_flags |= FFTW_MEASURE; - break; - case PATIENT: - plan_flags |= FFTW_PATIENT; - break; - case EXHAUSTIVE: - plan_flags |= FFTW_EXHAUSTIVE; - break; - case HYBRID: - if (nn < 8193) - plan_flags |= FFTW_MEASURE; - else - { - plan_flags |= FFTW_ESTIMATE; - plan_destroys_in = false; - } + create_new_plan = true; break; } - - if (ioalign) - plan_flags &= ~FFTW_UNALIGNED; - else - plan_flags |= FFTW_UNALIGNED; + } - if (*cur_plan_p) - fftwf_destroy_plan (*cur_plan_p); - - if (plan_destroys_in) - { - // Create matrix with the same size and 16-byte alignment as input - OCTAVE_LOCAL_BUFFER (float, itmp, nn + 32); - itmp = reinterpret_cast - (((reinterpret_cast (itmp) + 15) & ~ 0xF) + - ((reinterpret_cast (in)) & 0xF)); + if (create_new_plan) + { + m_rd = dist; + m_rs = stride; + m_rr = rank; + m_rh = howmany; + m_rsimd_align = ioalign; + m_rn = dims; - *cur_plan_p - = fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp, - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, plan_flags); - } - else - { - *cur_plan_p - = fftwf_plan_many_dft_r2c (rank, tmp, howmany, - (const_cast (in)), - nullptr, stride, dist, - reinterpret_cast (out), - nullptr, stride, dist, plan_flags); - } + // Note reversal of dimensions for column major storage in FFTW. + octave_idx_type nn = 1; + OCTAVE_LOCAL_BUFFER (int, tmp, rank); - if (*cur_plan_p == nullptr) - (*current_liboctave_error_handler) ("Error creating FFTW plan"); - } + for (int i = 0, j = rank-1; i < rank; i++, j--) + { + tmp[i] = dims(j); + nn *= dims(j); + } - return *cur_plan_p; - } - - float_fftw_planner::FftwMethod - float_fftw_planner::do_method (void) - { - return m_meth; - } + int plan_flags = 0; + bool plan_destroys_in = true; - float_fftw_planner::FftwMethod - float_fftw_planner::do_method (FftwMethod _meth) - { - FftwMethod ret = m_meth; - if (_meth == ESTIMATE || _meth == MEASURE - || _meth == PATIENT || _meth == EXHAUSTIVE - || _meth == HYBRID) - { - if (m_meth != _meth) - { - m_meth = _meth; - if (m_rplan) - fftwf_destroy_plan (reinterpret_cast (m_rplan)); - if (m_plan[0]) - fftwf_destroy_plan (reinterpret_cast (m_plan[0])); - if (m_plan[1]) - fftwf_destroy_plan (reinterpret_cast (m_plan[1])); - m_rplan = m_plan[0] = m_plan[1] = nullptr; - } - } - else - ret = UNKNOWN; - return ret; - } + switch (m_meth) + { + case UNKNOWN: + case ESTIMATE: + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + break; + case MEASURE: + plan_flags |= FFTW_MEASURE; + break; + case PATIENT: + plan_flags |= FFTW_PATIENT; + break; + case EXHAUSTIVE: + plan_flags |= FFTW_EXHAUSTIVE; + break; + case HYBRID: + if (nn < 8193) + plan_flags |= FFTW_MEASURE; + else + { + plan_flags |= FFTW_ESTIMATE; + plan_destroys_in = false; + } + break; + } + + if (ioalign) + plan_flags &= ~FFTW_UNALIGNED; + else + plan_flags |= FFTW_UNALIGNED; + + if (*cur_plan_p) + fftwf_destroy_plan (*cur_plan_p); - template - static inline void - convert_packcomplex_1d (T *out, std::size_t nr, std::size_t nc, - octave_idx_type stride, octave_idx_type dist) - { - octave_quit (); - - // Fill in the missing data. - - for (std::size_t i = 0; i < nr; i++) - for (std::size_t j = nc/2+1; j < nc; j++) - out[j*stride + i*dist] = conj (out[(nc - j)*stride + i*dist]); + if (plan_destroys_in) + { + // Create matrix with the same size and 16-byte alignment as input + OCTAVE_LOCAL_BUFFER (float, itmp, nn + 32); + itmp = reinterpret_cast + (((reinterpret_cast (itmp) + 15) & ~ 0xF) + + ((reinterpret_cast (in)) & 0xF)); - octave_quit (); - } + *cur_plan_p + = fftwf_plan_many_dft_r2c (rank, tmp, howmany, itmp, + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, plan_flags); + } + else + { + *cur_plan_p + = fftwf_plan_many_dft_r2c (rank, tmp, howmany, + (const_cast (in)), + nullptr, stride, dist, + reinterpret_cast (out), + nullptr, stride, dist, plan_flags); + } - template - static inline void - convert_packcomplex_Nd (T *out, const dim_vector& dv) - { - std::size_t nc = dv(0); - std::size_t nr = dv(1); - std::size_t np = (dv.ndims () > 2 ? dv.numel () / nc / nr : 1); - std::size_t nrp = nr * np; - T *ptr1, *ptr2; + if (*cur_plan_p == nullptr) + (*current_liboctave_error_handler) ("Error creating FFTW plan"); + } - octave_quit (); + return *cur_plan_p; +} - // Create space for the missing elements. +float_fftw_planner::FftwMethod +float_fftw_planner::do_method (void) +{ + return m_meth; +} - for (std::size_t i = 0; i < nrp; i++) - { - ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2); - ptr2 = out + i * nc; - for (std::size_t j = 0; j < nc/2+1; j++) - *ptr2++ = *ptr1++; - } - - octave_quit (); - - // Fill in the missing data for the rank = 2 case directly for speed. +float_fftw_planner::FftwMethod +float_fftw_planner::do_method (FftwMethod _meth) +{ + FftwMethod ret = m_meth; + if (_meth == ESTIMATE || _meth == MEASURE + || _meth == PATIENT || _meth == EXHAUSTIVE + || _meth == HYBRID) + { + if (m_meth != _meth) + { + m_meth = _meth; + if (m_rplan) + fftwf_destroy_plan (reinterpret_cast (m_rplan)); + if (m_plan[0]) + fftwf_destroy_plan (reinterpret_cast (m_plan[0])); + if (m_plan[1]) + fftwf_destroy_plan (reinterpret_cast (m_plan[1])); + m_rplan = m_plan[0] = m_plan[1] = nullptr; + } + } + else + ret = UNKNOWN; + return ret; +} - for (std::size_t i = 0; i < np; i++) - { - for (std::size_t j = 1; j < nr; j++) - for (std::size_t k = nc/2+1; k < nc; k++) - out[k + (j + i*nr)*nc] = conj (out[nc - k + ((i+1)*nr - j)*nc]); - - for (std::size_t j = nc/2+1; j < nc; j++) - out[j + i*nr*nc] = conj (out[(i*nr+1)*nc - j]); - } - - octave_quit (); +template +static inline void +convert_packcomplex_1d (T *out, std::size_t nr, std::size_t nc, + octave_idx_type stride, octave_idx_type dist) +{ + octave_quit (); - // Now do the permutations needed for rank > 2 cases. + // Fill in the missing data. - std::size_t jstart = dv(0) * dv(1); - std::size_t kstep = dv(0); - std::size_t nel = dv.numel (); + for (std::size_t i = 0; i < nr; i++) + for (std::size_t j = nc/2+1; j < nc; j++) + out[j*stride + i*dist] = conj (out[(nc - j)*stride + i*dist]); + + octave_quit (); +} - for (int inner = 2; inner < dv.ndims (); inner++) - { - std::size_t jmax = jstart * dv(inner); - for (std::size_t i = 0; i < nel; i+=jmax) - for (std::size_t j = jstart, jj = jmax-jstart; j < jj; - j+=jstart, jj-=jstart) - for (std::size_t k = 0; k < jstart; k+= kstep) - for (std::size_t l = nc/2+1; l < nc; l++) - { - T tmp = out[i+ j + k + l]; - out[i + j + k + l] = out[i + jj + k + l]; - out[i + jj + k + l] = tmp; - } - jstart = jmax; - } +template +static inline void +convert_packcomplex_Nd (T *out, const dim_vector& dv) +{ + std::size_t nc = dv(0); + std::size_t nr = dv(1); + std::size_t np = (dv.ndims () > 2 ? dv.numel () / nc / nr : 1); + std::size_t nrp = nr * np; + T *ptr1, *ptr2; + + octave_quit (); - octave_quit (); - } + // Create space for the missing elements. + + for (std::size_t i = 0; i < nrp; i++) + { + ptr1 = out + i * (nc/2 + 1) + nrp*((nc-1)/2); + ptr2 = out + i * nc; + for (std::size_t j = 0; j < nc/2+1; j++) + *ptr2++ = *ptr1++; + } + + octave_quit (); + + // Fill in the missing data for the rank = 2 case directly for speed. - int - fftw::fft (const double *in, Complex *out, std::size_t npts, - std::size_t nsamples, octave_idx_type stride, - octave_idx_type dist) - { - dist = (dist < 0 ? npts : dist); + for (std::size_t i = 0; i < np; i++) + { + for (std::size_t j = 1; j < nr; j++) + for (std::size_t k = nc/2+1; k < nc; k++) + out[k + (j + i*nr)*nc] = conj (out[nc - k + ((i+1)*nr - j)*nc]); - dim_vector dv (npts, 1); - void *vplan = fftw_planner::create_plan (1, dv, nsamples, - stride, dist, in, out); - fftw_plan m_plan = reinterpret_cast (vplan); + for (std::size_t j = nc/2+1; j < nc; j++) + out[j + i*nr*nc] = conj (out[(i*nr+1)*nc - j]); + } + + octave_quit (); + + // Now do the permutations needed for rank > 2 cases. - fftw_execute_dft_r2c (m_plan, (const_cast(in)), - reinterpret_cast (out)); - - // Need to create other half of the transform. - - convert_packcomplex_1d (out, nsamples, npts, stride, dist); + std::size_t jstart = dv(0) * dv(1); + std::size_t kstep = dv(0); + std::size_t nel = dv.numel (); - return 0; - } - - int - fftw::fft (const Complex *in, Complex *out, std::size_t npts, - std::size_t nsamples, octave_idx_type stride, - octave_idx_type dist) - { - dist = (dist < 0 ? npts : dist); + for (int inner = 2; inner < dv.ndims (); inner++) + { + std::size_t jmax = jstart * dv(inner); + for (std::size_t i = 0; i < nel; i+=jmax) + for (std::size_t j = jstart, jj = jmax-jstart; j < jj; + j+=jstart, jj-=jstart) + for (std::size_t k = 0; k < jstart; k+= kstep) + for (std::size_t l = nc/2+1; l < nc; l++) + { + T tmp = out[i+ j + k + l]; + out[i + j + k + l] = out[i + jj + k + l]; + out[i + jj + k + l] = tmp; + } + jstart = jmax; + } - dim_vector dv (npts, 1); - void *vplan = fftw_planner::create_plan (FFTW_FORWARD, 1, dv, - nsamples, stride, - dist, in, out); - fftw_plan m_plan = reinterpret_cast (vplan); + octave_quit (); +} - fftw_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); +int +fftw::fft (const double *in, Complex *out, std::size_t npts, + std::size_t nsamples, octave_idx_type stride, + octave_idx_type dist) +{ + dist = (dist < 0 ? npts : dist); - return 0; - } + dim_vector dv (npts, 1); + void *vplan = fftw_planner::create_plan (1, dv, nsamples, + stride, dist, in, out); + fftw_plan m_plan = reinterpret_cast (vplan); + + fftw_execute_dft_r2c (m_plan, (const_cast(in)), + reinterpret_cast (out)); - int - fftw::ifft (const Complex *in, Complex *out, std::size_t npts, - std::size_t nsamples, octave_idx_type stride, - octave_idx_type dist) - { - dist = (dist < 0 ? npts : dist); + // Need to create other half of the transform. + + convert_packcomplex_1d (out, nsamples, npts, stride, dist); + + return 0; +} - dim_vector dv (npts, 1); - void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, nsamples, - stride, dist, in, out); - fftw_plan m_plan = reinterpret_cast (vplan); +int +fftw::fft (const Complex *in, Complex *out, std::size_t npts, + std::size_t nsamples, octave_idx_type stride, + octave_idx_type dist) +{ + dist = (dist < 0 ? npts : dist); - fftw_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); + dim_vector dv (npts, 1); + void *vplan = fftw_planner::create_plan (FFTW_FORWARD, 1, dv, + nsamples, stride, + dist, in, out); + fftw_plan m_plan = reinterpret_cast (vplan); - const Complex scale = npts; - for (std::size_t j = 0; j < nsamples; j++) - for (std::size_t i = 0; i < npts; i++) - out[i*stride + j*dist] /= scale; + fftw_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); + + return 0; +} - return 0; - } +int +fftw::ifft (const Complex *in, Complex *out, std::size_t npts, + std::size_t nsamples, octave_idx_type stride, + octave_idx_type dist) +{ + dist = (dist < 0 ? npts : dist); - int - fftw::fftNd (const double *in, Complex *out, const int rank, - const dim_vector& dv) - { - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + dim_vector dv (npts, 1); + void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, nsamples, + stride, dist, in, out); + fftw_plan m_plan = reinterpret_cast (vplan); - // Fool with the position of the start of the output matrix, so that - // creating other half of the matrix won't cause cache problems. + fftw_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); - octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); - - void *vplan = fftw_planner::create_plan (rank, dv, 1, 1, dist, - in, out + offset); - fftw_plan m_plan = reinterpret_cast (vplan); + const Complex scale = npts; + for (std::size_t j = 0; j < nsamples; j++) + for (std::size_t i = 0; i < npts; i++) + out[i*stride + j*dist] /= scale; - fftw_execute_dft_r2c (m_plan, (const_cast(in)), - reinterpret_cast (out+ offset)); - - // Need to create other half of the transform. + return 0; +} - convert_packcomplex_Nd (out, dv); +int +fftw::fftNd (const double *in, Complex *out, const int rank, + const dim_vector& dv) +{ + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - return 0; - } + // Fool with the position of the start of the output matrix, so that + // creating other half of the matrix won't cause cache problems. - int - fftw::fftNd (const Complex *in, Complex *out, const int rank, - const dim_vector& dv) - { - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); + + void *vplan = fftw_planner::create_plan (rank, dv, 1, 1, dist, + in, out + offset); + fftw_plan m_plan = reinterpret_cast (vplan); - void *vplan = fftw_planner::create_plan (FFTW_FORWARD, rank, dv, - 1, 1, dist, in, out); - fftw_plan m_plan = reinterpret_cast (vplan); + fftw_execute_dft_r2c (m_plan, (const_cast(in)), + reinterpret_cast (out+ offset)); + + // Need to create other half of the transform. - fftw_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); + convert_packcomplex_Nd (out, dv); + + return 0; +} - return 0; - } +int +fftw::fftNd (const Complex *in, Complex *out, const int rank, + const dim_vector& dv) +{ + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - int - fftw::ifftNd (const Complex *in, Complex *out, const int rank, - const dim_vector& dv) - { - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + void *vplan = fftw_planner::create_plan (FFTW_FORWARD, rank, dv, + 1, 1, dist, in, out); + fftw_plan m_plan = reinterpret_cast (vplan); - void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, rank, dv, - 1, 1, dist, in, out); - fftw_plan m_plan = reinterpret_cast (vplan); + fftw_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); - fftw_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); + return 0; +} - const std::size_t npts = dv.numel (); - const Complex scale = npts; - for (std::size_t i = 0; i < npts; i++) - out[i] /= scale; - - return 0; - } +int +fftw::ifftNd (const Complex *in, Complex *out, const int rank, + const dim_vector& dv) +{ + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - int - fftw::fft (const float *in, FloatComplex *out, std::size_t npts, - std::size_t nsamples, octave_idx_type stride, - octave_idx_type dist) - { - dist = (dist < 0 ? npts : dist); + void *vplan = fftw_planner::create_plan (FFTW_BACKWARD, rank, dv, + 1, 1, dist, in, out); + fftw_plan m_plan = reinterpret_cast (vplan); + + fftw_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); - dim_vector dv (npts, 1); - void *vplan = float_fftw_planner::create_plan (1, dv, nsamples, stride, - dist, in, out); - fftwf_plan m_plan = reinterpret_cast (vplan); + const std::size_t npts = dv.numel (); + const Complex scale = npts; + for (std::size_t i = 0; i < npts; i++) + out[i] /= scale; + + return 0; +} - fftwf_execute_dft_r2c (m_plan, (const_cast(in)), - reinterpret_cast (out)); - - // Need to create other half of the transform. - - convert_packcomplex_1d (out, nsamples, npts, stride, dist); +int +fftw::fft (const float *in, FloatComplex *out, std::size_t npts, + std::size_t nsamples, octave_idx_type stride, + octave_idx_type dist) +{ + dist = (dist < 0 ? npts : dist); - return 0; - } + dim_vector dv (npts, 1); + void *vplan = float_fftw_planner::create_plan (1, dv, nsamples, stride, + dist, in, out); + fftwf_plan m_plan = reinterpret_cast (vplan); - int - fftw::fft (const FloatComplex *in, FloatComplex *out, std::size_t npts, - std::size_t nsamples, octave_idx_type stride, - octave_idx_type dist) - { - dist = (dist < 0 ? npts : dist); + fftwf_execute_dft_r2c (m_plan, (const_cast(in)), + reinterpret_cast (out)); + + // Need to create other half of the transform. - dim_vector dv (npts, 1); - void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, 1, dv, - nsamples, stride, dist, - in, out); - fftwf_plan m_plan = reinterpret_cast (vplan); + convert_packcomplex_1d (out, nsamples, npts, stride, dist); + + return 0; +} - fftwf_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); +int +fftw::fft (const FloatComplex *in, FloatComplex *out, std::size_t npts, + std::size_t nsamples, octave_idx_type stride, + octave_idx_type dist) +{ + dist = (dist < 0 ? npts : dist); - return 0; - } + dim_vector dv (npts, 1); + void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, 1, dv, + nsamples, stride, dist, + in, out); + fftwf_plan m_plan = reinterpret_cast (vplan); - int - fftw::ifft (const FloatComplex *in, FloatComplex *out, std::size_t npts, - std::size_t nsamples, octave_idx_type stride, - octave_idx_type dist) - { - dist = (dist < 0 ? npts : dist); + fftwf_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); + + return 0; +} - dim_vector dv (npts, 1); - void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, - nsamples, stride, dist, - in, out); - fftwf_plan m_plan = reinterpret_cast (vplan); +int +fftw::ifft (const FloatComplex *in, FloatComplex *out, std::size_t npts, + std::size_t nsamples, octave_idx_type stride, + octave_idx_type dist) +{ + dist = (dist < 0 ? npts : dist); - fftwf_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); - - const FloatComplex scale = npts; - for (std::size_t j = 0; j < nsamples; j++) - for (std::size_t i = 0; i < npts; i++) - out[i*stride + j*dist] /= scale; + dim_vector dv (npts, 1); + void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, 1, dv, + nsamples, stride, dist, + in, out); + fftwf_plan m_plan = reinterpret_cast (vplan); - return 0; - } + fftwf_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); + + const FloatComplex scale = npts; + for (std::size_t j = 0; j < nsamples; j++) + for (std::size_t i = 0; i < npts; i++) + out[i*stride + j*dist] /= scale; - int - fftw::fftNd (const float *in, FloatComplex *out, const int rank, - const dim_vector& dv) - { - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); + return 0; +} - // Fool with the position of the start of the output matrix, so that - // creating other half of the matrix won't cause cache problems. - - octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); +int +fftw::fftNd (const float *in, FloatComplex *out, const int rank, + const dim_vector& dv) +{ + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - void *vplan = float_fftw_planner::create_plan (rank, dv, 1, 1, dist, - in, out + offset); - fftwf_plan m_plan = reinterpret_cast (vplan); + // Fool with the position of the start of the output matrix, so that + // creating other half of the matrix won't cause cache problems. + + octave_idx_type offset = (dv.numel () / dv(0)) * ((dv(0) - 1) / 2); - fftwf_execute_dft_r2c (m_plan, (const_cast(in)), - reinterpret_cast (out+ offset)); + void *vplan = float_fftw_planner::create_plan (rank, dv, 1, 1, dist, + in, out + offset); + fftwf_plan m_plan = reinterpret_cast (vplan); - // Need to create other half of the transform. + fftwf_execute_dft_r2c (m_plan, (const_cast(in)), + reinterpret_cast (out+ offset)); - convert_packcomplex_Nd (out, dv); + // Need to create other half of the transform. - return 0; - } + convert_packcomplex_Nd (out, dv); + + return 0; +} - int - fftw::fftNd (const FloatComplex *in, FloatComplex *out, const int rank, - const dim_vector& dv) - { - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); +int +fftw::fftNd (const FloatComplex *in, FloatComplex *out, const int rank, + const dim_vector& dv) +{ + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, rank, dv, - 1, 1, dist, in, out); - fftwf_plan m_plan = reinterpret_cast (vplan); + void *vplan = float_fftw_planner::create_plan (FFTW_FORWARD, rank, dv, + 1, 1, dist, in, out); + fftwf_plan m_plan = reinterpret_cast (vplan); - fftwf_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); + fftwf_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); - return 0; - } + return 0; +} - int - fftw::ifftNd (const FloatComplex *in, FloatComplex *out, const int rank, - const dim_vector& dv) - { - octave_idx_type dist = 1; - for (int i = 0; i < rank; i++) - dist *= dv(i); +int +fftw::ifftNd (const FloatComplex *in, FloatComplex *out, const int rank, + const dim_vector& dv) +{ + octave_idx_type dist = 1; + for (int i = 0; i < rank; i++) + dist *= dv(i); - void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, rank, dv, - 1, 1, dist, in, out); - fftwf_plan m_plan = reinterpret_cast (vplan); + void *vplan = float_fftw_planner::create_plan (FFTW_BACKWARD, rank, dv, + 1, 1, dist, in, out); + fftwf_plan m_plan = reinterpret_cast (vplan); - fftwf_execute_dft (m_plan, - reinterpret_cast (const_cast(in)), - reinterpret_cast (out)); + fftwf_execute_dft (m_plan, + reinterpret_cast (const_cast(in)), + reinterpret_cast (out)); - const std::size_t npts = dv.numel (); - const FloatComplex scale = npts; - for (std::size_t i = 0; i < npts; i++) - out[i] /= scale; + const std::size_t npts = dv.numel (); + const FloatComplex scale = npts; + for (std::size_t i = 0; i < npts; i++) + out[i] /= scale; - return 0; - } + return 0; +} #endif - std::string - fftw_version (void) - { +std::string +fftw_version (void) +{ #if defined (HAVE_FFTW) - return ::fftw_version; + return ::fftw_version; #else - return "none"; + return "none"; #endif - } +} - std::string - fftwf_version (void) - { +std::string +fftwf_version (void) +{ #if defined (HAVE_FFTW) - return ::fftwf_version; + return ::fftwf_version; #else - return "none"; + return "none"; #endif - } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-fftw.h --- a/liboctave/numeric/oct-fftw.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-fftw.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,349 +37,349 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTAVE_API - fftw_planner - { - protected: - - fftw_planner (void); - - public: - - // No copying! - - fftw_planner (const fftw_planner&) = delete; - - fftw_planner& operator = (const fftw_planner&) = delete; - - ~fftw_planner (void); - - enum FftwMethod - { - UNKNOWN = -1, - ESTIMATE, - MEASURE, - PATIENT, - EXHAUSTIVE, - HYBRID - }; - - static bool instance_ok (void); +class +OCTAVE_API +fftw_planner +{ +protected: - static void * - create_plan (int dir, const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const Complex *in, - Complex *out) - { - return instance_ok () - ? s_instance->do_create_plan (dir, rank, dims, howmany, stride, - dist, in, out) - : nullptr; - } + fftw_planner (void); - static void * - create_plan (const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const double *in, Complex *out) - { - return instance_ok () - ? s_instance->do_create_plan (rank, dims, howmany, stride, dist, - in, out) - : nullptr; - } +public: - static FftwMethod method (void) - { - static FftwMethod dummy; - - return instance_ok () ? s_instance->do_method () : dummy; - } - - static FftwMethod method (FftwMethod meth) - { - static FftwMethod dummy; - - return instance_ok () ? s_instance->do_method (meth) : dummy; - } - - static void threads (int nt); + // No copying! - static int threads (void) - { - return instance_ok () ? s_instance->m_nthreads : 0; - } - - private: - - static fftw_planner *s_instance; - - static void cleanup_instance (void) - { delete s_instance; s_instance = nullptr; } - - void * - do_create_plan (int dir, const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const Complex *in, - Complex *out); + fftw_planner (const fftw_planner&) = delete; - void * - do_create_plan (const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const double *in, Complex *out); - - FftwMethod do_method (void); - - FftwMethod do_method (FftwMethod meth); + fftw_planner& operator = (const fftw_planner&) = delete; - FftwMethod m_meth; - - // FIXME: perhaps this should be split into two classes? - - // Plan for fft and ifft of complex values - void *m_plan[2]; - - // dist - octave_idx_type m_d[2]; + ~fftw_planner (void); - // stride - octave_idx_type m_s[2]; - - // rank - int m_r[2]; - - // howmany - octave_idx_type m_h[2]; - - // dims - dim_vector m_n[2]; - - bool m_simd_align[2]; - bool m_inplace[2]; - - // Plan for fft of real values - void *m_rplan; - - // dist - octave_idx_type m_rd; - - // stride - octave_idx_type m_rs; - - // rank - int m_rr; - - // howmany - octave_idx_type m_rh; - - // dims - dim_vector m_rn; - - bool m_rsimd_align; - - // number of threads. Always 1 unless compiled with multi-threading - // support. - int m_nthreads; + enum FftwMethod + { + UNKNOWN = -1, + ESTIMATE, + MEASURE, + PATIENT, + EXHAUSTIVE, + HYBRID }; - class - OCTAVE_API - float_fftw_planner - { - protected: + static bool instance_ok (void); - float_fftw_planner (void); - - public: - - // No copying! - - float_fftw_planner (const float_fftw_planner&) = delete; + static void * + create_plan (int dir, const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const Complex *in, + Complex *out) + { + return instance_ok () + ? s_instance->do_create_plan (dir, rank, dims, howmany, stride, + dist, in, out) + : nullptr; + } - float_fftw_planner& - operator = (const float_fftw_planner&) = delete; - - ~float_fftw_planner (void); + static void * + create_plan (const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const double *in, Complex *out) + { + return instance_ok () + ? s_instance->do_create_plan (rank, dims, howmany, stride, dist, + in, out) + : nullptr; + } - enum FftwMethod - { - UNKNOWN = -1, - ESTIMATE, - MEASURE, - PATIENT, - EXHAUSTIVE, - HYBRID - }; + static FftwMethod method (void) + { + static FftwMethod dummy; - static bool instance_ok (void); + return instance_ok () ? s_instance->do_method () : dummy; + } + + static FftwMethod method (FftwMethod meth) + { + static FftwMethod dummy; - static void * - create_plan (int dir, const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const FloatComplex *in, - FloatComplex *out) - { - return instance_ok () - ? s_instance->do_create_plan (dir, rank, dims, howmany, stride, - dist, in, out) - : nullptr; - } + return instance_ok () ? s_instance->do_method (meth) : dummy; + } + + static void threads (int nt); + + static int threads (void) + { + return instance_ok () ? s_instance->m_nthreads : 0; + } + +private: + + static fftw_planner *s_instance; + + static void cleanup_instance (void) + { delete s_instance; s_instance = nullptr; } - static void * - create_plan (const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const float *in, FloatComplex *out) - { - return instance_ok () - ? s_instance->do_create_plan (rank, dims, howmany, stride, dist, - in, out) - : nullptr; - } + void * + do_create_plan (int dir, const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const Complex *in, + Complex *out); - static FftwMethod method (void) - { - static FftwMethod dummy; - - return instance_ok () ? s_instance->do_method () : dummy; - } + void * + do_create_plan (const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const double *in, Complex *out); - static FftwMethod method (FftwMethod meth) - { - static FftwMethod dummy; + FftwMethod do_method (void); + + FftwMethod do_method (FftwMethod meth); - return instance_ok () ? s_instance->do_method (meth) : dummy; - } + FftwMethod m_meth; - static void threads (int nt); + // FIXME: perhaps this should be split into two classes? - static int threads (void) - { - return instance_ok () ? s_instance->m_nthreads : 0; - } + // Plan for fft and ifft of complex values + void *m_plan[2]; - private: + // dist + octave_idx_type m_d[2]; - static float_fftw_planner *s_instance; + // stride + octave_idx_type m_s[2]; - static void cleanup_instance (void) - { delete s_instance; s_instance = nullptr; } + // rank + int m_r[2]; - void * - do_create_plan (int dir, const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const FloatComplex *in, - FloatComplex *out); + // howmany + octave_idx_type m_h[2]; + + // dims + dim_vector m_n[2]; - void * - do_create_plan (const int rank, const dim_vector& dims, - octave_idx_type howmany, octave_idx_type stride, - octave_idx_type dist, const float *in, FloatComplex *out); + bool m_simd_align[2]; + bool m_inplace[2]; - FftwMethod do_method (void); + // Plan for fft of real values + void *m_rplan; - FftwMethod do_method (FftwMethod meth); + // dist + octave_idx_type m_rd; - FftwMethod m_meth; - - // FIXME: perhaps this should be split into two classes? + // stride + octave_idx_type m_rs; - // Plan for fft and ifft of complex values - void *m_plan[2]; + // rank + int m_rr; - // dist - octave_idx_type m_d[2]; + // howmany + octave_idx_type m_rh; - // stride - octave_idx_type m_s[2]; + // dims + dim_vector m_rn; - // rank - int m_r[2]; - - // howmany - octave_idx_type m_h[2]; + bool m_rsimd_align; - // dims - dim_vector m_n[2]; + // number of threads. Always 1 unless compiled with multi-threading + // support. + int m_nthreads; +}; - bool m_simd_align[2]; - bool m_inplace[2]; +class +OCTAVE_API +float_fftw_planner +{ +protected: - // Plan for fft of real values - void *m_rplan; + float_fftw_planner (void); - // dist - octave_idx_type m_rd; +public: + + // No copying! - // stride - octave_idx_type m_rs; + float_fftw_planner (const float_fftw_planner&) = delete; - // rank - int m_rr; + float_fftw_planner& + operator = (const float_fftw_planner&) = delete; - // howmany - octave_idx_type m_rh; - - // dims - dim_vector m_rn; + ~float_fftw_planner (void); - bool m_rsimd_align; - - // number of threads. Always 1 unless compiled with multi-threading - // support. - int m_nthreads; + enum FftwMethod + { + UNKNOWN = -1, + ESTIMATE, + MEASURE, + PATIENT, + EXHAUSTIVE, + HYBRID }; - class - OCTAVE_API - fftw + static bool instance_ok (void); + + static void * + create_plan (int dir, const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const FloatComplex *in, + FloatComplex *out) { - public: + return instance_ok () + ? s_instance->do_create_plan (dir, rank, dims, howmany, stride, + dist, in, out) + : nullptr; + } - fftw (void) = delete; + static void * + create_plan (const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const float *in, FloatComplex *out) + { + return instance_ok () + ? s_instance->do_create_plan (rank, dims, howmany, stride, dist, + in, out) + : nullptr; + } - // No copying. + static FftwMethod method (void) + { + static FftwMethod dummy; + + return instance_ok () ? s_instance->do_method () : dummy; + } - fftw (const fftw&) = delete; + static FftwMethod method (FftwMethod meth) + { + static FftwMethod dummy; + + return instance_ok () ? s_instance->do_method (meth) : dummy; + } + + static void threads (int nt); - fftw& operator = (const fftw&) = delete; + static int threads (void) + { + return instance_ok () ? s_instance->m_nthreads : 0; + } + +private: + + static float_fftw_planner *s_instance; + + static void cleanup_instance (void) + { delete s_instance; s_instance = nullptr; } + + void * + do_create_plan (int dir, const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const FloatComplex *in, + FloatComplex *out); - static int fft (const double *in, Complex *out, std::size_t npts, - std::size_t nsamples = 1, octave_idx_type stride = 1, - octave_idx_type dist = -1); - static int fft (const Complex *in, Complex *out, std::size_t npts, - std::size_t nsamples = 1, octave_idx_type stride = 1, - octave_idx_type dist = -1); - static int ifft (const Complex *in, Complex *out, std::size_t npts, - std::size_t nsamples = 1, octave_idx_type stride = 1, - octave_idx_type dist = -1); + void * + do_create_plan (const int rank, const dim_vector& dims, + octave_idx_type howmany, octave_idx_type stride, + octave_idx_type dist, const float *in, FloatComplex *out); + + FftwMethod do_method (void); + + FftwMethod do_method (FftwMethod meth); + + FftwMethod m_meth; + + // FIXME: perhaps this should be split into two classes? + + // Plan for fft and ifft of complex values + void *m_plan[2]; + + // dist + octave_idx_type m_d[2]; + + // stride + octave_idx_type m_s[2]; + + // rank + int m_r[2]; - static int fftNd (const double *, Complex *, const int, const dim_vector&); - static int fftNd (const Complex *, Complex *, const int, - const dim_vector&); - static int ifftNd (const Complex *, Complex *, const int, - const dim_vector&); + // howmany + octave_idx_type m_h[2]; + + // dims + dim_vector m_n[2]; + + bool m_simd_align[2]; + bool m_inplace[2]; + + // Plan for fft of real values + void *m_rplan; + + // dist + octave_idx_type m_rd; + + // stride + octave_idx_type m_rs; + + // rank + int m_rr; + + // howmany + octave_idx_type m_rh; + + // dims + dim_vector m_rn; + + bool m_rsimd_align; + + // number of threads. Always 1 unless compiled with multi-threading + // support. + int m_nthreads; +}; + +class +OCTAVE_API +fftw +{ +public: + + fftw (void) = delete; - static int fft (const float *in, FloatComplex *out, std::size_t npts, - std::size_t nsamples = 1, octave_idx_type stride = 1, - octave_idx_type dist = -1); - static int fft (const FloatComplex *in, FloatComplex *out, std::size_t npts, - std::size_t nsamples = 1, octave_idx_type stride = 1, - octave_idx_type dist = -1); - static int ifft (const FloatComplex *in, FloatComplex *out, std::size_t npts, - std::size_t nsamples = 1, octave_idx_type stride = 1, - octave_idx_type dist = -1); + // No copying. + + fftw (const fftw&) = delete; + + fftw& operator = (const fftw&) = delete; + + static int fft (const double *in, Complex *out, std::size_t npts, + std::size_t nsamples = 1, octave_idx_type stride = 1, + octave_idx_type dist = -1); + static int fft (const Complex *in, Complex *out, std::size_t npts, + std::size_t nsamples = 1, octave_idx_type stride = 1, + octave_idx_type dist = -1); + static int ifft (const Complex *in, Complex *out, std::size_t npts, + std::size_t nsamples = 1, octave_idx_type stride = 1, + octave_idx_type dist = -1); - static int fftNd (const float *, FloatComplex *, const int, - const dim_vector&); - static int fftNd (const FloatComplex *, FloatComplex *, const int, - const dim_vector&); - static int ifftNd (const FloatComplex *, FloatComplex *, const int, - const dim_vector&); - }; + static int fftNd (const double *, Complex *, const int, const dim_vector&); + static int fftNd (const Complex *, Complex *, const int, + const dim_vector&); + static int ifftNd (const Complex *, Complex *, const int, + const dim_vector&); - extern OCTAVE_API std::string fftw_version (void); - extern OCTAVE_API std::string fftwf_version (void); + static int fft (const float *in, FloatComplex *out, std::size_t npts, + std::size_t nsamples = 1, octave_idx_type stride = 1, + octave_idx_type dist = -1); + static int fft (const FloatComplex *in, FloatComplex *out, std::size_t npts, + std::size_t nsamples = 1, octave_idx_type stride = 1, + octave_idx_type dist = -1); + static int ifft (const FloatComplex *in, FloatComplex *out, std::size_t npts, + std::size_t nsamples = 1, octave_idx_type stride = 1, + octave_idx_type dist = -1); + + static int fftNd (const float *, FloatComplex *, const int, + const dim_vector&); + static int fftNd (const FloatComplex *, FloatComplex *, const int, + const dim_vector&); + static int ifftNd (const FloatComplex *, FloatComplex *, const int, + const dim_vector&); +}; + +extern OCTAVE_API std::string fftw_version (void); +extern OCTAVE_API std::string fftwf_version (void); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-norm.cc diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-norm.h --- a/liboctave/numeric/oct-norm.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-norm.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,49 +34,49 @@ OCTAVE_BEGIN_NAMESPACE(octave) - extern OCTAVE_API double xnorm (const ColumnVector&, double p = 2); - extern OCTAVE_API double xnorm (const RowVector&, double p = 2); - extern OCTAVE_API double xnorm (const Matrix&, double p = 2); - extern OCTAVE_API double xfrobnorm (const Matrix&); +extern OCTAVE_API double xnorm (const ColumnVector&, double p = 2); +extern OCTAVE_API double xnorm (const RowVector&, double p = 2); +extern OCTAVE_API double xnorm (const Matrix&, double p = 2); +extern OCTAVE_API double xfrobnorm (const Matrix&); - extern OCTAVE_API double xnorm (const ComplexColumnVector&, double p = 2); - extern OCTAVE_API double xnorm (const ComplexRowVector&, double p = 2); - extern OCTAVE_API double xnorm (const ComplexMatrix&, double p = 2); - extern OCTAVE_API double xfrobnorm (const ComplexMatrix&); +extern OCTAVE_API double xnorm (const ComplexColumnVector&, double p = 2); +extern OCTAVE_API double xnorm (const ComplexRowVector&, double p = 2); +extern OCTAVE_API double xnorm (const ComplexMatrix&, double p = 2); +extern OCTAVE_API double xfrobnorm (const ComplexMatrix&); - extern OCTAVE_API float xnorm (const FloatColumnVector&, float p = 2); - extern OCTAVE_API float xnorm (const FloatRowVector&, float p = 2); - extern OCTAVE_API float xnorm (const FloatMatrix&, float p = 2); - extern OCTAVE_API float xfrobnorm (const FloatMatrix&); +extern OCTAVE_API float xnorm (const FloatColumnVector&, float p = 2); +extern OCTAVE_API float xnorm (const FloatRowVector&, float p = 2); +extern OCTAVE_API float xnorm (const FloatMatrix&, float p = 2); +extern OCTAVE_API float xfrobnorm (const FloatMatrix&); - extern OCTAVE_API float xnorm (const FloatComplexColumnVector&, float p = 2); - extern OCTAVE_API float xnorm (const FloatComplexRowVector&, float p = 2); - extern OCTAVE_API float xnorm (const FloatComplexMatrix&, float p = 2); - extern OCTAVE_API float xfrobnorm (const FloatComplexMatrix&); +extern OCTAVE_API float xnorm (const FloatComplexColumnVector&, float p = 2); +extern OCTAVE_API float xnorm (const FloatComplexRowVector&, float p = 2); +extern OCTAVE_API float xnorm (const FloatComplexMatrix&, float p = 2); +extern OCTAVE_API float xfrobnorm (const FloatComplexMatrix&); - extern OCTAVE_API double xnorm (const SparseMatrix&, double p = 2); - extern OCTAVE_API double xfrobnorm (const SparseMatrix&); +extern OCTAVE_API double xnorm (const SparseMatrix&, double p = 2); +extern OCTAVE_API double xfrobnorm (const SparseMatrix&); - extern OCTAVE_API double xnorm (const SparseComplexMatrix&, double p = 2); - extern OCTAVE_API double xfrobnorm (const SparseComplexMatrix&); +extern OCTAVE_API double xnorm (const SparseComplexMatrix&, double p = 2); +extern OCTAVE_API double xfrobnorm (const SparseComplexMatrix&); - extern OCTAVE_API RowVector xcolnorms (const Matrix&, double p = 2); - extern OCTAVE_API ColumnVector xrownorms (const Matrix&, double p = 2); +extern OCTAVE_API RowVector xcolnorms (const Matrix&, double p = 2); +extern OCTAVE_API ColumnVector xrownorms (const Matrix&, double p = 2); - extern OCTAVE_API RowVector xcolnorms (const ComplexMatrix&, double p = 2); - extern OCTAVE_API ColumnVector xrownorms (const ComplexMatrix&, double p = 2); +extern OCTAVE_API RowVector xcolnorms (const ComplexMatrix&, double p = 2); +extern OCTAVE_API ColumnVector xrownorms (const ComplexMatrix&, double p = 2); - extern OCTAVE_API FloatRowVector xcolnorms (const FloatMatrix&, float p = 2); - extern OCTAVE_API FloatColumnVector xrownorms (const FloatMatrix&, float p = 2); +extern OCTAVE_API FloatRowVector xcolnorms (const FloatMatrix&, float p = 2); +extern OCTAVE_API FloatColumnVector xrownorms (const FloatMatrix&, float p = 2); - extern OCTAVE_API FloatRowVector xcolnorms (const FloatComplexMatrix&, float p = 2); - extern OCTAVE_API FloatColumnVector xrownorms (const FloatComplexMatrix&, float p = 2); +extern OCTAVE_API FloatRowVector xcolnorms (const FloatComplexMatrix&, float p = 2); +extern OCTAVE_API FloatColumnVector xrownorms (const FloatComplexMatrix&, float p = 2); - extern OCTAVE_API RowVector xcolnorms (const SparseMatrix&, double p = 2); - extern OCTAVE_API ColumnVector xrownorms (const SparseMatrix&, double p = 2); +extern OCTAVE_API RowVector xcolnorms (const SparseMatrix&, double p = 2); +extern OCTAVE_API ColumnVector xrownorms (const SparseMatrix&, double p = 2); - extern OCTAVE_API RowVector xcolnorms (const SparseComplexMatrix&, double p = 2); - extern OCTAVE_API ColumnVector xrownorms (const SparseComplexMatrix&, double p = 2); +extern OCTAVE_API RowVector xcolnorms (const SparseComplexMatrix&, double p = 2); +extern OCTAVE_API ColumnVector xrownorms (const SparseComplexMatrix&, double p = 2); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-rand.cc --- a/liboctave/numeric/oct-rand.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-rand.cc Thu Dec 01 20:05:44 2022 -0800 @@ -48,747 +48,747 @@ OCTAVE_BEGIN_NAMESPACE(octave) - rand *rand::m_instance = nullptr; +rand *rand::m_instance = nullptr; - rand::rand (void) - : m_current_distribution (uniform_dist), m_use_old_generators (false), - m_rand_states () - { - initialize_ranlib_generators (); +rand::rand (void) + : m_current_distribution (uniform_dist), m_use_old_generators (false), + m_rand_states () +{ + initialize_ranlib_generators (); - initialize_mersenne_twister (); - } - - bool rand::instance_ok (void) - { - bool retval = true; + initialize_mersenne_twister (); +} - if (! m_instance) - { - m_instance = new rand (); - singleton_cleanup_list::add (cleanup_instance); - } - - return retval; - } +bool rand::instance_ok (void) +{ + bool retval = true; - double rand::do_seed (void) - { - union d2i { double d; int32_t i[2]; }; - union d2i u; + if (! m_instance) + { + m_instance = new rand (); + singleton_cleanup_list::add (cleanup_instance); + } - mach_info::float_format ff = mach_info::native_float_format (); - - switch (ff) - { - case mach_info::flt_fmt_ieee_big_endian: - F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]); - break; + return retval; +} - default: - F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]); - break; - } - - return u.d; - } +double rand::do_seed (void) +{ + union d2i { double d; int32_t i[2]; }; + union d2i u; - static int32_t - force_to_fit_range (int32_t i, int32_t lo, int32_t hi) - { - assert (hi > lo && lo >= 0); + mach_info::float_format ff = mach_info::native_float_format (); - i = (i > 0 ? i : -i); - - if (i < lo) - i = lo; - else if (i > hi) - i = i % hi; + switch (ff) + { + case mach_info::flt_fmt_ieee_big_endian: + F77_FUNC (getsd, GETSD) (u.i[1], u.i[0]); + break; - return i; - } - - void rand::do_seed (double s) - { - m_use_old_generators = true; + default: + F77_FUNC (getsd, GETSD) (u.i[0], u.i[1]); + break; + } - int i0, i1; - union d2i { double d; int32_t i[2]; }; - union d2i u; - u.d = s; - - mach_info::float_format ff = mach_info::native_float_format (); + return u.d; +} - switch (ff) - { - case mach_info::flt_fmt_ieee_big_endian: - i1 = force_to_fit_range (u.i[0], 1, 2147483563); - i0 = force_to_fit_range (u.i[1], 1, 2147483399); - break; +static int32_t +force_to_fit_range (int32_t i, int32_t lo, int32_t hi) +{ + assert (hi > lo && lo >= 0); + + i = (i > 0 ? i : -i); - default: - i0 = force_to_fit_range (u.i[0], 1, 2147483563); - i1 = force_to_fit_range (u.i[1], 1, 2147483399); - break; - } - - F77_FUNC (setsd, SETSD) (i0, i1); - } + if (i < lo) + i = lo; + else if (i > hi) + i = i % hi; - void rand::do_reset (void) - { - m_use_old_generators = true; - initialize_ranlib_generators (); - } + return i; +} - uint32NDArray rand::do_state (const std::string& d) - { - return m_rand_states[d.empty () ? m_current_distribution : get_dist_id (d)]; - } +void rand::do_seed (double s) +{ + m_use_old_generators = true; - void rand::do_state (const uint32NDArray& s, const std::string& d) - { - m_use_old_generators = false; + int i0, i1; + union d2i { double d; int32_t i[2]; }; + union d2i u; + u.d = s; - int old_dist = m_current_distribution; - - int new_dist = (d.empty () ? m_current_distribution : get_dist_id (d)); - - uint32NDArray saved_state; + mach_info::float_format ff = mach_info::native_float_format (); - if (old_dist != new_dist) - saved_state = get_internal_state (); - - set_internal_state (s); - - m_rand_states[new_dist] = get_internal_state (); - - if (old_dist != new_dist) - m_rand_states[old_dist] = saved_state; - } + switch (ff) + { + case mach_info::flt_fmt_ieee_big_endian: + i1 = force_to_fit_range (u.i[0], 1, 2147483563); + i0 = force_to_fit_range (u.i[1], 1, 2147483399); + break; - void rand::do_reset (const std::string& d) - { - m_use_old_generators = false; - - int old_dist = m_current_distribution; - - int new_dist = (d.empty () ? m_current_distribution : get_dist_id (d)); - - uint32NDArray saved_state; + default: + i0 = force_to_fit_range (u.i[0], 1, 2147483563); + i1 = force_to_fit_range (u.i[1], 1, 2147483399); + break; + } - if (old_dist != new_dist) - saved_state = get_internal_state (); + F77_FUNC (setsd, SETSD) (i0, i1); +} - init_mersenne_twister (); - m_rand_states[new_dist] = get_internal_state (); - - if (old_dist != new_dist) - m_rand_states[old_dist] = saved_state; - } +void rand::do_reset (void) +{ + m_use_old_generators = true; + initialize_ranlib_generators (); +} - std::string rand::do_distribution (void) - { - std::string retval; - - switch (m_current_distribution) - { - case uniform_dist: - retval = "uniform"; - break; +uint32NDArray rand::do_state (const std::string& d) +{ + return m_rand_states[d.empty () ? m_current_distribution : get_dist_id (d)]; +} - case normal_dist: - retval = "normal"; - break; - - case expon_dist: - retval = "exponential"; - break; +void rand::do_state (const uint32NDArray& s, const std::string& d) +{ + m_use_old_generators = false; - case poisson_dist: - retval = "poisson"; - break; + int old_dist = m_current_distribution; - case gamma_dist: - retval = "gamma"; - break; + int new_dist = (d.empty () ? m_current_distribution : get_dist_id (d)); + + uint32NDArray saved_state; - default: - (*current_liboctave_error_handler) - ("rand: invalid distribution ID = %d", m_current_distribution); - break; - } + if (old_dist != new_dist) + saved_state = get_internal_state (); + + set_internal_state (s); - return retval; - } + m_rand_states[new_dist] = get_internal_state (); - void rand::do_distribution (const std::string& d) - { - int id = get_dist_id (d); + if (old_dist != new_dist) + m_rand_states[old_dist] = saved_state; +} - switch (id) - { - case uniform_dist: - rand::uniform_distribution (); - break; +void rand::do_reset (const std::string& d) +{ + m_use_old_generators = false; - case normal_dist: - rand::normal_distribution (); - break; + int old_dist = m_current_distribution; - case expon_dist: - rand::exponential_distribution (); - break; + int new_dist = (d.empty () ? m_current_distribution : get_dist_id (d)); - case poisson_dist: - rand::poisson_distribution (); - break; + uint32NDArray saved_state; - case gamma_dist: - rand::gamma_distribution (); - break; + if (old_dist != new_dist) + saved_state = get_internal_state (); - default: - (*current_liboctave_error_handler) - ("rand: invalid distribution ID = %d", id); - break; - } - } + init_mersenne_twister (); + m_rand_states[new_dist] = get_internal_state (); - void rand::do_uniform_distribution (void) - { - switch_to_generator (uniform_dist); - - F77_FUNC (setcgn, SETCGN) (uniform_dist); - } + if (old_dist != new_dist) + m_rand_states[old_dist] = saved_state; +} - void rand::do_normal_distribution (void) - { - switch_to_generator (normal_dist); - - F77_FUNC (setcgn, SETCGN) (normal_dist); - } +std::string rand::do_distribution (void) +{ + std::string retval; - void rand::do_exponential_distribution (void) - { - switch_to_generator (expon_dist); - - F77_FUNC (setcgn, SETCGN) (expon_dist); - } - - void rand::do_poisson_distribution (void) - { - switch_to_generator (poisson_dist); + switch (m_current_distribution) + { + case uniform_dist: + retval = "uniform"; + break; - F77_FUNC (setcgn, SETCGN) (poisson_dist); - } - - void rand::do_gamma_distribution (void) - { - switch_to_generator (gamma_dist); + case normal_dist: + retval = "normal"; + break; - F77_FUNC (setcgn, SETCGN) (gamma_dist); - } + case expon_dist: + retval = "exponential"; + break; - template <> - OCTAVE_API double rand::uniform (void) - { - double retval; + case poisson_dist: + retval = "poisson"; + break; - if (m_use_old_generators) - F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval); - else - retval = rand_uniform (); - - return retval; - } + case gamma_dist: + retval = "gamma"; + break; - template <> - OCTAVE_API double rand::normal (void) - { - double retval; + default: + (*current_liboctave_error_handler) + ("rand: invalid distribution ID = %d", m_current_distribution); + break; + } - if (m_use_old_generators) - F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval); - else - retval = rand_normal (); + return retval; +} - return retval; - } - - template <> - OCTAVE_API double rand::exponential (void) - { - double retval; +void rand::do_distribution (const std::string& d) +{ + int id = get_dist_id (d); - if (m_use_old_generators) - F77_FUNC (dgenexp, DGENEXP) (1.0, retval); - else - retval = rand_exponential (); + switch (id) + { + case uniform_dist: + rand::uniform_distribution (); + break; - return retval; - } - - template <> - OCTAVE_API double rand::poisson (double a) - { - double retval; + case normal_dist: + rand::normal_distribution (); + break; - if (m_use_old_generators) - { - if (a < 0.0 || ! math::isfinite (a)) - retval = numeric_limits::NaN (); - else - { - // workaround bug in ignpoi, by calling with different Mu - F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval); - F77_FUNC (dignpoi, DIGNPOI) (a, retval); - } - } - else - retval = rand_poisson (a); + case expon_dist: + rand::exponential_distribution (); + break; - return retval; - } + case poisson_dist: + rand::poisson_distribution (); + break; - template <> - OCTAVE_API double rand::gamma (double a) - { - double retval; + case gamma_dist: + rand::gamma_distribution (); + break; - if (m_use_old_generators) - { - if (a <= 0.0 || ! math::isfinite (a)) - retval = numeric_limits::NaN (); - else - F77_FUNC (dgengam, DGENGAM) (1.0, a, retval); - } - else - retval = rand_gamma (a); - - return retval; - } + default: + (*current_liboctave_error_handler) + ("rand: invalid distribution ID = %d", id); + break; + } +} - template <> - OCTAVE_API float rand::uniform (void) - { - float retval; +void rand::do_uniform_distribution (void) +{ + switch_to_generator (uniform_dist); - if (m_use_old_generators) - F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, retval); - else - retval = rand_uniform (); + F77_FUNC (setcgn, SETCGN) (uniform_dist); +} - return retval; - } +void rand::do_normal_distribution (void) +{ + switch_to_generator (normal_dist); - template <> - OCTAVE_API float rand::normal (void) - { - float retval; + F77_FUNC (setcgn, SETCGN) (normal_dist); +} - if (m_use_old_generators) - F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, retval); - else - retval = rand_normal (); +void rand::do_exponential_distribution (void) +{ + switch_to_generator (expon_dist); - return retval; - } + F77_FUNC (setcgn, SETCGN) (expon_dist); +} - template <> - OCTAVE_API float rand::exponential (void) - { - float retval; +void rand::do_poisson_distribution (void) +{ + switch_to_generator (poisson_dist); + + F77_FUNC (setcgn, SETCGN) (poisson_dist); +} - if (m_use_old_generators) - F77_FUNC (fgenexp, FGENEXP) (1.0f, retval); - else - retval = rand_exponential (); +void rand::do_gamma_distribution (void) +{ + switch_to_generator (gamma_dist); - return retval; - } - - template <> - OCTAVE_API float rand::poisson (float a) - { - float retval; + F77_FUNC (setcgn, SETCGN) (gamma_dist); +} - if (m_use_old_generators) - { - if (a < 0.0f || ! math::isfinite (a)) - retval = numeric_limits::NaN (); - else - { - // workaround bug in ignpoi, by calling with different Mu - F77_FUNC (fignpoi, FIGNPOI) (a + 1, retval); - F77_FUNC (fignpoi, FIGNPOI) (a, retval); - } - } - else - { - // Keep poisson distribution in double precision for accuracy - retval = rand_poisson (a); - } +template <> +OCTAVE_API double rand::uniform (void) +{ + double retval; - return retval; - } + if (m_use_old_generators) + F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, retval); + else + retval = rand_uniform (); + + return retval; +} - template <> - OCTAVE_API float rand::gamma (float a) - { - float retval; +template <> +OCTAVE_API double rand::normal (void) +{ + double retval; - if (m_use_old_generators) - { - if (a <= 0.0f || ! math::isfinite (a)) - retval = numeric_limits::NaN (); - else - F77_FUNC (fgengam, FGENGAM) (1.0f, a, retval); - } - else - retval = rand_gamma (a); + if (m_use_old_generators) + F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, retval); + else + retval = rand_normal (); - return retval; - } - - template - T rand::do_scalar (T a) - { - T retval = 0; - - switch (m_current_distribution) - { - case uniform_dist: - retval = uniform (); - break; + return retval; +} - case normal_dist: - retval = normal (); - break; - - case expon_dist: - retval = exponential (); - break; - - case poisson_dist: - retval = poisson (a); - break; - - case gamma_dist: - retval = gamma (a); - break; +template <> +OCTAVE_API double rand::exponential (void) +{ + double retval; - default: - (*current_liboctave_error_handler) - ("rand: invalid distribution ID = %d", m_current_distribution); - break; - } - - if (! m_use_old_generators) - save_state (); - - return retval; - } + if (m_use_old_generators) + F77_FUNC (dgenexp, DGENEXP) (1.0, retval); + else + retval = rand_exponential (); - template OCTAVE_API double rand::do_scalar (double); - template OCTAVE_API float rand::do_scalar (float); + return retval; +} - template - Array - rand::do_vector (octave_idx_type n, T a) - { - Array retval; - - if (n > 0) - { - retval.clear (n, 1); +template <> +OCTAVE_API double rand::poisson (double a) +{ + double retval; - fill (retval.numel (), retval.fortran_vec (), a); - } - else if (n < 0) - (*current_liboctave_error_handler) ("rand: invalid negative argument"); - - return retval; - } + if (m_use_old_generators) + { + if (a < 0.0 || ! math::isfinite (a)) + retval = numeric_limits::NaN (); + else + { + // workaround bug in ignpoi, by calling with different Mu + F77_FUNC (dignpoi, DIGNPOI) (a + 1, retval); + F77_FUNC (dignpoi, DIGNPOI) (a, retval); + } + } + else + retval = rand_poisson (a); - template OCTAVE_API Array - rand::do_vector (octave_idx_type, double); - template OCTAVE_API Array - rand::do_vector (octave_idx_type, float); - - NDArray rand::do_nd_array (const dim_vector& dims, double a) - { - NDArray retval; - - if (! dims.all_zero ()) - { - retval.clear (dims); + return retval; +} - fill (retval.numel (), retval.fortran_vec (), a); - } - - return retval; - } - - FloatNDArray rand::do_float_nd_array (const dim_vector& dims, float a) - { - FloatNDArray retval; +template <> +OCTAVE_API double rand::gamma (double a) +{ + double retval; - if (! dims.all_zero ()) - { - retval.clear (dims); - - fill (retval.numel (), retval.fortran_vec (), a); - } + if (m_use_old_generators) + { + if (a <= 0.0 || ! math::isfinite (a)) + retval = numeric_limits::NaN (); + else + F77_FUNC (dgengam, DGENGAM) (1.0, a, retval); + } + else + retval = rand_gamma (a); - return retval; - } + return retval; +} - // Make the random number generator give us a different sequence every - // time we start octave unless we specifically set the seed. The - // technique used below will cycle monthly, but it does seem to - // work ok to give fairly different seeds each time Octave starts. +template <> +OCTAVE_API float rand::uniform (void) +{ + float retval; - void rand::initialize_ranlib_generators (void) - { - sys::localtime tm; - int stored_distribution = m_current_distribution; - F77_FUNC (setcgn, SETCGN) (uniform_dist); - - int hour = tm.hour () + 1; - int minute = tm.min () + 1; - int second = tm.sec () + 1; + if (m_use_old_generators) + F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, retval); + else + retval = rand_uniform (); - int32_t s0 = tm.mday () * hour * minute * second; - int32_t s1 = hour * minute * second; + return retval; +} - s0 = force_to_fit_range (s0, 1, 2147483563); - s1 = force_to_fit_range (s1, 1, 2147483399); - - F77_FUNC (setall, SETALL) (s0, s1); - F77_FUNC (setcgn, SETCGN) (stored_distribution); - } +template <> +OCTAVE_API float rand::normal (void) +{ + float retval; - void rand::initialize_mersenne_twister (void) - { - uint32NDArray s; - - init_mersenne_twister (); - s = get_internal_state (); - m_rand_states[uniform_dist] = s; + if (m_use_old_generators) + F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, retval); + else + retval = rand_normal (); - init_mersenne_twister (); - s = get_internal_state (); - m_rand_states[normal_dist] = s; + return retval; +} - init_mersenne_twister (); - s = get_internal_state (); - m_rand_states[expon_dist] = s; - - init_mersenne_twister (); - s = get_internal_state (); - m_rand_states[poisson_dist] = s; +template <> +OCTAVE_API float rand::exponential (void) +{ + float retval; - init_mersenne_twister (); - s = get_internal_state (); - m_rand_states[gamma_dist] = s; - - // All of the initializations above have messed with the internal state. - // Restore the state of the currently selected distribution. - set_internal_state (m_rand_states[m_current_distribution]); - } + if (m_use_old_generators) + F77_FUNC (fgenexp, FGENEXP) (1.0f, retval); + else + retval = rand_exponential (); - uint32NDArray rand::get_internal_state (void) - { - uint32NDArray s (dim_vector (MT_N + 1, 1)); + return retval; +} - get_mersenne_twister_state (reinterpret_cast (s.fortran_vec ())); - - return s; - } +template <> +OCTAVE_API float rand::poisson (float a) +{ + float retval; - void rand::save_state (void) - { - m_rand_states[m_current_distribution] = get_internal_state ();; - } - - int rand::get_dist_id (const std::string& d) - { - int retval = unknown_dist; - - if (d == "uniform" || d == "rand") - retval = uniform_dist; - else if (d == "normal" || d == "randn") - retval = normal_dist; - else if (d == "exponential" || d == "rande") - retval = expon_dist; - else if (d == "poisson" || d == "randp") - retval = poisson_dist; - else if (d == "gamma" || d == "randg") - retval = gamma_dist; - else - (*current_liboctave_error_handler) - ("rand: invalid distribution '%s'", d.c_str ()); - - return retval; - } + if (m_use_old_generators) + { + if (a < 0.0f || ! math::isfinite (a)) + retval = numeric_limits::NaN (); + else + { + // workaround bug in ignpoi, by calling with different Mu + F77_FUNC (fignpoi, FIGNPOI) (a + 1, retval); + F77_FUNC (fignpoi, FIGNPOI) (a, retval); + } + } + else + { + // Keep poisson distribution in double precision for accuracy + retval = rand_poisson (a); + } - void rand::set_internal_state (const uint32NDArray& s) - { - octave_idx_type len = s.numel (); - - const uint32_t *sdata = reinterpret_cast (s.data ()); + return retval; +} - if (len == MT_N + 1 && sdata[MT_N] <= MT_N && sdata[MT_N] > 0) - set_mersenne_twister_state (sdata); - else - init_mersenne_twister (sdata, len); - } - - void rand::switch_to_generator (int dist) - { - if (dist != m_current_distribution) - { - m_current_distribution = dist; +template <> +OCTAVE_API float rand::gamma (float a) +{ + float retval; - set_internal_state (m_rand_states[dist]); - } - } - - void rand::fill (octave_idx_type len, double *v, double a) - { - if (len < 1) - return; + if (m_use_old_generators) + { + if (a <= 0.0f || ! math::isfinite (a)) + retval = numeric_limits::NaN (); + else + F77_FUNC (fgengam, FGENGAM) (1.0f, a, retval); + } + else + retval = rand_gamma (a); - switch (m_current_distribution) - { - case uniform_dist: - if (m_use_old_generators) - std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; }); - else - rand_uniform (len, v); - break; + return retval; +} - case normal_dist: - if (m_use_old_generators) - std::generate_n (v, len, [](void) { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; }); - else - rand_normal (len, v); - break; +template +T rand::do_scalar (T a) +{ + T retval = 0; - case expon_dist: - if (m_use_old_generators) - std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; }); - else - rand_exponential (len, v); - break; + switch (m_current_distribution) + { + case uniform_dist: + retval = uniform (); + break; + + case normal_dist: + retval = normal (); + break; + + case expon_dist: + retval = exponential (); + break; - case poisson_dist: - if (m_use_old_generators) - { - if (a < 0.0 || ! math::isfinite (a)) - std::fill_n (v, len, numeric_limits::NaN ()); - else - { - // workaround bug in ignpoi, by calling with different Mu - double tmp; - F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp); - std::generate_n (v, len, [a](void) { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; }); - } - } - else - rand_poisson (a, len, v); - break; + case poisson_dist: + retval = poisson (a); + break; + + case gamma_dist: + retval = gamma (a); + break; - case gamma_dist: - if (m_use_old_generators) - { - if (a <= 0.0 || ! math::isfinite (a)) - std::fill_n (v, len, numeric_limits::NaN ()); - else - std::generate_n (v, len, [a](void) { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; }); - } - else - rand_gamma (a, len, v); - break; + default: + (*current_liboctave_error_handler) + ("rand: invalid distribution ID = %d", m_current_distribution); + break; + } - default: - (*current_liboctave_error_handler) - ("rand: invalid distribution ID = %d", m_current_distribution); - break; - } - + if (! m_use_old_generators) save_state (); - return; - } + return retval; +} + +template OCTAVE_API double rand::do_scalar (double); +template OCTAVE_API float rand::do_scalar (float); + +template +Array +rand::do_vector (octave_idx_type n, T a) +{ + Array retval; + + if (n > 0) + { + retval.clear (n, 1); + + fill (retval.numel (), retval.fortran_vec (), a); + } + else if (n < 0) + (*current_liboctave_error_handler) ("rand: invalid negative argument"); + + return retval; +} + +template OCTAVE_API Array +rand::do_vector (octave_idx_type, double); +template OCTAVE_API Array +rand::do_vector (octave_idx_type, float); + +NDArray rand::do_nd_array (const dim_vector& dims, double a) +{ + NDArray retval; + + if (! dims.all_zero ()) + { + retval.clear (dims); - void rand::fill (octave_idx_type len, float *v, float a) - { - if (len < 1) - return; + fill (retval.numel (), retval.fortran_vec (), a); + } + + return retval; +} + +FloatNDArray rand::do_float_nd_array (const dim_vector& dims, float a) +{ + FloatNDArray retval; + + if (! dims.all_zero ()) + { + retval.clear (dims); + + fill (retval.numel (), retval.fortran_vec (), a); + } + + return retval; +} + +// Make the random number generator give us a different sequence every +// time we start octave unless we specifically set the seed. The +// technique used below will cycle monthly, but it does seem to +// work ok to give fairly different seeds each time Octave starts. + +void rand::initialize_ranlib_generators (void) +{ + sys::localtime tm; + int stored_distribution = m_current_distribution; + F77_FUNC (setcgn, SETCGN) (uniform_dist); + + int hour = tm.hour () + 1; + int minute = tm.min () + 1; + int second = tm.sec () + 1; + + int32_t s0 = tm.mday () * hour * minute * second; + int32_t s1 = hour * minute * second; - switch (m_current_distribution) - { - case uniform_dist: - if (m_use_old_generators) - std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; }); - else - rand_uniform (len, v); - break; + s0 = force_to_fit_range (s0, 1, 2147483563); + s1 = force_to_fit_range (s1, 1, 2147483399); + + F77_FUNC (setall, SETALL) (s0, s1); + F77_FUNC (setcgn, SETCGN) (stored_distribution); +} + +void rand::initialize_mersenne_twister (void) +{ + uint32NDArray s; + + init_mersenne_twister (); + s = get_internal_state (); + m_rand_states[uniform_dist] = s; + + init_mersenne_twister (); + s = get_internal_state (); + m_rand_states[normal_dist] = s; + + init_mersenne_twister (); + s = get_internal_state (); + m_rand_states[expon_dist] = s; + + init_mersenne_twister (); + s = get_internal_state (); + m_rand_states[poisson_dist] = s; + + init_mersenne_twister (); + s = get_internal_state (); + m_rand_states[gamma_dist] = s; + + // All of the initializations above have messed with the internal state. + // Restore the state of the currently selected distribution. + set_internal_state (m_rand_states[m_current_distribution]); +} - case normal_dist: - if (m_use_old_generators) - std::generate_n (v, len, [](void) { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; }); - else - rand_normal (len, v); - break; +uint32NDArray rand::get_internal_state (void) +{ + uint32NDArray s (dim_vector (MT_N + 1, 1)); + + get_mersenne_twister_state (reinterpret_cast (s.fortran_vec ())); + + return s; +} + +void rand::save_state (void) +{ + m_rand_states[m_current_distribution] = get_internal_state ();; +} + +int rand::get_dist_id (const std::string& d) +{ + int retval = unknown_dist; - case expon_dist: - if (m_use_old_generators) - std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; }); - else - rand_exponential (len, v); - break; + if (d == "uniform" || d == "rand") + retval = uniform_dist; + else if (d == "normal" || d == "randn") + retval = normal_dist; + else if (d == "exponential" || d == "rande") + retval = expon_dist; + else if (d == "poisson" || d == "randp") + retval = poisson_dist; + else if (d == "gamma" || d == "randg") + retval = gamma_dist; + else + (*current_liboctave_error_handler) + ("rand: invalid distribution '%s'", d.c_str ()); + + return retval; +} + +void rand::set_internal_state (const uint32NDArray& s) +{ + octave_idx_type len = s.numel (); + + const uint32_t *sdata = reinterpret_cast (s.data ()); - case poisson_dist: - if (m_use_old_generators) - { - if (a < 0.0f || ! math::isfinite (a)) - std::fill_n (v, len, numeric_limits::NaN ()); - else - { - // workaround bug in ignpoi, by calling with different Mu - float tmp; - F77_FUNC (fignpoi, FIGNPOI) (a + 1, tmp); - std::generate_n (v, len, [a](void) { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; }); - } - } - else - rand_poisson (a, len, v); - break; + if (len == MT_N + 1 && sdata[MT_N] <= MT_N && sdata[MT_N] > 0) + set_mersenne_twister_state (sdata); + else + init_mersenne_twister (sdata, len); +} + +void rand::switch_to_generator (int dist) +{ + if (dist != m_current_distribution) + { + m_current_distribution = dist; + + set_internal_state (m_rand_states[dist]); + } +} + +void rand::fill (octave_idx_type len, double *v, double a) +{ + if (len < 1) + return; + + switch (m_current_distribution) + { + case uniform_dist: + if (m_use_old_generators) + std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenunf, DGENUNF) (0.0, 1.0, x); return x; }); + else + rand_uniform (len, v); + break; + + case normal_dist: + if (m_use_old_generators) + std::generate_n (v, len, [](void) { double x; F77_FUNC (dgennor, DGENNOR) (0.0, 1.0, x); return x; }); + else + rand_normal (len, v); + break; + + case expon_dist: + if (m_use_old_generators) + std::generate_n (v, len, [](void) { double x; F77_FUNC (dgenexp, DGENEXP) (1.0, x); return x; }); + else + rand_exponential (len, v); + break; + + case poisson_dist: + if (m_use_old_generators) + { + if (a < 0.0 || ! math::isfinite (a)) + std::fill_n (v, len, numeric_limits::NaN ()); + else + { + // workaround bug in ignpoi, by calling with different Mu + double tmp; + F77_FUNC (dignpoi, DIGNPOI) (a + 1, tmp); + std::generate_n (v, len, [a](void) { double x; F77_FUNC (dignpoi, DIGNPOI) (a, x); return x; }); + } + } + else + rand_poisson (a, len, v); + break; + + case gamma_dist: + if (m_use_old_generators) + { + if (a <= 0.0 || ! math::isfinite (a)) + std::fill_n (v, len, numeric_limits::NaN ()); + else + std::generate_n (v, len, [a](void) { double x; F77_FUNC (dgengam, DGENGAM) (1.0, a, x); return x; }); + } + else + rand_gamma (a, len, v); + break; - case gamma_dist: - if (m_use_old_generators) - { - if (a <= 0.0f || ! math::isfinite (a)) - std::fill_n (v, len, numeric_limits::NaN ()); - else - std::generate_n (v, len, [a](void) { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; }); - } - else - rand_gamma (a, len, v); - break; + default: + (*current_liboctave_error_handler) + ("rand: invalid distribution ID = %d", m_current_distribution); + break; + } + + save_state (); + + return; +} + +void rand::fill (octave_idx_type len, float *v, float a) +{ + if (len < 1) + return; + + switch (m_current_distribution) + { + case uniform_dist: + if (m_use_old_generators) + std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenunf, FGENUNF) (0.0f, 1.0f, x); return x; }); + else + rand_uniform (len, v); + break; + + case normal_dist: + if (m_use_old_generators) + std::generate_n (v, len, [](void) { float x; F77_FUNC (fgennor, FGENNOR) (0.0f, 1.0f, x); return x; }); + else + rand_normal (len, v); + break; + + case expon_dist: + if (m_use_old_generators) + std::generate_n (v, len, [](void) { float x; F77_FUNC (fgenexp, FGENEXP) (1.0f, x); return x; }); + else + rand_exponential (len, v); + break; - default: - (*current_liboctave_error_handler) - ("rand: invalid distribution ID = %d", m_current_distribution); - break; - } + case poisson_dist: + if (m_use_old_generators) + { + if (a < 0.0f || ! math::isfinite (a)) + std::fill_n (v, len, numeric_limits::NaN ()); + else + { + // workaround bug in ignpoi, by calling with different Mu + float tmp; + F77_FUNC (fignpoi, FIGNPOI) (a + 1, tmp); + std::generate_n (v, len, [a](void) { float x; F77_FUNC (fignpoi, FIGNPOI) (a, x); return x; }); + } + } + else + rand_poisson (a, len, v); + break; - save_state (); + case gamma_dist: + if (m_use_old_generators) + { + if (a <= 0.0f || ! math::isfinite (a)) + std::fill_n (v, len, numeric_limits::NaN ()); + else + std::generate_n (v, len, [a](void) { float x; F77_FUNC (fgengam, FGENGAM) (1.0f, a, x); return x; }); + } + else + rand_gamma (a, len, v); + break; - return; - } + default: + (*current_liboctave_error_handler) + ("rand: invalid distribution ID = %d", m_current_distribution); + break; + } + + save_state (); + + return; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-rand.h --- a/liboctave/numeric/oct-rand.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-rand.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,256 +41,256 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class OCTAVE_API rand - { - protected: +class OCTAVE_API rand +{ +protected: - OCTAVE_API rand (void); + OCTAVE_API rand (void); - public: +public: - ~rand (void) = default; + ~rand (void) = default; - static bool instance_ok (void); + static bool instance_ok (void); - // Return the current seed. - static double seed (void) - { - return (instance_ok () - ? m_instance->do_seed () : numeric_limits::NaN ()); - } + // Return the current seed. + static double seed (void) + { + return (instance_ok () + ? m_instance->do_seed () : numeric_limits::NaN ()); + } - // Set the seed. - static void seed (double s) - { - if (instance_ok ()) - m_instance->do_seed (s); - } + // Set the seed. + static void seed (double s) + { + if (instance_ok ()) + m_instance->do_seed (s); + } - // Reset the seed. - static void reset (void) - { - if (instance_ok ()) - m_instance->do_reset (); - } + // Reset the seed. + static void reset (void) + { + if (instance_ok ()) + m_instance->do_reset (); + } - // Return the current state. - static uint32NDArray state (const std::string& d = "") - { - return instance_ok () ? m_instance->do_state (d) : uint32NDArray (); - } + // Return the current state. + static uint32NDArray state (const std::string& d = "") + { + return instance_ok () ? m_instance->do_state (d) : uint32NDArray (); + } - // Set the current state/ - static void state (const uint32NDArray& s, - const std::string& d = "") - { - if (instance_ok ()) - m_instance->do_state (s, d); - } + // Set the current state/ + static void state (const uint32NDArray& s, + const std::string& d = "") + { + if (instance_ok ()) + m_instance->do_state (s, d); + } - // Reset the current state/ - static void reset (const std::string& d) - { - if (instance_ok ()) - m_instance->do_reset (d); - } + // Reset the current state/ + static void reset (const std::string& d) + { + if (instance_ok ()) + m_instance->do_reset (d); + } - // Return the current distribution. - static std::string distribution (void) - { - return instance_ok () ? m_instance->do_distribution () : ""; - } + // Return the current distribution. + static std::string distribution (void) + { + return instance_ok () ? m_instance->do_distribution () : ""; + } - // Set the current distribution. May be either "uniform" (the - // default), "normal", "exponential", "poisson", or "gamma". - static void distribution (const std::string& d) - { - if (instance_ok ()) - m_instance->do_distribution (d); - } + // Set the current distribution. May be either "uniform" (the + // default), "normal", "exponential", "poisson", or "gamma". + static void distribution (const std::string& d) + { + if (instance_ok ()) + m_instance->do_distribution (d); + } - static void uniform_distribution (void) - { - if (instance_ok ()) - m_instance->do_uniform_distribution (); - } + static void uniform_distribution (void) + { + if (instance_ok ()) + m_instance->do_uniform_distribution (); + } - static void normal_distribution (void) - { - if (instance_ok ()) - m_instance->do_normal_distribution (); - } + static void normal_distribution (void) + { + if (instance_ok ()) + m_instance->do_normal_distribution (); + } - static void exponential_distribution (void) - { - if (instance_ok ()) - m_instance->do_exponential_distribution (); - } + static void exponential_distribution (void) + { + if (instance_ok ()) + m_instance->do_exponential_distribution (); + } - static void poisson_distribution (void) - { - if (instance_ok ()) - m_instance->do_poisson_distribution (); - } + static void poisson_distribution (void) + { + if (instance_ok ()) + m_instance->do_poisson_distribution (); + } - static void gamma_distribution (void) - { - if (instance_ok ()) - m_instance->do_gamma_distribution (); - } + static void gamma_distribution (void) + { + if (instance_ok ()) + m_instance->do_gamma_distribution (); + } - // Return the next number from the sequence. - static double scalar (double a = 1.0) - { - return (instance_ok () - ? m_instance->do_scalar (a) : numeric_limits::NaN ()); - } + // Return the next number from the sequence. + static double scalar (double a = 1.0) + { + return (instance_ok () + ? m_instance->do_scalar (a) : numeric_limits::NaN ()); + } - // Return the next number from the sequence. - static float float_scalar (float a = 1.0) - { - return (instance_ok () - ? m_instance->do_scalar (a) : numeric_limits::NaN ()); - } + // Return the next number from the sequence. + static float float_scalar (float a = 1.0) + { + return (instance_ok () + ? m_instance->do_scalar (a) : numeric_limits::NaN ()); + } - // Return an array of numbers from the sequence. - static Array vector (octave_idx_type n, double a = 1.0) - { - return instance_ok () ? m_instance->do_vector (n, a) : Array (); - } + // Return an array of numbers from the sequence. + static Array vector (octave_idx_type n, double a = 1.0) + { + return instance_ok () ? m_instance->do_vector (n, a) : Array (); + } - // Return an array of numbers from the sequence. - static Array float_vector (octave_idx_type n, float a = 1.0) - { - return instance_ok () ? m_instance->do_vector (n, a) : Array (); - } + // Return an array of numbers from the sequence. + static Array float_vector (octave_idx_type n, float a = 1.0) + { + return instance_ok () ? m_instance->do_vector (n, a) : Array (); + } - // Return an N-dimensional array of numbers from the sequence, - // filled in column major order. - static NDArray nd_array (const dim_vector& dims, double a = 1.0) - { - return instance_ok () ? m_instance->do_nd_array (dims, a) : NDArray (); - } + // Return an N-dimensional array of numbers from the sequence, + // filled in column major order. + static NDArray nd_array (const dim_vector& dims, double a = 1.0) + { + return instance_ok () ? m_instance->do_nd_array (dims, a) : NDArray (); + } - // Return an N-dimensional array of numbers from the sequence, - // filled in column major order. - static FloatNDArray float_nd_array (const dim_vector& dims, float a = 1.0) - { - return (instance_ok () - ? m_instance->do_float_nd_array (dims, a) : FloatNDArray ()); - } + // Return an N-dimensional array of numbers from the sequence, + // filled in column major order. + static FloatNDArray float_nd_array (const dim_vector& dims, float a = 1.0) + { + return (instance_ok () + ? m_instance->do_float_nd_array (dims, a) : FloatNDArray ()); + } - private: +private: - static rand *m_instance; + static rand *m_instance; - static void cleanup_instance (void) - { delete m_instance; m_instance = nullptr; } + static void cleanup_instance (void) + { delete m_instance; m_instance = nullptr; } - enum - { - unknown_dist, - uniform_dist, - normal_dist, - expon_dist, - poisson_dist, - gamma_dist - }; + enum + { + unknown_dist, + uniform_dist, + normal_dist, + expon_dist, + poisson_dist, + gamma_dist + }; - // Current distribution of random numbers. - int m_current_distribution; + // Current distribution of random numbers. + int m_current_distribution; - // If TRUE, use old RANLIB generators. Otherwise, use Mersenne - // Twister generator. - bool m_use_old_generators; + // If TRUE, use old RANLIB generators. Otherwise, use Mersenne + // Twister generator. + bool m_use_old_generators; - // Saved MT states. - std::map m_rand_states; + // Saved MT states. + std::map m_rand_states; - // Return the current seed. - OCTAVE_API double do_seed (void); + // Return the current seed. + OCTAVE_API double do_seed (void); - // Set the seed. - OCTAVE_API void do_seed (double s); + // Set the seed. + OCTAVE_API void do_seed (double s); - // Reset the seed. - OCTAVE_API void do_reset (); + // Reset the seed. + OCTAVE_API void do_reset (); - // Return the current state. - OCTAVE_API uint32NDArray do_state (const std::string& d); + // Return the current state. + OCTAVE_API uint32NDArray do_state (const std::string& d); - // Set the current state/ - OCTAVE_API void do_state (const uint32NDArray& s, const std::string& d); + // Set the current state/ + OCTAVE_API void do_state (const uint32NDArray& s, const std::string& d); - // Reset the current state/ - OCTAVE_API void do_reset (const std::string& d); + // Reset the current state/ + OCTAVE_API void do_reset (const std::string& d); - // Return the current distribution. - OCTAVE_API std::string do_distribution (void); + // Return the current distribution. + OCTAVE_API std::string do_distribution (void); - // Set the current distribution. May be either "uniform" (the - // default), "normal", "exponential", "poisson", or "gamma". - OCTAVE_API void do_distribution (const std::string& d); + // Set the current distribution. May be either "uniform" (the + // default), "normal", "exponential", "poisson", or "gamma". + OCTAVE_API void do_distribution (const std::string& d); - OCTAVE_API void do_uniform_distribution (void); + OCTAVE_API void do_uniform_distribution (void); - OCTAVE_API void do_normal_distribution (void); + OCTAVE_API void do_normal_distribution (void); - OCTAVE_API void do_exponential_distribution (void); + OCTAVE_API void do_exponential_distribution (void); - OCTAVE_API void do_poisson_distribution (void); + OCTAVE_API void do_poisson_distribution (void); - OCTAVE_API void do_gamma_distribution (void); + OCTAVE_API void do_gamma_distribution (void); - // The following templates only make sense for double and float - // types. + // The following templates only make sense for double and float + // types. - template OCTAVE_API T uniform (void); + template OCTAVE_API T uniform (void); - template OCTAVE_API T normal (void); + template OCTAVE_API T normal (void); - template OCTAVE_API T exponential (void); + template OCTAVE_API T exponential (void); - template OCTAVE_API T poisson (T a); + template OCTAVE_API T poisson (T a); - template OCTAVE_API T gamma (T a); + template OCTAVE_API T gamma (T a); - // Return the next number from the sequence. - template OCTAVE_API T do_scalar (T a = 1); + // Return the next number from the sequence. + template OCTAVE_API T do_scalar (T a = 1); - // Return an array of numbers from the sequence. - template OCTAVE_API Array - do_vector (octave_idx_type n, T a = 1); + // Return an array of numbers from the sequence. + template OCTAVE_API Array + do_vector (octave_idx_type n, T a = 1); - // Return an N-dimensional array of numbers from the sequence, - // filled in column major order. - OCTAVE_API NDArray do_nd_array (const dim_vector& dims, double a = 1.); + // Return an N-dimensional array of numbers from the sequence, + // filled in column major order. + OCTAVE_API NDArray do_nd_array (const dim_vector& dims, double a = 1.); - // Return an N-dimensional array of numbers from the sequence, - // filled in column major order. - OCTAVE_API FloatNDArray - do_float_nd_array (const dim_vector& dims, float a = 1.); + // Return an N-dimensional array of numbers from the sequence, + // filled in column major order. + OCTAVE_API FloatNDArray + do_float_nd_array (const dim_vector& dims, float a = 1.); - // Some helper functions. + // Some helper functions. - OCTAVE_API void initialize_ranlib_generators (void); + OCTAVE_API void initialize_ranlib_generators (void); - OCTAVE_API void initialize_mersenne_twister (void); + OCTAVE_API void initialize_mersenne_twister (void); - OCTAVE_API uint32NDArray get_internal_state (void); + OCTAVE_API uint32NDArray get_internal_state (void); - OCTAVE_API void save_state (void); + OCTAVE_API void save_state (void); - OCTAVE_API int get_dist_id (const std::string& d); + OCTAVE_API int get_dist_id (const std::string& d); - OCTAVE_API void set_internal_state (const uint32NDArray& s); + OCTAVE_API void set_internal_state (const uint32NDArray& s); - OCTAVE_API void switch_to_generator (int dist); + OCTAVE_API void switch_to_generator (int dist); - OCTAVE_API void fill (octave_idx_type len, double *v, double a); + OCTAVE_API void fill (octave_idx_type len, double *v, double a); - OCTAVE_API void fill (octave_idx_type len, float *v, float a); - }; + OCTAVE_API void fill (octave_idx_type len, float *v, float a); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-spparms.cc --- a/liboctave/numeric/oct-spparms.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-spparms.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,170 +37,170 @@ OCTAVE_BEGIN_NAMESPACE(octave) - sparse_params *sparse_params::s_instance = nullptr; +sparse_params *sparse_params::s_instance = nullptr; - bool sparse_params::instance_ok (void) - { - bool retval = true; +bool sparse_params::instance_ok (void) +{ + bool retval = true; - if (! s_instance) - { - s_instance = new sparse_params (); - singleton_cleanup_list::add (cleanup_instance); - } + if (! s_instance) + { + s_instance = new sparse_params (); + singleton_cleanup_list::add (cleanup_instance); + } - return retval; - } + return retval; +} - void sparse_params::defaults (void) - { - if (instance_ok ()) - s_instance->do_defaults (); - } +void sparse_params::defaults (void) +{ + if (instance_ok ()) + s_instance->do_defaults (); +} - void sparse_params::tight (void) - { - if (instance_ok ()) - s_instance->do_tight (); - } +void sparse_params::tight (void) +{ + if (instance_ok ()) + s_instance->do_tight (); +} - string_vector sparse_params::get_keys (void) - { - return instance_ok () ? s_instance->do_get_keys () : string_vector (); - } +string_vector sparse_params::get_keys (void) +{ + return instance_ok () ? s_instance->do_get_keys () : string_vector (); +} - ColumnVector sparse_params::get_vals (void) - { - return instance_ok () ? s_instance->do_get_vals () : ColumnVector (); - } +ColumnVector sparse_params::get_vals (void) +{ + return instance_ok () ? s_instance->do_get_vals () : ColumnVector (); +} - bool sparse_params::set_vals (const Array& vals) - { - return instance_ok () ? s_instance->do_set_vals (vals) : false; - } +bool sparse_params::set_vals (const Array& vals) +{ + return instance_ok () ? s_instance->do_set_vals (vals) : false; +} - bool sparse_params::set_key (const std::string& key, const double& val) - { - return instance_ok () ? s_instance->do_set_key (key, val) : false; - } +bool sparse_params::set_key (const std::string& key, const double& val) +{ + return instance_ok () ? s_instance->do_set_key (key, val) : false; +} - double sparse_params::get_key (const std::string& key) - { - return (instance_ok () - ? s_instance->do_get_key (key) : numeric_limits::NaN ()); - } +double sparse_params::get_key (const std::string& key) +{ + return (instance_ok () + ? s_instance->do_get_key (key) : numeric_limits::NaN ()); +} - double sparse_params::get_bandden (void) - { - return instance_ok () ? s_instance->do_get_bandden () : 0.0; - } +double sparse_params::get_bandden (void) +{ + return instance_ok () ? s_instance->do_get_bandden () : 0.0; +} - void sparse_params::print_info (std::ostream& os, const std::string& prefix) - { - if (instance_ok ()) - s_instance->do_print_info (os, prefix); - } +void sparse_params::print_info (std::ostream& os, const std::string& prefix) +{ + if (instance_ok ()) + s_instance->do_print_info (os, prefix); +} - void sparse_params::do_defaults (void) - { - m_params(0) = 0; // spumoni - m_params(1) = 1; // ths_rel - m_params(2) = 1; // ths_abs - m_params(3) = 0; // exact_d - m_params(4) = 3; // supernd - m_params(5) = 3; // rreduce - m_params(6) = 0.5; // wh_frac - m_params(7) = 1; // autommd - m_params(8) = 1; // autoamd - m_params(9) = 0.1; // piv_tol - m_params(10) = 0.5; // bandden - m_params(11) = 1; // umfpack - m_params(12) = 0.001; // sym_tol - } +void sparse_params::do_defaults (void) +{ + m_params(0) = 0; // spumoni + m_params(1) = 1; // ths_rel + m_params(2) = 1; // ths_abs + m_params(3) = 0; // exact_d + m_params(4) = 3; // supernd + m_params(5) = 3; // rreduce + m_params(6) = 0.5; // wh_frac + m_params(7) = 1; // autommd + m_params(8) = 1; // autoamd + m_params(9) = 0.1; // piv_tol + m_params(10) = 0.5; // bandden + m_params(11) = 1; // umfpack + m_params(12) = 0.001; // sym_tol +} - void sparse_params::do_tight (void) - { - m_params(0) = 0; // spumoni - m_params(1) = 1; // ths_rel - m_params(2) = 0; // ths_abs - m_params(3) = 1; // exact_d - m_params(4) = 1; // supernd - m_params(5) = 1; // rreduce - m_params(6) = 0.5; // wh_frac - m_params(7) = 1; // autommd - m_params(8) = 1; // autoamd - m_params(9) = 0.1; // piv_tol - m_params(10) = 0.5; // bandden - m_params(11) = 1; // umfpack - m_params(12) = 0.001; // sym_tol - } +void sparse_params::do_tight (void) +{ + m_params(0) = 0; // spumoni + m_params(1) = 1; // ths_rel + m_params(2) = 0; // ths_abs + m_params(3) = 1; // exact_d + m_params(4) = 1; // supernd + m_params(5) = 1; // rreduce + m_params(6) = 0.5; // wh_frac + m_params(7) = 1; // autommd + m_params(8) = 1; // autoamd + m_params(9) = 0.1; // piv_tol + m_params(10) = 0.5; // bandden + m_params(11) = 1; // umfpack + m_params(12) = 0.001; // sym_tol +} - void sparse_params::init_keys (void) - { - m_keys(0) = "spumoni"; - m_keys(1) = "ths_rel"; - m_keys(2) = "ths_abs"; - m_keys(3) = "exact_d"; - m_keys(4) = "supernd"; - m_keys(5) = "rreduce"; - m_keys(6) = "wh_frac"; - m_keys(7) = "autommd"; - m_keys(8) = "autoamd"; - m_keys(9) = "piv_tol"; - m_keys(10) = "bandden"; - m_keys(11) = "umfpack"; - m_keys(12) = "sym_tol"; - } +void sparse_params::init_keys (void) +{ + m_keys(0) = "spumoni"; + m_keys(1) = "ths_rel"; + m_keys(2) = "ths_abs"; + m_keys(3) = "exact_d"; + m_keys(4) = "supernd"; + m_keys(5) = "rreduce"; + m_keys(6) = "wh_frac"; + m_keys(7) = "autommd"; + m_keys(8) = "autoamd"; + m_keys(9) = "piv_tol"; + m_keys(10) = "bandden"; + m_keys(11) = "umfpack"; + m_keys(12) = "sym_tol"; +} - double sparse_params::do_get_bandden (void) - { - return m_params(10); - } +double sparse_params::do_get_bandden (void) +{ + return m_params(10); +} - bool sparse_params::do_set_vals (const Array& vals) - { - octave_idx_type len = vals.numel (); +bool sparse_params::do_set_vals (const Array& vals) +{ + octave_idx_type len = vals.numel (); - if (len > OCTAVE_SPARSE_CONTROLS_SIZE) - (*current_liboctave_error_handler) - ("sparse_params::do_set_vals: too many values"); + if (len > OCTAVE_SPARSE_CONTROLS_SIZE) + (*current_liboctave_error_handler) + ("sparse_params::do_set_vals: too many values"); - for (int i = 0; i < len; i++) - m_params(i) = vals(i); + for (int i = 0; i < len; i++) + m_params(i) = vals(i); - return true; - } + return true; +} - bool sparse_params::do_set_key (const std::string& key, const double& val) - { - for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) - { - if (m_keys (i) == key) - { - m_params(i) = val; - return true; - } - } +bool sparse_params::do_set_key (const std::string& key, const double& val) +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + { + if (m_keys (i) == key) + { + m_params(i) = val; + return true; + } + } - return false; - } + return false; +} - double sparse_params::do_get_key (const std::string& key) - { - for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) - { - if (m_keys (i) == key) - return m_params(i); - } +double sparse_params::do_get_key (const std::string& key) +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + { + if (m_keys (i) == key) + return m_params(i); + } - return numeric_limits::NaN (); - } + return numeric_limits::NaN (); +} - void sparse_params::do_print_info (std::ostream& os, - const std::string& prefix) const - { - for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) - os << prefix << m_keys(i) << ": " << m_params(i) << "\n"; - } +void sparse_params::do_print_info (std::ostream& os, + const std::string& prefix) const +{ + for (int i = 0; i < OCTAVE_SPARSE_CONTROLS_SIZE; i++) + os << prefix << m_keys(i) << ": " << m_params(i) << "\n"; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/oct-spparms.h --- a/liboctave/numeric/oct-spparms.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/oct-spparms.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,80 +39,80 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class OCTAVE_API sparse_params - { - protected: +class OCTAVE_API sparse_params +{ +protected: - sparse_params (void) - : m_params (OCTAVE_SPARSE_CONTROLS_SIZE), - m_keys (OCTAVE_SPARSE_CONTROLS_SIZE) - { - init_keys (); - do_defaults (); - } + sparse_params (void) + : m_params (OCTAVE_SPARSE_CONTROLS_SIZE), + m_keys (OCTAVE_SPARSE_CONTROLS_SIZE) + { + init_keys (); + do_defaults (); + } - public: +public: - sparse_params (const sparse_params&) = default; + sparse_params (const sparse_params&) = default; - sparse_params& operator = (const sparse_params&) = default; + sparse_params& operator = (const sparse_params&) = default; - ~sparse_params (void) = default; + ~sparse_params (void) = default; - static bool instance_ok (void); + static bool instance_ok (void); - static void defaults (void); + static void defaults (void); - static void tight (void); + static void tight (void); - static string_vector get_keys (void); + static string_vector get_keys (void); - static ColumnVector get_vals (void); + static ColumnVector get_vals (void); - static bool set_vals (const Array& vals); + static bool set_vals (const Array& vals); - static bool set_key (const std::string& key, const double& val); + static bool set_key (const std::string& key, const double& val); - static double get_key (const std::string& key); + static double get_key (const std::string& key); - static double get_bandden (void); + static double get_bandden (void); - static void print_info (std::ostream& os, const std::string& prefix); + static void print_info (std::ostream& os, const std::string& prefix); - private: +private: - ColumnVector m_params; + ColumnVector m_params; - string_vector m_keys; + string_vector m_keys; - static sparse_params *s_instance; + static sparse_params *s_instance; - static void cleanup_instance (void) - { - delete s_instance; - s_instance = nullptr; - } + static void cleanup_instance (void) + { + delete s_instance; + s_instance = nullptr; + } - void do_defaults (void); + void do_defaults (void); - void do_tight (void); + void do_tight (void); - string_vector do_get_keys (void) const { return m_keys; } + string_vector do_get_keys (void) const { return m_keys; } - ColumnVector do_get_vals (void) const { return m_params; } + ColumnVector do_get_vals (void) const { return m_params; } - bool do_set_vals (const Array& vals); + bool do_set_vals (const Array& vals); - bool do_set_key (const std::string& key, const double& val); + bool do_set_key (const std::string& key, const double& val); - double do_get_key (const std::string& key); + double do_get_key (const std::string& key); - double do_get_bandden (void); + double do_get_bandden (void); - void do_print_info (std::ostream& os, const std::string& prefix) const; + void do_print_info (std::ostream& os, const std::string& prefix) const; - void init_keys (void); - }; + void init_keys (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/qr.cc --- a/liboctave/numeric/qr.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/qr.cc Thu Dec 01 20:05:44 2022 -0800 @@ -54,2054 +54,2054 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - qr::qr (const T& q_arg, const T& r_arg) - : m_q (q_arg), m_r (r_arg) - { - octave_idx_type q_nr = m_q.rows (); - octave_idx_type q_nc = m_q.cols (); +template +qr::qr (const T& q_arg, const T& r_arg) + : m_q (q_arg), m_r (r_arg) +{ + octave_idx_type q_nr = m_q.rows (); + octave_idx_type q_nc = m_q.cols (); + + octave_idx_type r_nr = m_r.rows (); + octave_idx_type r_nc = m_r.cols (); - octave_idx_type r_nr = m_r.rows (); - octave_idx_type r_nc = m_r.cols (); + if (! (q_nc == r_nr && (q_nr == q_nc || (q_nr > q_nc && r_nr == r_nc)))) + (*current_liboctave_error_handler) ("QR dimensions mismatch"); +} - if (! (q_nc == r_nr && (q_nr == q_nc || (q_nr > q_nc && r_nr == r_nc)))) - (*current_liboctave_error_handler) ("QR dimensions mismatch"); - } +template +typename qr::type +qr::get_type (void) const +{ + type retval; - template - typename qr::type - qr::get_type (void) const - { - type retval; + if (! m_q.isempty () && m_q.issquare ()) + retval = qr::std; + else if (m_q.rows () > m_q.cols () && m_r.issquare ()) + retval = qr::economy; + else + retval = qr::raw; + + return retval; +} - if (! m_q.isempty () && m_q.issquare ()) - retval = qr::std; - else if (m_q.rows () > m_q.cols () && m_r.issquare ()) - retval = qr::economy; - else - retval = qr::raw; +template +bool +qr::regular (void) const +{ + bool retval = true; - return retval; - } + octave_idx_type k = std::min (m_r.rows (), m_r.cols ()); - template - bool - qr::regular (void) const + for (octave_idx_type i = 0; i < k; i++) { - bool retval = true; - - octave_idx_type k = std::min (m_r.rows (), m_r.cols ()); - - for (octave_idx_type i = 0; i < k; i++) + if (m_r(i, i) == ELT_T ()) { - if (m_r(i, i) == ELT_T ()) - { - retval = false; - break; - } - } - - return retval; - } - -#if ! defined (HAVE_QRUPDATE) - - // Replacement update methods. - - void - warn_qrupdate_once (void) - { - static bool warned = false; - - if (! warned) - { - (*current_liboctave_warning_with_id_handler) - ("Octave:missing-dependency", - "In this version of Octave, QR & Cholesky updating routines " - "simply update the matrix and recalculate factorizations. " - "To use fast algorithms, link Octave with the qrupdate library. " - "See ."); - - warned = true; + retval = false; + break; } } - template - void - qr::update (const CV_T& u, const CV_T& v) - { - warn_qrupdate_once (); + return retval; +} - octave_idx_type m = m_q.rows (); - octave_idx_type n = m_r.cols (); +#if ! defined (HAVE_QRUPDATE) - if (u.numel () != m || v.numel () != n) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); +// Replacement update methods. - init (m_q*m_r + T (u) * T (v).hermitian (), get_type ()); - } +void +warn_qrupdate_once (void) +{ + static bool warned = false; - template - void - qr::update (const T& u, const T& v) + if (! warned) { - warn_qrupdate_once (); - - octave_idx_type m = m_q.rows (); - octave_idx_type n = m_r.cols (); + (*current_liboctave_warning_with_id_handler) + ("Octave:missing-dependency", + "In this version of Octave, QR & Cholesky updating routines " + "simply update the matrix and recalculate factorizations. " + "To use fast algorithms, link Octave with the qrupdate library. " + "See ."); - if (u.rows () != m || v.rows () != n || u.cols () != v.cols ()) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); - - init (m_q*m_r + u * v.hermitian (), get_type ()); + warned = true; } +} - template - static - T - insert_col (const T& a, octave_idx_type i, const CV_T& x) - { - T retval (a.rows (), a.cols () + 1); - retval.assign (idx_vector::colon, idx_vector (0, i), - a.index (idx_vector::colon, idx_vector (0, i))); - retval.assign (idx_vector::colon, idx_vector (i), x); - retval.assign (idx_vector::colon, idx_vector (i+1, retval.cols ()), - a.index (idx_vector::colon, idx_vector (i, a.cols ()))); - return retval; - } +template +void +qr::update (const CV_T& u, const CV_T& v) +{ + warn_qrupdate_once (); + + octave_idx_type m = m_q.rows (); + octave_idx_type n = m_r.cols (); + + if (u.numel () != m || v.numel () != n) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + init (m_q*m_r + T (u) * T (v).hermitian (), get_type ()); +} - template - static - T - insert_row (const T& a, octave_idx_type i, const RV_T& x) - { - T retval (a.rows () + 1, a.cols ()); - retval.assign (idx_vector (0, i), idx_vector::colon, - a.index (idx_vector (0, i), idx_vector::colon)); - retval.assign (idx_vector (i), idx_vector::colon, x); - retval.assign (idx_vector (i+1, retval.rows ()), idx_vector::colon, - a.index (idx_vector (i, a.rows ()), idx_vector::colon)); - return retval; - } +template +void +qr::update (const T& u, const T& v) +{ + warn_qrupdate_once (); + + octave_idx_type m = m_q.rows (); + octave_idx_type n = m_r.cols (); + + if (u.rows () != m || v.rows () != n || u.cols () != v.cols ()) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + init (m_q*m_r + u * v.hermitian (), get_type ()); +} - template - static - T - delete_col (const T& a, octave_idx_type i) - { - T retval = a; - retval.delete_elements (1, idx_vector (i)); - return retval; - } +template +static +T +insert_col (const T& a, octave_idx_type i, const CV_T& x) +{ + T retval (a.rows (), a.cols () + 1); + retval.assign (idx_vector::colon, idx_vector (0, i), + a.index (idx_vector::colon, idx_vector (0, i))); + retval.assign (idx_vector::colon, idx_vector (i), x); + retval.assign (idx_vector::colon, idx_vector (i+1, retval.cols ()), + a.index (idx_vector::colon, idx_vector (i, a.cols ()))); + return retval; +} + +template +static +T +insert_row (const T& a, octave_idx_type i, const RV_T& x) +{ + T retval (a.rows () + 1, a.cols ()); + retval.assign (idx_vector (0, i), idx_vector::colon, + a.index (idx_vector (0, i), idx_vector::colon)); + retval.assign (idx_vector (i), idx_vector::colon, x); + retval.assign (idx_vector (i+1, retval.rows ()), idx_vector::colon, + a.index (idx_vector (i, a.rows ()), idx_vector::colon)); + return retval; +} - template - static - T - delete_row (const T& a, octave_idx_type i) - { - T retval = a; - retval.delete_elements (0, idx_vector (i)); - return retval; - } +template +static +T +delete_col (const T& a, octave_idx_type i) +{ + T retval = a; + retval.delete_elements (1, idx_vector (i)); + return retval; +} - template - static - T - shift_cols (const T& a, octave_idx_type i, octave_idx_type j) +template +static +T +delete_row (const T& a, octave_idx_type i) +{ + T retval = a; + retval.delete_elements (0, idx_vector (i)); + return retval; +} + +template +static +T +shift_cols (const T& a, octave_idx_type i, octave_idx_type j) +{ + octave_idx_type n = a.cols (); + Array p (dim_vector (n, 1)); + for (octave_idx_type k = 0; k < n; k++) p(k) = k; + if (i < j) { - octave_idx_type n = a.cols (); - Array p (dim_vector (n, 1)); - for (octave_idx_type k = 0; k < n; k++) p(k) = k; - if (i < j) - { - for (octave_idx_type k = i; k < j; k++) p(k) = k+1; - p(j) = i; - } - else if (j < i) - { - p(j) = i; - for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1; - } - - return a.index (idx_vector::colon, idx_vector (p)); + for (octave_idx_type k = i; k < j; k++) p(k) = k+1; + p(j) = i; } - - template - void - qr::insert_col (const CV_T& u, octave_idx_type j) + else if (j < i) { - warn_qrupdate_once (); - - octave_idx_type m = m_q.rows (); - octave_idx_type n = m_r.cols (); - - if (u.numel () != m) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - init (math::insert_col (m_q*m_r, j, u), get_type ()); + p(j) = i; + for (octave_idx_type k = j+1; k < i+1; k++) p(k) = k-1; } - template - void - qr::insert_col (const T& u, const Array& j) - { - warn_qrupdate_once (); + return a.index (idx_vector::colon, idx_vector (p)); +} - octave_idx_type m = m_q.rows (); - octave_idx_type n = m_r.cols (); +template +void +qr::insert_col (const CV_T& u, octave_idx_type j) +{ + warn_qrupdate_once (); + + octave_idx_type m = m_q.rows (); + octave_idx_type n = m_r.cols (); + + if (u.numel () != m) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - Array jsi; - Array js = j.sort (jsi, 0, ASCENDING); - octave_idx_type nj = js.numel (); - bool dups = false; - for (octave_idx_type i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + init (math::insert_col (m_q*m_r, j, u), get_type ()); +} - if (u.numel () != m || u.cols () != nj) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - if (nj > 0 && (js(0) < 0 || js(nj-1) > n)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); +template +void +qr::insert_col (const T& u, const Array& j) +{ + warn_qrupdate_once (); - if (nj > 0) - { - T a = m_q*m_r; - for (octave_idx_type i = 0; i < nj; i++) - a = math::insert_col (a, js(i), u.column (i)); + octave_idx_type m = m_q.rows (); + octave_idx_type n = m_r.cols (); - init (a, get_type ()); - } - } + Array jsi; + Array js = j.sort (jsi, 0, ASCENDING); + octave_idx_type nj = js.numel (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); - template - void - qr::delete_col (octave_idx_type j) - { - warn_qrupdate_once (); + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); - octave_idx_type n = m_r.cols (); + if (u.numel () != m || u.cols () != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + if (nj > 0 && (js(0) < 0 || js(nj-1) > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - init (math::delete_col (m_q*m_r, j), get_type ()); - } + if (nj > 0) + { + T a = m_q*m_r; + for (octave_idx_type i = 0; i < nj; i++) + a = math::insert_col (a, js(i), u.column (i)); - template - void - qr::delete_col (const Array& j) - { - warn_qrupdate_once (); + init (a, get_type ()); + } +} - octave_idx_type n = m_r.cols (); +template +void +qr::delete_col (octave_idx_type j) +{ + warn_qrupdate_once (); - Array jsi; - Array js = j.sort (jsi, 0, DESCENDING); - octave_idx_type nj = js.numel (); - bool dups = false; - for (octave_idx_type i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); + octave_idx_type n = m_r.cols (); + + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); + + init (math::delete_col (m_q*m_r, j), get_type ()); +} - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); +template +void +qr::delete_col (const Array& j) +{ + warn_qrupdate_once (); - if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + octave_idx_type n = m_r.cols (); - if (nj > 0) - { - T a = m_q*m_r; - for (octave_idx_type i = 0; i < nj; i++) - a = math::delete_col (a, js(i)); + Array jsi; + Array js = j.sort (jsi, 0, DESCENDING); + octave_idx_type nj = js.numel (); + bool dups = false; + for (octave_idx_type i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); - init (a, get_type ()); - } + if (nj > 0 && (js(0) > n-1 || js(nj-1) < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (nj > 0) + { + T a = m_q*m_r; + for (octave_idx_type i = 0; i < nj; i++) + a = math::delete_col (a, js(i)); + + init (a, get_type ()); } - - template - void - qr::insert_row (const RV_T& u, octave_idx_type j) - { - warn_qrupdate_once (); +} - octave_idx_type m = m_r.rows (); - octave_idx_type n = m_r.cols (); +template +void +qr::insert_row (const RV_T& u, octave_idx_type j) +{ + warn_qrupdate_once (); - if (! m_q.issquare () || u.numel () != n) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - if (j < 0 || j > m) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + octave_idx_type m = m_r.rows (); + octave_idx_type n = m_r.cols (); - init (math::insert_row (m_q*m_r, j, u), get_type ()); - } + if (! m_q.issquare () || u.numel () != n) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + + if (j < 0 || j > m) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + init (math::insert_row (m_q*m_r, j, u), get_type ()); +} - template - void - qr::delete_row (octave_idx_type j) - { - warn_qrupdate_once (); +template +void +qr::delete_row (octave_idx_type j) +{ + warn_qrupdate_once (); - octave_idx_type m = m_r.rows (); + octave_idx_type m = m_r.rows (); - if (! m_q.issquare ()) - (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - - if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + if (! m_q.issquare ()) + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - init (math::delete_row (m_q*m_r, j), get_type ()); - } + if (j < 0 || j > m-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); + + init (math::delete_row (m_q*m_r, j), get_type ()); +} - template - void - qr::shift_cols (octave_idx_type i, octave_idx_type j) - { - warn_qrupdate_once (); +template +void +qr::shift_cols (octave_idx_type i, octave_idx_type j) +{ + warn_qrupdate_once (); - octave_idx_type n = m_r.cols (); + octave_idx_type n = m_r.cols (); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrshift: index out of range"); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrshift: index out of range"); - init (math::shift_cols (m_q*m_r, i, j), get_type ()); - } + init (math::shift_cols (m_q*m_r, i, j), get_type ()); +} #endif - // Specializations. +// Specializations. - template <> - OCTAVE_API void - qr::form (octave_idx_type n_arg, Matrix& afact, double *tau, - type qr_type) +template <> +OCTAVE_API void +qr::form (octave_idx_type n_arg, Matrix& afact, double *tau, + type qr_type) +{ + F77_INT n = to_f77_int (n_arg); + F77_INT m = to_f77_int (afact.rows ()); + F77_INT min_mn = std::min (m, n); + F77_INT info; + + if (qr_type == qr::raw) { - F77_INT n = to_f77_int (n_arg); - F77_INT m = to_f77_int (afact.rows ()); - F77_INT min_mn = std::min (m, n); - F77_INT info; + for (F77_INT j = 0; j < min_mn; j++) + { + F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); + for (F77_INT i = limit + 1; i < m; i++) + afact.elem (i, j) *= tau[j]; + } - if (qr_type == qr::raw) + m_r = afact; + } + else + { + // Attempt to minimize copying. + if (m >= n) { - for (F77_INT j = 0; j < min_mn; j++) + // afact will become m_q. + m_q = afact; + F77_INT k = (qr_type == qr::economy ? n : m); + m_r = Matrix (k, n); + for (F77_INT j = 0; j < n; j++) { - F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); - for (F77_INT i = limit + 1; i < m; i++) - afact.elem (i, j) *= tau[j]; + F77_INT i = 0; + for (; i <= j; i++) + m_r.xelem (i, j) = afact.xelem (i, j); + for (; i < k; i++) + m_r.xelem (i, j) = 0; } - - m_r = afact; + afact = Matrix (); // optimize memory } else { - // Attempt to minimize copying. - if (m >= n) - { - // afact will become m_q. - m_q = afact; - F77_INT k = (qr_type == qr::economy ? n : m); - m_r = Matrix (k, n); - for (F77_INT j = 0; j < n; j++) - { - F77_INT i = 0; - for (; i <= j; i++) - m_r.xelem (i, j) = afact.xelem (i, j); - for (; i < k; i++) - m_r.xelem (i, j) = 0; - } - afact = Matrix (); // optimize memory - } - else - { - // afact will become m_r. - m_q = Matrix (m, m); - for (F77_INT j = 0; j < m; j++) - for (F77_INT i = j + 1; i < m; i++) - { - m_q.xelem (i, j) = afact.xelem (i, j); - afact.xelem (i, j) = 0; - } - m_r = afact; - } - - if (m > 0) - { - F77_INT k = to_f77_int (m_q.cols ()); - // workspace query. - double rlwork; - F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.fortran_vec (), m, - tau, &rlwork, -1, info)); - - // allocate buffer and do the job. - F77_INT lwork = static_cast (rlwork); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (double, work, lwork); - F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.fortran_vec (), m, - tau, work, lwork, info)); - } + // afact will become m_r. + m_q = Matrix (m, m); + for (F77_INT j = 0; j < m; j++) + for (F77_INT i = j + 1; i < m; i++) + { + m_q.xelem (i, j) = afact.xelem (i, j); + afact.xelem (i, j) = 0; + } + m_r = afact; } - } - - template <> - OCTAVE_API void - qr::init (const Matrix& a, type qr_type) - { - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (double, tau, min_mn); - - F77_INT info = 0; - - Matrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); if (m > 0) { + F77_INT k = to_f77_int (m_q.cols ()); // workspace query. double rlwork; - F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau, - &rlwork, -1, info)); + F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.fortran_vec (), m, + tau, &rlwork, -1, info)); // allocate buffer and do the job. F77_INT lwork = static_cast (rlwork); lwork = std::max (lwork, static_cast (1)); OCTAVE_LOCAL_BUFFER (double, work, lwork); - F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau, - work, lwork, info)); + F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.fortran_vec (), m, + tau, work, lwork, info)); } + } +} - form (n, afact, tau, qr_type); +template <> +OCTAVE_API void +qr::init (const Matrix& a, type qr_type) +{ + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); + + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (double, tau, min_mn); + + F77_INT info = 0; + + Matrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); + + if (m > 0) + { + // workspace query. + double rlwork; + F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau, + &rlwork, -1, info)); + + // allocate buffer and do the job. + F77_INT lwork = static_cast (rlwork); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (double, work, lwork); + F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau, + work, lwork, info)); } + form (n, afact, tau, qr_type); +} + #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - qr::update (const ColumnVector& u, const ColumnVector& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::update (const ColumnVector& u, const ColumnVector& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + ColumnVector utmp = u; + ColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (double, w, 2*k); + F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.fortran_vec (), m, + m_r.fortran_vec (), k, utmp.fortran_vec (), + vtmp.fortran_vec (), w)); +} - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); +template <> +OCTAVE_API void +qr::update (const Matrix& u, const Matrix& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_rows = to_f77_int (u.rows ()); + F77_INT u_cols = to_f77_int (u.cols ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT v_rows = to_f77_int (v.rows ()); + F77_INT v_cols = to_f77_int (v.cols ()); + + if (u_rows != m || v_rows != n || u_cols != v_cols) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); - ColumnVector utmp = u; - ColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (double, w, 2*k); + OCTAVE_LOCAL_BUFFER (double, w, 2*k); + for (volatile F77_INT i = 0; i < u_cols; i++) + { + ColumnVector utmp = u.column (i); + ColumnVector vtmp = v.column (i); F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.fortran_vec (), m, m_r.fortran_vec (), k, utmp.fortran_vec (), vtmp.fortran_vec (), w)); } +} - template <> - OCTAVE_API void - qr::update (const Matrix& u, const Matrix& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::insert_col (const ColumnVector& u, octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_rows = to_f77_int (u.rows ()); - F77_INT u_cols = to_f77_int (u.cols ()); + if (u_nel != m) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - F77_INT v_rows = to_f77_int (v.rows ()); - F77_INT v_cols = to_f77_int (v.cols ()); + if (k < m) + { + m_q.resize (m, k+1); + m_r.resize (k+1, n+1); + } + else + m_r.resize (k, n+1); - if (u_rows != m || v_rows != n || u_cols != v_cols) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - OCTAVE_LOCAL_BUFFER (double, w, 2*k); - for (volatile F77_INT i = 0; i < u_cols; i++) - { - ColumnVector utmp = u.column (i); - ColumnVector vtmp = v.column (i); - F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.fortran_vec (), m, - m_r.fortran_vec (), k, utmp.fortran_vec (), - vtmp.fortran_vec (), w)); - } - } + ColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, w, k); + F77_XFCN (dqrinc, DQRINC, (m, n, k, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, j + 1, + utmp.data (), w)); +} + +template <> +OCTAVE_API void +qr::insert_col (const Matrix& u, const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - template <> - OCTAVE_API void - qr::insert_col (const ColumnVector& u, octave_idx_type j_arg) + Array jsi; + Array js = j.sort (jsi, 0, ASCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT u_cols = to_f77_int (u.cols ()); + + if (u_nel != m || u_cols != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); + + if (nj > 0 && (js_beg < 0 || js_end > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (nj > 0) { - F77_INT j = to_f77_int (j_arg); - - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); - - F77_INT u_nel = to_f77_int (u.numel ()); - - if (u_nel != m) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - + F77_INT kmax = std::min (k + nj, m); if (k < m) { - m_q.resize (m, k+1); - m_r.resize (k+1, n+1); + m_q.resize (m, kmax); + m_r.resize (kmax, n + nj); } else - m_r.resize (k, n+1); + m_r.resize (k, n + nj); F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); - ColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, k); - F77_XFCN (dqrinc, DQRINC, (m, n, k, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, j + 1, - utmp.data (), w)); - } - - template <> - OCTAVE_API void - qr::insert_col (const Matrix& u, const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); - - Array jsi; - Array js = j.sort (jsi, 0, ASCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); - - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_cols = to_f77_int (u.cols ()); - - if (u_nel != m || u_cols != nj) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); - - if (nj > 0 && (js_beg < 0 || js_end > n)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - if (nj > 0) + OCTAVE_LOCAL_BUFFER (double, w, kmax); + for (volatile F77_INT i = 0; i < nj; i++) { - F77_INT kmax = std::min (k + nj, m); - if (k < m) - { - m_q.resize (m, kmax); - m_r.resize (kmax, n + nj); - } - else - m_r.resize (k, n + nj); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (double, w, kmax); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - ColumnVector utmp = u.column (jsi(i)); - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (dqrinc, DQRINC, (m, n + ii, std::min (kmax, k + ii), - m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, js_elt + 1, - utmp.data (), w)); - } + F77_INT ii = i; + ColumnVector utmp = u.column (jsi(i)); + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (dqrinc, DQRINC, (m, n + ii, std::min (kmax, k + ii), + m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, js_elt + 1, + utmp.data (), w)); } } +} - template <> - OCTAVE_API void - qr::delete_col (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +qr::delete_col (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); + + OCTAVE_LOCAL_BUFFER (double, w, k); + F77_XFCN (dqrdec, DQRDEC, (m, n, k, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, j + 1, w)); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + if (k < m) + { + m_q.resize (m, k-1); + m_r.resize (k-1, n-1); + } + else + m_r.resize (k, n-1); +} + +template <> +OCTAVE_API void +qr::delete_col (const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + Array jsi; + Array js = j.sort (jsi, 0, DESCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); + + if (nj > 0 && (js_beg > n-1 || js_end < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (nj > 0) + { F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); OCTAVE_LOCAL_BUFFER (double, w, k); - F77_XFCN (dqrdec, DQRDEC, (m, n, k, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, j + 1, w)); + for (volatile F77_INT i = 0; i < nj; i++) + { + F77_INT ii = i; + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (dqrdec, DQRDEC, (m, n - ii, (k == m ? k : k - ii), + m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, + js_elt + 1, w)); + } if (k < m) { - m_q.resize (m, k-1); - m_r.resize (k-1, n-1); + m_q.resize (m, k - nj); + m_r.resize (k - nj, n - nj); } else - m_r.resize (k, n-1); + m_r.resize (k, n - nj); } - - template <> - OCTAVE_API void - qr::delete_col (const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +} - Array jsi; - Array js = j.sort (jsi, 0, DESCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); +template <> +OCTAVE_API void +qr::insert_row (const RowVector& u, octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = std::min (m, n); - if (nj > 0 && (js_beg > n-1 || js_end < 0)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + F77_INT u_nel = to_f77_int (u.numel ()); - if (nj > 0) - { - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + if (! m_q.issquare () || u_nel != n) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - OCTAVE_LOCAL_BUFFER (double, w, k); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (dqrdec, DQRDEC, (m, n - ii, (k == m ? k : k - ii), - m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, - js_elt + 1, w)); - } + if (j < 0 || j > m) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + m_q.resize (m + 1, m + 1); + m_r.resize (m + 1, n); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (k < m) - { - m_q.resize (m, k - nj); - m_r.resize (k - nj, n - nj); - } - else - m_r.resize (k, n - nj); - } - } + RowVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, w, k); + F77_XFCN (dqrinr, DQRINR, (m, n, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, + j + 1, utmp.fortran_vec (), w)); - template <> - OCTAVE_API void - qr::insert_row (const RowVector& u, octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +} - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = std::min (m, n); - - F77_INT u_nel = to_f77_int (u.numel ()); +template <> +OCTAVE_API void +qr::delete_row (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - if (! m_q.issquare () || u_nel != n) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - if (j < 0 || j > m) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - m_q.resize (m + 1, m + 1); - m_r.resize (m + 1, n); + if (! m_q.issquare ()) + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + if (j < 0 || j > m-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); - RowVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, w, k); - F77_XFCN (dqrinr, DQRINR, (m, n, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, - j + 1, utmp.fortran_vec (), w)); - - } + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - template <> - OCTAVE_API void - qr::delete_row (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); + OCTAVE_LOCAL_BUFFER (double, w, 2*m); + F77_XFCN (dqrder, DQRDER, (m, n, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, j + 1, w)); - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - - if (! m_q.issquare ()) - (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - - if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + m_q.resize (m - 1, m - 1); + m_r.resize (m - 1, n); +} - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); +template <> +OCTAVE_API void +qr::shift_cols (octave_idx_type i_arg, octave_idx_type j_arg) +{ + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - OCTAVE_LOCAL_BUFFER (double, w, 2*m); - F77_XFCN (dqrder, DQRDER, (m, n, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, j + 1, w)); - - m_q.resize (m - 1, m - 1); - m_r.resize (m - 1, n); - } + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - template <> - OCTAVE_API void - qr::shift_cols (octave_idx_type i_arg, octave_idx_type j_arg) - { - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrshift: index out of range"); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrshift: index out of range"); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (double, w, 2*k); - F77_XFCN (dqrshc, DQRSHC, (m, n, k, - m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, - i + 1, j + 1, w)); - } + OCTAVE_LOCAL_BUFFER (double, w, 2*k); + F77_XFCN (dqrshc, DQRSHC, (m, n, k, + m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, + i + 1, j + 1, w)); +} #endif - template <> - OCTAVE_API void - qr::form (octave_idx_type n_arg, FloatMatrix& afact, - float *tau, type qr_type) +template <> +OCTAVE_API void +qr::form (octave_idx_type n_arg, FloatMatrix& afact, + float *tau, type qr_type) +{ + F77_INT n = to_f77_int (n_arg); + F77_INT m = to_f77_int (afact.rows ()); + F77_INT min_mn = std::min (m, n); + F77_INT info; + + if (qr_type == qr::raw) { - F77_INT n = to_f77_int (n_arg); - F77_INT m = to_f77_int (afact.rows ()); - F77_INT min_mn = std::min (m, n); - F77_INT info; + for (F77_INT j = 0; j < min_mn; j++) + { + F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); + for (F77_INT i = limit + 1; i < m; i++) + afact.elem (i, j) *= tau[j]; + } - if (qr_type == qr::raw) + m_r = afact; + } + else + { + // Attempt to minimize copying. + if (m >= n) { - for (F77_INT j = 0; j < min_mn; j++) + // afact will become m_q. + m_q = afact; + F77_INT k = (qr_type == qr::economy ? n : m); + m_r = FloatMatrix (k, n); + for (F77_INT j = 0; j < n; j++) { - F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); - for (F77_INT i = limit + 1; i < m; i++) - afact.elem (i, j) *= tau[j]; + F77_INT i = 0; + for (; i <= j; i++) + m_r.xelem (i, j) = afact.xelem (i, j); + for (; i < k; i++) + m_r.xelem (i, j) = 0; } - - m_r = afact; + afact = FloatMatrix (); // optimize memory } else { - // Attempt to minimize copying. - if (m >= n) - { - // afact will become m_q. - m_q = afact; - F77_INT k = (qr_type == qr::economy ? n : m); - m_r = FloatMatrix (k, n); - for (F77_INT j = 0; j < n; j++) - { - F77_INT i = 0; - for (; i <= j; i++) - m_r.xelem (i, j) = afact.xelem (i, j); - for (; i < k; i++) - m_r.xelem (i, j) = 0; - } - afact = FloatMatrix (); // optimize memory - } - else - { - // afact will become m_r. - m_q = FloatMatrix (m, m); - for (F77_INT j = 0; j < m; j++) - for (F77_INT i = j + 1; i < m; i++) - { - m_q.xelem (i, j) = afact.xelem (i, j); - afact.xelem (i, j) = 0; - } - m_r = afact; - } - - if (m > 0) - { - F77_INT k = to_f77_int (m_q.cols ()); - // workspace query. - float rlwork; - F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.fortran_vec (), m, - tau, &rlwork, -1, info)); - - // allocate buffer and do the job. - F77_INT lwork = static_cast (rlwork); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (float, work, lwork); - F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.fortran_vec (), m, - tau, work, lwork, info)); - } + // afact will become m_r. + m_q = FloatMatrix (m, m); + for (F77_INT j = 0; j < m; j++) + for (F77_INT i = j + 1; i < m; i++) + { + m_q.xelem (i, j) = afact.xelem (i, j); + afact.xelem (i, j) = 0; + } + m_r = afact; } - } - - template <> - OCTAVE_API void - qr::init (const FloatMatrix& a, type qr_type) - { - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (float, tau, min_mn); - - F77_INT info = 0; - - FloatMatrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); if (m > 0) { + F77_INT k = to_f77_int (m_q.cols ()); // workspace query. float rlwork; - F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau, - &rlwork, -1, info)); + F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.fortran_vec (), m, + tau, &rlwork, -1, info)); // allocate buffer and do the job. F77_INT lwork = static_cast (rlwork); lwork = std::max (lwork, static_cast (1)); OCTAVE_LOCAL_BUFFER (float, work, lwork); - F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau, - work, lwork, info)); + F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.fortran_vec (), m, + tau, work, lwork, info)); } + } +} - form (n, afact, tau, qr_type); +template <> +OCTAVE_API void +qr::init (const FloatMatrix& a, type qr_type) +{ + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); + + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (float, tau, min_mn); + + F77_INT info = 0; + + FloatMatrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); + + if (m > 0) + { + // workspace query. + float rlwork; + F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau, + &rlwork, -1, info)); + + // allocate buffer and do the job. + F77_INT lwork = static_cast (rlwork); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (float, work, lwork); + F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau, + work, lwork, info)); } + form (n, afact, tau, qr_type); +} + #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - qr::update (const FloatColumnVector& u, const FloatColumnVector& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::update (const FloatColumnVector& u, const FloatColumnVector& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + FloatColumnVector utmp = u; + FloatColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (float, w, 2*k); + F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.fortran_vec (), m, + m_r.fortran_vec (), k, utmp.fortran_vec (), + vtmp.fortran_vec (), w)); +} - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); +template <> +OCTAVE_API void +qr::update (const FloatMatrix& u, const FloatMatrix& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_rows = to_f77_int (u.rows ()); + F77_INT u_cols = to_f77_int (u.cols ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT v_rows = to_f77_int (v.rows ()); + F77_INT v_cols = to_f77_int (v.cols ()); + + if (u_rows != m || v_rows != n || u_cols != v_cols) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); - FloatColumnVector utmp = u; - FloatColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (float, w, 2*k); + OCTAVE_LOCAL_BUFFER (float, w, 2*k); + for (volatile F77_INT i = 0; i < u_cols; i++) + { + FloatColumnVector utmp = u.column (i); + FloatColumnVector vtmp = v.column (i); F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.fortran_vec (), m, m_r.fortran_vec (), k, utmp.fortran_vec (), vtmp.fortran_vec (), w)); } +} - template <> - OCTAVE_API void - qr::update (const FloatMatrix& u, const FloatMatrix& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::insert_col (const FloatColumnVector& u, + octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_rows = to_f77_int (u.rows ()); - F77_INT u_cols = to_f77_int (u.cols ()); + if (u_nel != m) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - F77_INT v_rows = to_f77_int (v.rows ()); - F77_INT v_cols = to_f77_int (v.cols ()); + if (k < m) + { + m_q.resize (m, k+1); + m_r.resize (k+1, n+1); + } + else + m_r.resize (k, n+1); - if (u_rows != m || v_rows != n || u_cols != v_cols) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - OCTAVE_LOCAL_BUFFER (float, w, 2*k); - for (volatile F77_INT i = 0; i < u_cols; i++) - { - FloatColumnVector utmp = u.column (i); - FloatColumnVector vtmp = v.column (i); - F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.fortran_vec (), m, - m_r.fortran_vec (), k, utmp.fortran_vec (), - vtmp.fortran_vec (), w)); - } - } + FloatColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, w, k); + F77_XFCN (sqrinc, SQRINC, (m, n, k, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, j + 1, + utmp.data (), w)); +} + +template <> +OCTAVE_API void +qr::insert_col (const FloatMatrix& u, + const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - template <> - OCTAVE_API void - qr::insert_col (const FloatColumnVector& u, - octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); + Array jsi; + Array js = j.sort (jsi, 0, ASCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT u_cols = to_f77_int (u.cols ()); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); + if (u_nel != m || u_cols != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); - if (u_nel != m) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + if (nj > 0 && (js_beg < 0 || js_end > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - + if (nj > 0) + { + F77_INT kmax = std::min (k + nj, m); if (k < m) { - m_q.resize (m, k+1); - m_r.resize (k+1, n+1); + m_q.resize (m, kmax); + m_r.resize (kmax, n + nj); } else - m_r.resize (k, n+1); + m_r.resize (k, n + nj); F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); - FloatColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, k); - F77_XFCN (sqrinc, SQRINC, (m, n, k, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, j + 1, - utmp.data (), w)); - } - - template <> - OCTAVE_API void - qr::insert_col (const FloatMatrix& u, - const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); - - Array jsi; - Array js = j.sort (jsi, 0, ASCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); - - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_cols = to_f77_int (u.cols ()); - - if (u_nel != m || u_cols != nj) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); - - if (nj > 0 && (js_beg < 0 || js_end > n)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - if (nj > 0) + OCTAVE_LOCAL_BUFFER (float, w, kmax); + for (volatile F77_INT i = 0; i < nj; i++) { - F77_INT kmax = std::min (k + nj, m); - if (k < m) - { - m_q.resize (m, kmax); - m_r.resize (kmax, n + nj); - } - else - m_r.resize (k, n + nj); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (float, w, kmax); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - FloatColumnVector utmp = u.column (jsi(i)); - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (sqrinc, SQRINC, (m, n + ii, std::min (kmax, k + ii), - m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, js_elt + 1, - utmp.data (), w)); - } + F77_INT ii = i; + FloatColumnVector utmp = u.column (jsi(i)); + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (sqrinc, SQRINC, (m, n + ii, std::min (kmax, k + ii), + m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, js_elt + 1, + utmp.data (), w)); } } +} - template <> - OCTAVE_API void - qr::delete_col (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +qr::delete_col (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); + + OCTAVE_LOCAL_BUFFER (float, w, k); + F77_XFCN (sqrdec, SQRDEC, (m, n, k, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, j + 1, w)); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + if (k < m) + { + m_q.resize (m, k-1); + m_r.resize (k-1, n-1); + } + else + m_r.resize (k, n-1); +} + +template <> +OCTAVE_API void +qr::delete_col (const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + Array jsi; + Array js = j.sort (jsi, 0, DESCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); + + if (nj > 0 && (js_beg > n-1 || js_end < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (nj > 0) + { F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); OCTAVE_LOCAL_BUFFER (float, w, k); - F77_XFCN (sqrdec, SQRDEC, (m, n, k, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, j + 1, w)); + for (volatile F77_INT i = 0; i < nj; i++) + { + F77_INT ii = i; + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (sqrdec, SQRDEC, (m, n - ii, (k == m ? k : k - ii), + m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, + js_elt + 1, w)); + } if (k < m) { - m_q.resize (m, k-1); - m_r.resize (k-1, n-1); + m_q.resize (m, k - nj); + m_r.resize (k - nj, n - nj); } else - m_r.resize (k, n-1); + m_r.resize (k, n - nj); } - - template <> - OCTAVE_API void - qr::delete_col (const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +} - Array jsi; - Array js = j.sort (jsi, 0, DESCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); +template <> +OCTAVE_API void +qr::insert_row (const FloatRowVector& u, + octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = std::min (m, n); - if (nj > 0 && (js_beg > n-1 || js_end < 0)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + F77_INT u_nel = to_f77_int (u.numel ()); - if (nj > 0) - { - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + if (! m_q.issquare () || u_nel != n) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - OCTAVE_LOCAL_BUFFER (float, w, k); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (sqrdec, SQRDEC, (m, n - ii, (k == m ? k : k - ii), - m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, - js_elt + 1, w)); - } + if (j < 0 || j > m) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + m_q.resize (m + 1, m + 1); + m_r.resize (m + 1, n); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (k < m) - { - m_q.resize (m, k - nj); - m_r.resize (k - nj, n - nj); - } - else - m_r.resize (k, n - nj); - } - } + FloatRowVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, w, k); + F77_XFCN (sqrinr, SQRINR, (m, n, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, + j + 1, utmp.fortran_vec (), w)); - template <> - OCTAVE_API void - qr::insert_row (const FloatRowVector& u, - octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +} - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = std::min (m, n); - - F77_INT u_nel = to_f77_int (u.numel ()); +template <> +OCTAVE_API void +qr::delete_row (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - if (! m_q.issquare () || u_nel != n) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - if (j < 0 || j > m) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - m_q.resize (m + 1, m + 1); - m_r.resize (m + 1, n); + if (! m_q.issquare ()) + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + if (j < 0 || j > m-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); - FloatRowVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, w, k); - F77_XFCN (sqrinr, SQRINR, (m, n, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, - j + 1, utmp.fortran_vec (), w)); - - } + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - template <> - OCTAVE_API void - qr::delete_row (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); + OCTAVE_LOCAL_BUFFER (float, w, 2*m); + F77_XFCN (sqrder, SQRDER, (m, n, m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, j + 1, + w)); - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - - if (! m_q.issquare ()) - (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - - if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + m_q.resize (m - 1, m - 1); + m_r.resize (m - 1, n); +} - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); +template <> +OCTAVE_API void +qr::shift_cols (octave_idx_type i_arg, octave_idx_type j_arg) +{ + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - OCTAVE_LOCAL_BUFFER (float, w, 2*m); - F77_XFCN (sqrder, SQRDER, (m, n, m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, j + 1, - w)); - - m_q.resize (m - 1, m - 1); - m_r.resize (m - 1, n); - } + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - template <> - OCTAVE_API void - qr::shift_cols (octave_idx_type i_arg, octave_idx_type j_arg) - { - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrshift: index out of range"); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrshift: index out of range"); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (float, w, 2*k); - F77_XFCN (sqrshc, SQRSHC, (m, n, k, - m_q.fortran_vec (), ldq, - m_r.fortran_vec (), ldr, - i + 1, j + 1, w)); - } + OCTAVE_LOCAL_BUFFER (float, w, 2*k); + F77_XFCN (sqrshc, SQRSHC, (m, n, k, + m_q.fortran_vec (), ldq, + m_r.fortran_vec (), ldr, + i + 1, j + 1, w)); +} #endif - template <> - OCTAVE_API void - qr::form (octave_idx_type n_arg, ComplexMatrix& afact, - Complex *tau, type qr_type) +template <> +OCTAVE_API void +qr::form (octave_idx_type n_arg, ComplexMatrix& afact, + Complex *tau, type qr_type) +{ + F77_INT n = to_f77_int (n_arg); + F77_INT m = to_f77_int (afact.rows ()); + F77_INT min_mn = std::min (m, n); + F77_INT info; + + if (qr_type == qr::raw) { - F77_INT n = to_f77_int (n_arg); - F77_INT m = to_f77_int (afact.rows ()); - F77_INT min_mn = std::min (m, n); - F77_INT info; + for (F77_INT j = 0; j < min_mn; j++) + { + F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); + for (F77_INT i = limit + 1; i < m; i++) + afact.elem (i, j) *= tau[j]; + } - if (qr_type == qr::raw) + m_r = afact; + } + else + { + // Attempt to minimize copying. + if (m >= n) { - for (F77_INT j = 0; j < min_mn; j++) + // afact will become m_q. + m_q = afact; + F77_INT k = (qr_type == qr::economy ? n : m); + m_r = ComplexMatrix (k, n); + for (F77_INT j = 0; j < n; j++) { - F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); - for (F77_INT i = limit + 1; i < m; i++) - afact.elem (i, j) *= tau[j]; + F77_INT i = 0; + for (; i <= j; i++) + m_r.xelem (i, j) = afact.xelem (i, j); + for (; i < k; i++) + m_r.xelem (i, j) = 0; } - - m_r = afact; + afact = ComplexMatrix (); // optimize memory } else { - // Attempt to minimize copying. - if (m >= n) - { - // afact will become m_q. - m_q = afact; - F77_INT k = (qr_type == qr::economy ? n : m); - m_r = ComplexMatrix (k, n); - for (F77_INT j = 0; j < n; j++) - { - F77_INT i = 0; - for (; i <= j; i++) - m_r.xelem (i, j) = afact.xelem (i, j); - for (; i < k; i++) - m_r.xelem (i, j) = 0; - } - afact = ComplexMatrix (); // optimize memory - } - else - { - // afact will become m_r. - m_q = ComplexMatrix (m, m); - for (F77_INT j = 0; j < m; j++) - for (F77_INT i = j + 1; i < m; i++) - { - m_q.xelem (i, j) = afact.xelem (i, j); - afact.xelem (i, j) = 0; - } - m_r = afact; - } - - if (m > 0) - { - F77_INT k = to_f77_int (m_q.cols ()); - // workspace query. - Complex clwork; - F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn, - F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - m, F77_DBLE_CMPLX_ARG (tau), - F77_DBLE_CMPLX_ARG (&clwork), -1, - info)); - - // allocate buffer and do the job. - F77_INT lwork = static_cast (clwork.real ()); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (Complex, work, lwork); - F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn, - F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - m, F77_DBLE_CMPLX_ARG (tau), - F77_DBLE_CMPLX_ARG (work), lwork, - info)); - } + // afact will become m_r. + m_q = ComplexMatrix (m, m); + for (F77_INT j = 0; j < m; j++) + for (F77_INT i = j + 1; i < m; i++) + { + m_q.xelem (i, j) = afact.xelem (i, j); + afact.xelem (i, j) = 0; + } + m_r = afact; } - } - - template <> - OCTAVE_API void - qr::init (const ComplexMatrix& a, type qr_type) - { - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn); - - F77_INT info = 0; - - ComplexMatrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); if (m > 0) { + F77_INT k = to_f77_int (m_q.cols ()); // workspace query. Complex clwork; - F77_XFCN (zgeqrf, ZGEQRF, (m, n, - F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), + F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn, + F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), m, F77_DBLE_CMPLX_ARG (tau), - F77_DBLE_CMPLX_ARG (&clwork), -1, info)); + F77_DBLE_CMPLX_ARG (&clwork), -1, + info)); // allocate buffer and do the job. F77_INT lwork = static_cast (clwork.real ()); lwork = std::max (lwork, static_cast (1)); OCTAVE_LOCAL_BUFFER (Complex, work, lwork); - F77_XFCN (zgeqrf, ZGEQRF, (m, n, - F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), + F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn, + F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), m, F77_DBLE_CMPLX_ARG (tau), - F77_DBLE_CMPLX_ARG (work), lwork, info)); + F77_DBLE_CMPLX_ARG (work), lwork, + info)); } + } +} + +template <> +OCTAVE_API void +qr::init (const ComplexMatrix& a, type qr_type) +{ + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); + + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn); + + F77_INT info = 0; + + ComplexMatrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); - form (n, afact, tau, qr_type); + if (m > 0) + { + // workspace query. + Complex clwork; + F77_XFCN (zgeqrf, ZGEQRF, (m, n, + F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), + m, F77_DBLE_CMPLX_ARG (tau), + F77_DBLE_CMPLX_ARG (&clwork), -1, info)); + + // allocate buffer and do the job. + F77_INT lwork = static_cast (clwork.real ()); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (Complex, work, lwork); + F77_XFCN (zgeqrf, ZGEQRF, (m, n, + F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), + m, F77_DBLE_CMPLX_ARG (tau), + F77_DBLE_CMPLX_ARG (work), lwork, info)); } + form (n, afact, tau, qr_type); +} + #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - qr::update (const ComplexColumnVector& u, - const ComplexColumnVector& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::update (const ComplexColumnVector& u, + const ComplexColumnVector& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + ComplexColumnVector utmp = u; + ComplexColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (Complex, w, k); + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqr1up, ZQR1UP, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + m, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), k, + F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), + F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()), + F77_DBLE_CMPLX_ARG (w), rw)); +} - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); +template <> +OCTAVE_API void +qr::update (const ComplexMatrix& u, const ComplexMatrix& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT u_rows = to_f77_int (u.rows ()); + F77_INT u_cols = to_f77_int (u.cols ()); - ComplexColumnVector utmp = u; - ComplexColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (Complex, w, k); - OCTAVE_LOCAL_BUFFER (double, rw, k); - F77_XFCN (zqr1up, ZQR1UP, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + F77_INT v_rows = to_f77_int (v.rows ()); + F77_INT v_cols = to_f77_int (v.cols ()); + + if (u_rows != m || v_rows != n || u_cols != v_cols) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + OCTAVE_LOCAL_BUFFER (Complex, w, k); + OCTAVE_LOCAL_BUFFER (double, rw, k); + for (volatile F77_INT i = 0; i < u_cols; i++) + { + ComplexColumnVector utmp = u.column (i); + ComplexColumnVector vtmp = v.column (i); + F77_XFCN (zqr1up, ZQR1UP, (m, n, k, + F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), m, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), k, F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()), F77_DBLE_CMPLX_ARG (w), rw)); } +} - template <> - OCTAVE_API void - qr::update (const ComplexMatrix& u, const ComplexMatrix& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::insert_col (const ComplexColumnVector& u, + octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_rows = to_f77_int (u.rows ()); - F77_INT u_cols = to_f77_int (u.cols ()); + if (u_nel != m) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - F77_INT v_rows = to_f77_int (v.rows ()); - F77_INT v_cols = to_f77_int (v.cols ()); + if (k < m) + { + m_q.resize (m, k+1); + m_r.resize (k+1, n+1); + } + else + m_r.resize (k, n+1); - if (u_rows != m || v_rows != n || u_cols != v_cols) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - OCTAVE_LOCAL_BUFFER (Complex, w, k); - OCTAVE_LOCAL_BUFFER (double, rw, k); - for (volatile F77_INT i = 0; i < u_cols; i++) - { - ComplexColumnVector utmp = u.column (i); - ComplexColumnVector vtmp = v.column (i); - F77_XFCN (zqr1up, ZQR1UP, (m, n, k, - F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - m, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), k, - F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), - F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()), - F77_DBLE_CMPLX_ARG (w), rw)); - } - } + ComplexColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrinc, ZQRINC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), + ldr, j + 1, + F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), rw)); +} + +template <> +OCTAVE_API void +qr::insert_col (const ComplexMatrix& u, + const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - template <> - OCTAVE_API void - qr::insert_col (const ComplexColumnVector& u, - octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); + Array jsi; + Array js = j.sort (jsi, 0, ASCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT u_cols = to_f77_int (u.cols ()); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); + if (u_nel != m || u_cols != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); - if (u_nel != m) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + if (nj > 0 && (js_beg < 0 || js_end > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - + if (nj > 0) + { + F77_INT kmax = std::min (k + nj, m); if (k < m) { - m_q.resize (m, k+1); - m_r.resize (k+1, n+1); + m_q.resize (m, kmax); + m_r.resize (kmax, n + nj); } else - m_r.resize (k, n+1); + m_r.resize (k, n + nj); F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); - ComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, rw, k); - F77_XFCN (zqrinc, ZQRINC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), - ldr, j + 1, - F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), rw)); - } - - template <> - OCTAVE_API void - qr::insert_col (const ComplexMatrix& u, - const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); - - Array jsi; - Array js = j.sort (jsi, 0, ASCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); - - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_cols = to_f77_int (u.cols ()); - - if (u_nel != m || u_cols != nj) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); - - if (nj > 0 && (js_beg < 0 || js_end > n)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - if (nj > 0) + OCTAVE_LOCAL_BUFFER (double, rw, kmax); + for (volatile F77_INT i = 0; i < nj; i++) { - F77_INT kmax = std::min (k + nj, m); - if (k < m) - { - m_q.resize (m, kmax); - m_r.resize (kmax, n + nj); - } - else - m_r.resize (k, n + nj); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (double, rw, kmax); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - ComplexColumnVector utmp = u.column (jsi(i)); - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (zqrinc, ZQRINC, (m, n + ii, std::min (kmax, k + ii), - F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - ldq, - F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), - ldr, js_elt + 1, - F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), - rw)); - } + F77_INT ii = i; + ComplexColumnVector utmp = u.column (jsi(i)); + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (zqrinc, ZQRINC, (m, n + ii, std::min (kmax, k + ii), + F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + ldq, + F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), + ldr, js_elt + 1, + F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), + rw)); } } +} - template <> - OCTAVE_API void - qr::delete_col (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +qr::delete_col (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); + + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrdec, ZQRDEC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), + ldr, j + 1, rw)); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + if (k < m) + { + m_q.resize (m, k-1); + m_r.resize (k-1, n-1); + } + else + m_r.resize (k, n-1); +} + +template <> +OCTAVE_API void +qr::delete_col (const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + Array jsi; + Array js = j.sort (jsi, 0, DESCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); + + if (nj > 0 && (js_beg > n-1 || js_end < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (nj > 0) + { F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); OCTAVE_LOCAL_BUFFER (double, rw, k); - F77_XFCN (zqrdec, ZQRDEC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), - ldr, j + 1, rw)); + for (volatile F77_INT i = 0; i < nj; i++) + { + F77_INT ii = i; + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (zqrdec, ZQRDEC, (m, n - ii, (k == m ? k : k - ii), + F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + ldq, + F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), + ldr, js_elt + 1, rw)); + } if (k < m) { - m_q.resize (m, k-1); - m_r.resize (k-1, n-1); + m_q.resize (m, k - nj); + m_r.resize (k - nj, n - nj); } else - m_r.resize (k, n-1); + m_r.resize (k, n - nj); } - - template <> - OCTAVE_API void - qr::delete_col (const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +} - Array jsi; - Array js = j.sort (jsi, 0, DESCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); +template <> +OCTAVE_API void +qr::insert_row (const ComplexRowVector& u, + octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = std::min (m, n); - if (nj > 0 && (js_beg > n-1 || js_end < 0)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + F77_INT u_nel = to_f77_int (u.numel ()); - if (nj > 0) - { - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + if (! m_q.issquare () || u_nel != n) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - OCTAVE_LOCAL_BUFFER (double, rw, k); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (zqrdec, ZQRDEC, (m, n - ii, (k == m ? k : k - ii), - F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - ldq, - F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), - ldr, js_elt + 1, rw)); - } + if (j < 0 || j > m) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + m_q.resize (m + 1, m + 1); + m_r.resize (m + 1, n); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (k < m) - { - m_q.resize (m, k - nj); - m_r.resize (k - nj, n - nj); - } - else - m_r.resize (k, n - nj); - } - } + ComplexRowVector utmp = u; + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrinr, ZQRINR, (m, n, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), + ldr, j + 1, + F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), rw)); - template <> - OCTAVE_API void - qr::insert_row (const ComplexRowVector& u, - octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +} - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = std::min (m, n); - - F77_INT u_nel = to_f77_int (u.numel ()); - - if (! m_q.issquare () || u_nel != n) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); +template <> +OCTAVE_API void +qr::delete_row (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - if (j < 0 || j > m) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - m_q.resize (m + 1, m + 1); - m_r.resize (m + 1, n); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - ComplexRowVector utmp = u; - OCTAVE_LOCAL_BUFFER (double, rw, k); - F77_XFCN (zqrinr, ZQRINR, (m, n, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), - ldr, j + 1, - F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), rw)); + if (! m_q.issquare ()) + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - } + if (j < 0 || j > m-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); - template <> - OCTAVE_API void - qr::delete_row (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); - - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (! m_q.issquare ()) - (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); + OCTAVE_LOCAL_BUFFER (Complex, w, m); + OCTAVE_LOCAL_BUFFER (double, rw, m); + F77_XFCN (zqrder, ZQRDER, (m, n, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), + ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), + ldr, j + 1, F77_DBLE_CMPLX_ARG (w), rw)); - if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + m_q.resize (m - 1, m - 1); + m_r.resize (m - 1, n); +} - OCTAVE_LOCAL_BUFFER (Complex, w, m); - OCTAVE_LOCAL_BUFFER (double, rw, m); - F77_XFCN (zqrder, ZQRDER, (m, n, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), - ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), - ldr, j + 1, F77_DBLE_CMPLX_ARG (w), rw)); +template <> +OCTAVE_API void +qr::shift_cols (octave_idx_type i_arg, + octave_idx_type j_arg) +{ + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - m_q.resize (m - 1, m - 1); - m_r.resize (m - 1, n); - } - - template <> - OCTAVE_API void - qr::shift_cols (octave_idx_type i_arg, - octave_idx_type j_arg) - { - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrshift: index out of range"); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrshift: index out of range"); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (Complex, w, k); - OCTAVE_LOCAL_BUFFER (double, rw, k); - F77_XFCN (zqrshc, ZQRSHC, (m, n, k, - F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), ldr, - i + 1, j + 1, F77_DBLE_CMPLX_ARG (w), rw)); - } + OCTAVE_LOCAL_BUFFER (Complex, w, k); + OCTAVE_LOCAL_BUFFER (double, rw, k); + F77_XFCN (zqrshc, ZQRSHC, (m, n, k, + F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), ldr, + i + 1, j + 1, F77_DBLE_CMPLX_ARG (w), rw)); +} #endif - template <> - OCTAVE_API void - qr::form (octave_idx_type n_arg, FloatComplexMatrix& afact, - FloatComplex *tau, type qr_type) +template <> +OCTAVE_API void +qr::form (octave_idx_type n_arg, FloatComplexMatrix& afact, + FloatComplex *tau, type qr_type) +{ + F77_INT n = to_f77_int (n_arg); + F77_INT m = to_f77_int (afact.rows ()); + F77_INT min_mn = std::min (m, n); + F77_INT info; + + if (qr_type == qr::raw) { - F77_INT n = to_f77_int (n_arg); - F77_INT m = to_f77_int (afact.rows ()); - F77_INT min_mn = std::min (m, n); - F77_INT info; + for (F77_INT j = 0; j < min_mn; j++) + { + F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); + for (F77_INT i = limit + 1; i < m; i++) + afact.elem (i, j) *= tau[j]; + } - if (qr_type == qr::raw) + m_r = afact; + } + else + { + // Attempt to minimize copying. + if (m >= n) { - for (F77_INT j = 0; j < min_mn; j++) + // afact will become m_q. + m_q = afact; + F77_INT k = (qr_type == qr::economy ? n : m); + m_r = FloatComplexMatrix (k, n); + for (F77_INT j = 0; j < n; j++) { - F77_INT limit = (j < min_mn - 1 ? j : min_mn - 1); - for (F77_INT i = limit + 1; i < m; i++) - afact.elem (i, j) *= tau[j]; + F77_INT i = 0; + for (; i <= j; i++) + m_r.xelem (i, j) = afact.xelem (i, j); + for (; i < k; i++) + m_r.xelem (i, j) = 0; } - - m_r = afact; + afact = FloatComplexMatrix (); // optimize memory } else { - // Attempt to minimize copying. - if (m >= n) - { - // afact will become m_q. - m_q = afact; - F77_INT k = (qr_type == qr::economy ? n : m); - m_r = FloatComplexMatrix (k, n); - for (F77_INT j = 0; j < n; j++) - { - F77_INT i = 0; - for (; i <= j; i++) - m_r.xelem (i, j) = afact.xelem (i, j); - for (; i < k; i++) - m_r.xelem (i, j) = 0; - } - afact = FloatComplexMatrix (); // optimize memory - } - else - { - // afact will become m_r. - m_q = FloatComplexMatrix (m, m); - for (F77_INT j = 0; j < m; j++) - for (F77_INT i = j + 1; i < m; i++) - { - m_q.xelem (i, j) = afact.xelem (i, j); - afact.xelem (i, j) = 0; - } - m_r = afact; - } - - if (m > 0) - { - F77_INT k = to_f77_int (m_q.cols ()); - // workspace query. - FloatComplex clwork; - F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, - F77_CMPLX_ARG (m_q.fortran_vec ()), m, - F77_CMPLX_ARG (tau), - F77_CMPLX_ARG (&clwork), -1, info)); - - // allocate buffer and do the job. - F77_INT lwork = static_cast (clwork.real ()); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork); - F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, - F77_CMPLX_ARG (m_q.fortran_vec ()), m, - F77_CMPLX_ARG (tau), - F77_CMPLX_ARG (work), lwork, info)); - } + // afact will become m_r. + m_q = FloatComplexMatrix (m, m); + for (F77_INT j = 0; j < m; j++) + for (F77_INT i = j + 1; i < m; i++) + { + m_q.xelem (i, j) = afact.xelem (i, j); + afact.xelem (i, j) = 0; + } + m_r = afact; } - } - - template <> - OCTAVE_API void - qr::init (const FloatComplexMatrix& a, type qr_type) - { - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn); - - F77_INT info = 0; - - FloatComplexMatrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); if (m > 0) { + F77_INT k = to_f77_int (m_q.cols ()); // workspace query. FloatComplex clwork; - F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()), - m, F77_CMPLX_ARG (tau), + F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, + F77_CMPLX_ARG (m_q.fortran_vec ()), m, + F77_CMPLX_ARG (tau), F77_CMPLX_ARG (&clwork), -1, info)); // allocate buffer and do the job. F77_INT lwork = static_cast (clwork.real ()); lwork = std::max (lwork, static_cast (1)); OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork); - F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()), - m, F77_CMPLX_ARG (tau), + F77_XFCN (cungqr, CUNGQR, (m, k, min_mn, + F77_CMPLX_ARG (m_q.fortran_vec ()), m, + F77_CMPLX_ARG (tau), F77_CMPLX_ARG (work), lwork, info)); } + } +} - form (n, afact, tau, qr_type); +template <> +OCTAVE_API void +qr::init (const FloatComplexMatrix& a, type qr_type) +{ + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); + + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn); + + F77_INT info = 0; + + FloatComplexMatrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); + + if (m > 0) + { + // workspace query. + FloatComplex clwork; + F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()), + m, F77_CMPLX_ARG (tau), + F77_CMPLX_ARG (&clwork), -1, info)); + + // allocate buffer and do the job. + F77_INT lwork = static_cast (clwork.real ()); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork); + F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()), + m, F77_CMPLX_ARG (tau), + F77_CMPLX_ARG (work), lwork, info)); } + form (n, afact, tau, qr_type); +} + #if defined (HAVE_QRUPDATE) - template <> - OCTAVE_API void - qr::update (const FloatComplexColumnVector& u, - const FloatComplexColumnVector& v) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +template <> +OCTAVE_API void +qr::update (const FloatComplexColumnVector& u, + const FloatComplexColumnVector& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT v_nel = to_f77_int (v.numel ()); + + if (u_nel != m || v_nel != n) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT v_nel = to_f77_int (v.numel ()); + FloatComplexColumnVector utmp = u; + FloatComplexColumnVector vtmp = v; + OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), + m, F77_CMPLX_ARG (m_r.fortran_vec ()), k, + F77_CMPLX_ARG (utmp.fortran_vec ()), + F77_CMPLX_ARG (vtmp.fortran_vec ()), + F77_CMPLX_ARG (w), rw)); +} - if (u_nel != m || v_nel != n) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); +template <> +OCTAVE_API void +qr::update (const FloatComplexMatrix& u, + const FloatComplexMatrix& v) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_rows = to_f77_int (u.rows ()); + F77_INT u_cols = to_f77_int (u.cols ()); - FloatComplexColumnVector utmp = u; - FloatComplexColumnVector vtmp = v; - OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); - OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_INT v_rows = to_f77_int (v.rows ()); + F77_INT v_cols = to_f77_int (v.cols ()); + + if (u_rows != m || v_rows != n || u_cols != v_cols) + (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + + OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); + OCTAVE_LOCAL_BUFFER (float, rw, k); + for (volatile F77_INT i = 0; i < u_cols; i++) + { + FloatComplexColumnVector utmp = u.column (i); + FloatComplexColumnVector vtmp = v.column (i); F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), m, F77_CMPLX_ARG (m_r.fortran_vec ()), k, F77_CMPLX_ARG (utmp.fortran_vec ()), F77_CMPLX_ARG (vtmp.fortran_vec ()), F77_CMPLX_ARG (w), rw)); } +} - template <> - OCTAVE_API void - qr::update (const FloatComplexMatrix& u, - const FloatComplexMatrix& v) +template <> +OCTAVE_API void +qr::insert_col (const FloatComplexColumnVector& u, + octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); + + F77_INT u_nel = to_f77_int (u.numel ()); + + if (u_nel != m) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + + if (j < 0 || j > n) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (k < m) { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); + m_q.resize (m, k+1); + m_r.resize (k+1, n+1); + } + else + m_r.resize (k, n+1); - F77_INT u_rows = to_f77_int (u.rows ()); - F77_INT u_cols = to_f77_int (u.cols ()); - - F77_INT v_rows = to_f77_int (v.rows ()); - F77_INT v_cols = to_f77_int (v.cols ()); - - if (u_rows != m || v_rows != n || u_cols != v_cols) - (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch"); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); - OCTAVE_LOCAL_BUFFER (float, rw, k); - for (volatile F77_INT i = 0; i < u_cols; i++) - { - FloatComplexColumnVector utmp = u.column (i); - FloatComplexColumnVector vtmp = v.column (i); - F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), - m, F77_CMPLX_ARG (m_r.fortran_vec ()), k, - F77_CMPLX_ARG (utmp.fortran_vec ()), - F77_CMPLX_ARG (vtmp.fortran_vec ()), - F77_CMPLX_ARG (w), rw)); - } - } + FloatComplexColumnVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrinc, CQRINC, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1, + F77_CONST_CMPLX_ARG (utmp.data ()), rw)); +} + +template <> +OCTAVE_API void +qr::insert_col (const FloatComplexMatrix& u, + const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - template <> - OCTAVE_API void - qr::insert_col (const FloatComplexColumnVector& u, - octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); + Array jsi; + Array js = j.sort (jsi, 0, ASCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT u_cols = to_f77_int (u.cols ()); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); + if (u_nel != m || u_cols != nj) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - F77_INT u_nel = to_f77_int (u.numel ()); + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); - if (u_nel != m) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); + if (nj > 0 && (js_beg < 0 || js_end > n)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); - if (j < 0 || j > n) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - + if (nj > 0) + { + F77_INT kmax = std::min (k + nj, m); if (k < m) { - m_q.resize (m, k+1); - m_r.resize (k+1, n+1); + m_q.resize (m, kmax); + m_r.resize (kmax, n + nj); } else - m_r.resize (k, n+1); + m_r.resize (k, n + nj); F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); - FloatComplexColumnVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, rw, k); - F77_XFCN (cqrinc, CQRINC, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1, - F77_CONST_CMPLX_ARG (utmp.data ()), rw)); - } - - template <> - OCTAVE_API void - qr::insert_col (const FloatComplexMatrix& u, - const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); - - Array jsi; - Array js = j.sort (jsi, 0, ASCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); - - F77_INT u_nel = to_f77_int (u.numel ()); - F77_INT u_cols = to_f77_int (u.cols ()); - - if (u_nel != m || u_cols != nj) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); - - if (nj > 0 && (js_beg < 0 || js_end > n)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - if (nj > 0) + OCTAVE_LOCAL_BUFFER (float, rw, kmax); + for (volatile F77_INT i = 0; i < nj; i++) { - F77_INT kmax = std::min (k + nj, m); - if (k < m) - { - m_q.resize (m, kmax); - m_r.resize (kmax, n + nj); - } - else - m_r.resize (k, n + nj); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (float, rw, kmax); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (cqrinc, CQRINC, (m, n + ii, std::min (kmax, k + ii), - F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, - js_elt + 1, - F77_CONST_CMPLX_ARG (u.column (jsi(i)).data ()), - rw)); - } + F77_INT ii = i; + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (cqrinc, CQRINC, (m, n + ii, std::min (kmax, k + ii), + F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, + js_elt + 1, + F77_CONST_CMPLX_ARG (u.column (jsi(i)).data ()), + rw)); } } +} - template <> - OCTAVE_API void - qr::delete_col (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +template <> +OCTAVE_API void +qr::delete_col (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); + + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + + if (j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); + + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrdec, CQRDEC, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1, + rw)); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + if (k < m) + { + m_q.resize (m, k-1); + m_r.resize (k-1, n-1); + } + else + m_r.resize (k, n-1); +} + +template <> +OCTAVE_API void +qr::delete_col (const Array& j) +{ + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = to_f77_int (m_q.cols ()); - if (j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); + Array jsi; + Array js = j.sort (jsi, 0, DESCENDING); + F77_INT nj = to_f77_int (js.numel ()); + bool dups = false; + for (F77_INT i = 0; i < nj - 1; i++) + dups = dups && js(i) == js(i+1); + if (dups) + (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); + + F77_INT js_beg = to_f77_int (js(0)); + F77_INT js_end = to_f77_int (js(nj-1)); + + if (nj > 0 && (js_beg > n-1 || js_end < 0)) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + if (nj > 0) + { F77_INT ldq = to_f77_int (m_q.rows ()); F77_INT ldr = to_f77_int (m_r.rows ()); OCTAVE_LOCAL_BUFFER (float, rw, k); - F77_XFCN (cqrdec, CQRDEC, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1, - rw)); + for (volatile F77_INT i = 0; i < nj; i++) + { + F77_INT ii = i; + F77_INT js_elt = to_f77_int (js(ii)); + F77_XFCN (cqrdec, CQRDEC, (m, n - ii, (k == m ? k : k - ii), + F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, + js_elt + 1, rw)); + } if (k < m) { - m_q.resize (m, k-1); - m_r.resize (k-1, n-1); + m_q.resize (m, k - nj); + m_r.resize (k - nj, n - nj); } else - m_r.resize (k, n-1); + m_r.resize (k, n - nj); } - - template <> - OCTAVE_API void - qr::delete_col (const Array& j) - { - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = to_f77_int (m_q.cols ()); +} - Array jsi; - Array js = j.sort (jsi, 0, DESCENDING); - F77_INT nj = to_f77_int (js.numel ()); - bool dups = false; - for (F77_INT i = 0; i < nj - 1; i++) - dups = dups && js(i) == js(i+1); - - if (dups) - (*current_liboctave_error_handler) ("qrinsert: duplicate index detected"); +template <> +OCTAVE_API void +qr::insert_row (const FloatComplexRowVector& u, + octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - F77_INT js_beg = to_f77_int (js(0)); - F77_INT js_end = to_f77_int (js(nj-1)); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); + F77_INT k = std::min (m, n); - if (nj > 0 && (js_beg > n-1 || js_end < 0)) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); + F77_INT u_nel = to_f77_int (u.numel ()); - if (nj > 0) - { - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + if (! m_q.issquare () || u_nel != n) + (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); - OCTAVE_LOCAL_BUFFER (float, rw, k); - for (volatile F77_INT i = 0; i < nj; i++) - { - F77_INT ii = i; - F77_INT js_elt = to_f77_int (js(ii)); - F77_XFCN (cqrdec, CQRDEC, (m, n - ii, (k == m ? k : k - ii), - F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, - js_elt + 1, rw)); - } + if (j < 0 || j > m) + (*current_liboctave_error_handler) ("qrinsert: index out of range"); + + m_q.resize (m + 1, m + 1); + m_r.resize (m + 1, n); + + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (k < m) - { - m_q.resize (m, k - nj); - m_r.resize (k - nj, n - nj); - } - else - m_r.resize (k, n - nj); - } - } + FloatComplexRowVector utmp = u; + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrinr, CQRINR, (m, n, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, + j + 1, F77_CMPLX_ARG (utmp.fortran_vec ()), + rw)); - template <> - OCTAVE_API void - qr::insert_row (const FloatComplexRowVector& u, - octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); +} - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); - F77_INT k = std::min (m, n); - - F77_INT u_nel = to_f77_int (u.numel ()); - - if (! m_q.issquare () || u_nel != n) - (*current_liboctave_error_handler) ("qrinsert: dimensions mismatch"); +template <> +OCTAVE_API void +qr::delete_row (octave_idx_type j_arg) +{ + F77_INT j = to_f77_int (j_arg); - if (j < 0 || j > m) - (*current_liboctave_error_handler) ("qrinsert: index out of range"); - - m_q.resize (m + 1, m + 1); - m_r.resize (m + 1, n); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + F77_INT m = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - FloatComplexRowVector utmp = u; - OCTAVE_LOCAL_BUFFER (float, rw, k); - F77_XFCN (cqrinr, CQRINR, (m, n, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, - j + 1, F77_CMPLX_ARG (utmp.fortran_vec ()), - rw)); + if (! m_q.issquare ()) + (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); - } + if (j < 0 || j > m-1) + (*current_liboctave_error_handler) ("qrdelete: index out of range"); - template <> - OCTAVE_API void - qr::delete_row (octave_idx_type j_arg) - { - F77_INT j = to_f77_int (j_arg); - - F77_INT m = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - if (! m_q.issquare ()) - (*current_liboctave_error_handler) ("qrdelete: dimensions mismatch"); + OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); + OCTAVE_LOCAL_BUFFER (float, rw, m); + F77_XFCN (cqrder, CQRDER, (m, n, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1, + F77_CMPLX_ARG (w), rw)); - if (j < 0 || j > m-1) - (*current_liboctave_error_handler) ("qrdelete: index out of range"); - - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); + m_q.resize (m - 1, m - 1); + m_r.resize (m - 1, n); +} - OCTAVE_LOCAL_BUFFER (FloatComplex, w, m); - OCTAVE_LOCAL_BUFFER (float, rw, m); - F77_XFCN (cqrder, CQRDER, (m, n, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1, - F77_CMPLX_ARG (w), rw)); +template <> +OCTAVE_API void +qr::shift_cols (octave_idx_type i_arg, + octave_idx_type j_arg) +{ + F77_INT i = to_f77_int (i_arg); + F77_INT j = to_f77_int (j_arg); - m_q.resize (m - 1, m - 1); - m_r.resize (m - 1, n); - } - - template <> - OCTAVE_API void - qr::shift_cols (octave_idx_type i_arg, - octave_idx_type j_arg) - { - F77_INT i = to_f77_int (i_arg); - F77_INT j = to_f77_int (j_arg); + F77_INT m = to_f77_int (m_q.rows ()); + F77_INT k = to_f77_int (m_r.rows ()); + F77_INT n = to_f77_int (m_r.cols ()); - F77_INT m = to_f77_int (m_q.rows ()); - F77_INT k = to_f77_int (m_r.rows ()); - F77_INT n = to_f77_int (m_r.cols ()); + if (i < 0 || i > n-1 || j < 0 || j > n-1) + (*current_liboctave_error_handler) ("qrshift: index out of range"); - if (i < 0 || i > n-1 || j < 0 || j > n-1) - (*current_liboctave_error_handler) ("qrshift: index out of range"); + F77_INT ldq = to_f77_int (m_q.rows ()); + F77_INT ldr = to_f77_int (m_r.rows ()); - F77_INT ldq = to_f77_int (m_q.rows ()); - F77_INT ldr = to_f77_int (m_r.rows ()); - - OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); - OCTAVE_LOCAL_BUFFER (float, rw, k); - F77_XFCN (cqrshc, CQRSHC, (m, n, k, - F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, - F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, - i + 1, j + 1, F77_CMPLX_ARG (w), rw)); - } + OCTAVE_LOCAL_BUFFER (FloatComplex, w, k); + OCTAVE_LOCAL_BUFFER (float, rw, k); + F77_XFCN (cqrshc, CQRSHC, (m, n, k, + F77_CMPLX_ARG (m_q.fortran_vec ()), ldq, + F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, + i + 1, j + 1, F77_CMPLX_ARG (w), rw)); +} #endif - // Instantiations we need. +// Instantiations we need. - template class qr; +template class qr; - template class qr; +template class qr; - template class qr; +template class qr; - template class qr; +template class qr; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/qr.h --- a/liboctave/numeric/qr.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/qr.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,86 +34,86 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - qr - { - public: +template +class +qr +{ +public: - typedef typename T::element_type ELT_T; - typedef typename T::row_vector_type RV_T; - typedef typename T::column_vector_type CV_T; + typedef typename T::element_type ELT_T; + typedef typename T::row_vector_type RV_T; + typedef typename T::column_vector_type CV_T; - enum type - { - std, - raw, - economy - }; - - qr (void) : m_q (), m_r () { } + enum type + { + std, + raw, + economy + }; - qr (const T& a, type qr_type = qr::std) - : m_q (), m_r () - { - init (a, qr_type); - } + qr (void) : m_q (), m_r () { } - OCTAVE_API qr (const T& m_q, const T& m_r); - - qr (const qr& a) : m_q (a.m_q), m_r (a.m_r) { } + qr (const T& a, type qr_type = qr::std) + : m_q (), m_r () + { + init (a, qr_type); + } - qr& operator = (const qr& a) + OCTAVE_API qr (const T& m_q, const T& m_r); + + qr (const qr& a) : m_q (a.m_q), m_r (a.m_r) { } + + qr& operator = (const qr& a) + { + if (this != &a) { - if (this != &a) - { - m_q = a.m_q; - m_r = a.m_r; - } - - return *this; + m_q = a.m_q; + m_r = a.m_r; } - virtual ~qr (void) = default; - - T Q (void) const { return m_q; } + return *this; + } - T R (void) const { return m_r; } + virtual ~qr (void) = default; - OCTAVE_API type get_type (void) const; + T Q (void) const { return m_q; } - OCTAVE_API bool regular (void) const; + T R (void) const { return m_r; } - OCTAVE_API void init (const T& a, type qr_type); + OCTAVE_API type get_type (void) const; - OCTAVE_API void update (const CV_T& u, const CV_T& v); + OCTAVE_API bool regular (void) const; + + OCTAVE_API void init (const T& a, type qr_type); - OCTAVE_API void update (const T& u, const T& v); + OCTAVE_API void update (const CV_T& u, const CV_T& v); - OCTAVE_API void insert_col (const CV_T& u, octave_idx_type j); + OCTAVE_API void update (const T& u, const T& v); - OCTAVE_API void insert_col (const T& u, const Array& j); + OCTAVE_API void insert_col (const CV_T& u, octave_idx_type j); - OCTAVE_API void delete_col (octave_idx_type j); + OCTAVE_API void insert_col (const T& u, const Array& j); - OCTAVE_API void delete_col (const Array& j); + OCTAVE_API void delete_col (octave_idx_type j); - OCTAVE_API void insert_row (const RV_T& u, octave_idx_type j); + OCTAVE_API void delete_col (const Array& j); - OCTAVE_API void delete_row (octave_idx_type j); + OCTAVE_API void insert_row (const RV_T& u, octave_idx_type j); - OCTAVE_API void shift_cols (octave_idx_type i, octave_idx_type j); + OCTAVE_API void delete_row (octave_idx_type j); - protected: + OCTAVE_API void shift_cols (octave_idx_type i, octave_idx_type j); - T m_q; - T m_r; +protected: - OCTAVE_API void - form (octave_idx_type n, T& afact, ELT_T *tau, type qr_type); - }; + T m_q; + T m_r; - extern OCTAVE_API void warn_qrupdate_once (void); + OCTAVE_API void + form (octave_idx_type n, T& afact, ELT_T *tau, type qr_type); +}; + +extern OCTAVE_API void warn_qrupdate_once (void); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/qrp.cc --- a/liboctave/numeric/qrp.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/qrp.cc Thu Dec 01 20:05:44 2022 -0800 @@ -47,307 +47,307 @@ OCTAVE_BEGIN_NAMESPACE(math) - // Specialization. +// Specialization. - template <> - OCTAVE_API - void - qrp::init (const Matrix& a, type qr_type) - { - assert (qr_type != qr::raw); - - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (double, tau, min_mn); +template <> +OCTAVE_API +void +qrp::init (const Matrix& a, type qr_type) +{ + assert (qr_type != qr::raw); - F77_INT info = 0; + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); - Matrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); - - MArray jpvt (dim_vector (n, 1), 0); + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (double, tau, min_mn); - if (m > 0) - { - // workspace query. - double rlwork; - F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.fortran_vec (), - m, jpvt.fortran_vec (), tau, - &rlwork, -1, info)); + F77_INT info = 0; + + Matrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); - // allocate buffer and do the job. - F77_INT lwork = static_cast (rlwork); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (double, work, lwork); + MArray jpvt (dim_vector (n, 1), 0); - F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.fortran_vec (), - m, jpvt.fortran_vec (), tau, - work, lwork, info)); - } - else - { - for (F77_INT i = 0; i < n; i++) - jpvt(i) = i+1; - } + if (m > 0) + { + // workspace query. + double rlwork; + F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.fortran_vec (), + m, jpvt.fortran_vec (), tau, + &rlwork, -1, info)); - // Form Permutation matrix (if economy is requested, return the - // indices only!) + // allocate buffer and do the job. + F77_INT lwork = static_cast (rlwork); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (double, work, lwork); - jpvt -= static_cast (1); - m_p = PermMatrix (jpvt, true); - - form (n, afact, tau, qr_type); + F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.fortran_vec (), + m, jpvt.fortran_vec (), tau, + work, lwork, info)); } - - template <> - OCTAVE_API - qrp::qrp (const Matrix& a, type qr_type) - : qr (), m_p () + else { - init (a, qr_type); + for (F77_INT i = 0; i < n; i++) + jpvt(i) = i+1; } - template <> - OCTAVE_API - RowVector - qrp::Pvec (void) const - { - Array pa (m_p.col_perm_vec ()); - RowVector pv (MArray (pa) + 1.0); - return pv; - } + // Form Permutation matrix (if economy is requested, return the + // indices only!) + + jpvt -= static_cast (1); + m_p = PermMatrix (jpvt, true); - template <> - OCTAVE_API - void - qrp::init (const FloatMatrix& a, type qr_type) - { - assert (qr_type != qr::raw); + form (n, afact, tau, qr_type); +} + +template <> +OCTAVE_API +qrp::qrp (const Matrix& a, type qr_type) + : qr (), m_p () +{ + init (a, qr_type); +} - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (float, tau, min_mn); - - F77_INT info = 0; +template <> +OCTAVE_API +RowVector +qrp::Pvec (void) const +{ + Array pa (m_p.col_perm_vec ()); + RowVector pv (MArray (pa) + 1.0); + return pv; +} - FloatMatrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); - - MArray jpvt (dim_vector (n, 1), 0); - - if (m > 0) - { - // workspace query. - float rlwork; - F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.fortran_vec (), - m, jpvt.fortran_vec (), tau, - &rlwork, -1, info)); +template <> +OCTAVE_API +void +qrp::init (const FloatMatrix& a, type qr_type) +{ + assert (qr_type != qr::raw); - // allocate buffer and do the job. - F77_INT lwork = static_cast (rlwork); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (float, work, lwork); + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); + + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (float, tau, min_mn); - F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.fortran_vec (), - m, jpvt.fortran_vec (), tau, - work, lwork, info)); - } - else - { - for (F77_INT i = 0; i < n; i++) - jpvt(i) = i+1; - } + F77_INT info = 0; - // Form Permutation matrix (if economy is requested, return the - // indices only!) + FloatMatrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); + + MArray jpvt (dim_vector (n, 1), 0); - jpvt -= static_cast (1); - m_p = PermMatrix (jpvt, true); - - form (n, afact, tau, qr_type); - } - - template <> - OCTAVE_API - qrp::qrp (const FloatMatrix& a, type qr_type) - : qr (), m_p () + if (m > 0) { - init (a, qr_type); - } + // workspace query. + float rlwork; + F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.fortran_vec (), + m, jpvt.fortran_vec (), tau, + &rlwork, -1, info)); - template <> - OCTAVE_API - FloatRowVector - qrp::Pvec (void) const + // allocate buffer and do the job. + F77_INT lwork = static_cast (rlwork); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (float, work, lwork); + + F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.fortran_vec (), + m, jpvt.fortran_vec (), tau, + work, lwork, info)); + } + else { - Array pa (m_p.col_perm_vec ()); - FloatRowVector pv (MArray (pa) + 1.0f); - return pv; + for (F77_INT i = 0; i < n; i++) + jpvt(i) = i+1; } - template <> - OCTAVE_API - void - qrp::init (const ComplexMatrix& a, type qr_type) - { - assert (qr_type != qr::raw); + // Form Permutation matrix (if economy is requested, return the + // indices only!) + + jpvt -= static_cast (1); + m_p = PermMatrix (jpvt, true); - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn); + form (n, afact, tau, qr_type); +} - F77_INT info = 0; - - ComplexMatrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); +template <> +OCTAVE_API +qrp::qrp (const FloatMatrix& a, type qr_type) + : qr (), m_p () +{ + init (a, qr_type); +} - MArray jpvt (dim_vector (n, 1), 0); - - if (m > 0) - { - OCTAVE_LOCAL_BUFFER (double, rwork, 2*n); +template <> +OCTAVE_API +FloatRowVector +qrp::Pvec (void) const +{ + Array pa (m_p.col_perm_vec ()); + FloatRowVector pv (MArray (pa) + 1.0f); + return pv; +} - // workspace query. - Complex clwork; - F77_XFCN (zgeqp3, ZGEQP3, (m, n, - F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), - m, jpvt.fortran_vec (), - F77_DBLE_CMPLX_ARG (tau), - F77_DBLE_CMPLX_ARG (&clwork), - -1, rwork, info)); +template <> +OCTAVE_API +void +qrp::init (const ComplexMatrix& a, type qr_type) +{ + assert (qr_type != qr::raw); - // allocate buffer and do the job. - F77_INT lwork = static_cast (clwork.real ()); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (Complex, work, lwork); + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); - F77_XFCN (zgeqp3, ZGEQP3, (m, n, - F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), - m, jpvt.fortran_vec (), - F77_DBLE_CMPLX_ARG (tau), - F77_DBLE_CMPLX_ARG (work), - lwork, rwork, info)); - } - else - { - for (F77_INT i = 0; i < n; i++) - jpvt(i) = i+1; - } + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (Complex, tau, min_mn); + + F77_INT info = 0; - // Form Permutation matrix (if economy is requested, return the - // indices only!) + ComplexMatrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); - jpvt -= static_cast (1); - m_p = PermMatrix (jpvt, true); + MArray jpvt (dim_vector (n, 1), 0); + + if (m > 0) + { + OCTAVE_LOCAL_BUFFER (double, rwork, 2*n); - form (n, afact, tau, qr_type); - } + // workspace query. + Complex clwork; + F77_XFCN (zgeqp3, ZGEQP3, (m, n, + F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), + m, jpvt.fortran_vec (), + F77_DBLE_CMPLX_ARG (tau), + F77_DBLE_CMPLX_ARG (&clwork), + -1, rwork, info)); - template <> - OCTAVE_API - qrp::qrp (const ComplexMatrix& a, type qr_type) - : qr (), m_p () - { - init (a, qr_type); + // allocate buffer and do the job. + F77_INT lwork = static_cast (clwork.real ()); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (Complex, work, lwork); + + F77_XFCN (zgeqp3, ZGEQP3, (m, n, + F77_DBLE_CMPLX_ARG (afact.fortran_vec ()), + m, jpvt.fortran_vec (), + F77_DBLE_CMPLX_ARG (tau), + F77_DBLE_CMPLX_ARG (work), + lwork, rwork, info)); } - - template <> - OCTAVE_API - RowVector - qrp::Pvec (void) const + else { - Array pa (m_p.col_perm_vec ()); - RowVector pv (MArray (pa) + 1.0); - return pv; + for (F77_INT i = 0; i < n; i++) + jpvt(i) = i+1; } - template <> - OCTAVE_API - void - qrp::init (const FloatComplexMatrix& a, type qr_type) - { - assert (qr_type != qr::raw); + // Form Permutation matrix (if economy is requested, return the + // indices only!) + + jpvt -= static_cast (1); + m_p = PermMatrix (jpvt, true); - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); + form (n, afact, tau, qr_type); +} + +template <> +OCTAVE_API +qrp::qrp (const ComplexMatrix& a, type qr_type) + : qr (), m_p () +{ + init (a, qr_type); +} - F77_INT min_mn = (m < n ? m : n); - OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn); - - F77_INT info = 0; +template <> +OCTAVE_API +RowVector +qrp::Pvec (void) const +{ + Array pa (m_p.col_perm_vec ()); + RowVector pv (MArray (pa) + 1.0); + return pv; +} - FloatComplexMatrix afact = a; - if (m > n && qr_type == qr::std) - afact.resize (m, m); +template <> +OCTAVE_API +void +qrp::init (const FloatComplexMatrix& a, type qr_type) +{ + assert (qr_type != qr::raw); - MArray jpvt (dim_vector (n, 1), 0); - - if (m > 0) - { - OCTAVE_LOCAL_BUFFER (float, rwork, 2*n); + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); - // workspace query. - FloatComplex clwork; - F77_XFCN (cgeqp3, CGEQP3, (m, n, - F77_CMPLX_ARG (afact.fortran_vec ()), - m, jpvt.fortran_vec (), - F77_CMPLX_ARG (tau), - F77_CMPLX_ARG (&clwork), - -1, rwork, info)); + F77_INT min_mn = (m < n ? m : n); + OCTAVE_LOCAL_BUFFER (FloatComplex, tau, min_mn); + + F77_INT info = 0; - // allocate buffer and do the job. - F77_INT lwork = static_cast (clwork.real ()); - lwork = std::max (lwork, static_cast (1)); - OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork); + FloatComplexMatrix afact = a; + if (m > n && qr_type == qr::std) + afact.resize (m, m); + + MArray jpvt (dim_vector (n, 1), 0); + + if (m > 0) + { + OCTAVE_LOCAL_BUFFER (float, rwork, 2*n); - F77_XFCN (cgeqp3, CGEQP3, (m, n, - F77_CMPLX_ARG (afact.fortran_vec ()), - m, jpvt.fortran_vec (), - F77_CMPLX_ARG (tau), - F77_CMPLX_ARG (work), - lwork, rwork, info)); - } - else - { - for (F77_INT i = 0; i < n; i++) - jpvt(i) = i+1; - } + // workspace query. + FloatComplex clwork; + F77_XFCN (cgeqp3, CGEQP3, (m, n, + F77_CMPLX_ARG (afact.fortran_vec ()), + m, jpvt.fortran_vec (), + F77_CMPLX_ARG (tau), + F77_CMPLX_ARG (&clwork), + -1, rwork, info)); - // Form Permutation matrix (if economy is requested, return the - // indices only!) + // allocate buffer and do the job. + F77_INT lwork = static_cast (clwork.real ()); + lwork = std::max (lwork, static_cast (1)); + OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork); - jpvt -= static_cast (1); - m_p = PermMatrix (jpvt, true); - - form (n, afact, tau, qr_type); + F77_XFCN (cgeqp3, CGEQP3, (m, n, + F77_CMPLX_ARG (afact.fortran_vec ()), + m, jpvt.fortran_vec (), + F77_CMPLX_ARG (tau), + F77_CMPLX_ARG (work), + lwork, rwork, info)); + } + else + { + for (F77_INT i = 0; i < n; i++) + jpvt(i) = i+1; } - template <> - OCTAVE_API - qrp::qrp (const FloatComplexMatrix& a, type qr_type) - : qr (), m_p () - { - init (a, qr_type); - } + // Form Permutation matrix (if economy is requested, return the + // indices only!) + + jpvt -= static_cast (1); + m_p = PermMatrix (jpvt, true); + + form (n, afact, tau, qr_type); +} - template <> - OCTAVE_API - FloatRowVector - qrp::Pvec (void) const - { - Array pa (m_p.col_perm_vec ()); - FloatRowVector pv (MArray (pa) + 1.0f); - return pv; - } +template <> +OCTAVE_API +qrp::qrp (const FloatComplexMatrix& a, type qr_type) + : qr (), m_p () +{ + init (a, qr_type); +} + +template <> +OCTAVE_API +FloatRowVector +qrp::Pvec (void) const +{ + Array pa (m_p.col_perm_vec ()); + FloatRowVector pv (MArray (pa) + 1.0f); + return pv; +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/qrp.h --- a/liboctave/numeric/qrp.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/qrp.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,45 +35,45 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - qrp : public qr - { - public: +template +class +qrp : public qr +{ +public: - typedef typename T::real_row_vector_type RV_T; + typedef typename T::real_row_vector_type RV_T; - typedef typename qr::type type; - - qrp (void) : qr (), m_p () { } + typedef typename qr::type type; - OCTAVE_API qrp (const T&, type = qr::std); + qrp (void) : qr (), m_p () { } + + OCTAVE_API qrp (const T&, type = qr::std); - qrp (const qrp& a) : qr (a), m_p (a.m_p) { } + qrp (const qrp& a) : qr (a), m_p (a.m_p) { } - qrp& operator = (const qrp& a) + qrp& operator = (const qrp& a) + { + if (this != &a) { - if (this != &a) - { - qr::operator = (a); - m_p = a.m_p; - } - - return *this; + qr::operator = (a); + m_p = a.m_p; } - ~qrp (void) = default; + return *this; + } - OCTAVE_API void init (const T&, type = qr::std); + ~qrp (void) = default; - PermMatrix P (void) const { return m_p; } + OCTAVE_API void init (const T&, type = qr::std); - OCTAVE_API RV_T Pvec (void) const; + PermMatrix P (void) const { return m_p; } + + OCTAVE_API RV_T Pvec (void) const; - private: +private: - PermMatrix m_p; - }; + PermMatrix m_p; +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/randgamma.cc --- a/liboctave/numeric/randgamma.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/randgamma.cc Thu Dec 01 20:05:44 2022 -0800 @@ -92,46 +92,46 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template void rand_gamma (T a, octave_idx_type n, T *r) - { - octave_idx_type i; - /* If a < 1, start by generating gamma (1+a) */ - const T d = (a < 1. ? 1.+a : a) - 1./3.; - const T c = 1./std::sqrt (9.*d); +template void rand_gamma (T a, octave_idx_type n, T *r) +{ + octave_idx_type i; + /* If a < 1, start by generating gamma (1+a) */ + const T d = (a < 1. ? 1.+a : a) - 1./3.; + const T c = 1./std::sqrt (9.*d); - /* Handle invalid cases */ - if (a <= 0 || lo_ieee_isinf (a)) - { - for (i=0; i < n; i++) - r[i] = numeric_limits::NaN (); - return; - } + /* Handle invalid cases */ + if (a <= 0 || lo_ieee_isinf (a)) + { + for (i=0; i < n; i++) + r[i] = numeric_limits::NaN (); + return; + } - for (i=0; i < n; i++) - { - T x, xsq, v, u; - restart: - x = rand_normal (); - v = (1+c*x); - v *= (v*v); - if (v <= 0) - goto restart; /* rare, so don't bother moving up */ - u = rand_uniform (); - xsq = x*x; - if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v))) - goto restart; - r[i] = d*v; - } - if (a < 1) - { - /* Use gamma(a) = gamma(1+a)*U^(1/a) */ - /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */ - for (i = 0; i < n; i++) - r[i] *= exp (-rand_exponential () / a); - } - } + for (i=0; i < n; i++) + { + T x, xsq, v, u; + restart: + x = rand_normal (); + v = (1+c*x); + v *= (v*v); + if (v <= 0) + goto restart; /* rare, so don't bother moving up */ + u = rand_uniform (); + xsq = x*x; + if (u >= 1.-0.0331*xsq*xsq && std::log (u) >= 0.5*xsq + d*(1-v+std::log (v))) + goto restart; + r[i] = d*v; + } + if (a < 1) + { + /* Use gamma(a) = gamma(1+a)*U^(1/a) */ + /* Given REXP = -log(U) then U^(1/a) = exp(-REXP/a) */ + for (i = 0; i < n; i++) + r[i] *= exp (-rand_exponential () / a); + } +} - template OCTAVE_API void rand_gamma (double, octave_idx_type, double *); - template OCTAVE_API void rand_gamma (float, octave_idx_type, float *); +template OCTAVE_API void rand_gamma (double, octave_idx_type, double *); +template OCTAVE_API void rand_gamma (float, octave_idx_type, float *); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/randgamma.h --- a/liboctave/numeric/randgamma.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/randgamma.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,18 +33,18 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template - OCTAVE_API void - rand_gamma (T a, octave_idx_type n, T *p); +template +OCTAVE_API void +rand_gamma (T a, octave_idx_type n, T *p); - template - T - rand_gamma (T a) - { - T retval; - rand_gamma (a, 1, &retval); - return retval; - } +template +T +rand_gamma (T a) +{ + T retval; + rand_gamma (a, 1, &retval); + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/randmtzig.cc --- a/liboctave/numeric/randmtzig.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/randmtzig.cc Thu Dec 01 20:05:44 2022 -0800 @@ -180,7 +180,7 @@ OCTAVE_BEGIN_NAMESPACE(octave) - /* ===== Mersenne Twister 32-bit generator ===== */ +/* ===== Mersenne Twister 32-bit generator ===== */ #define MT_M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ @@ -189,259 +189,259 @@ #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) ) #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL)) - static uint32_t *next; - static uint32_t state[MT_N]; /* the array for the state vector */ - static int left = 1; - static int initf = 0; - static int initt = 1; - static int inittf = 1; +static uint32_t *next; +static uint32_t state[MT_N]; /* the array for the state vector */ +static int left = 1; +static int initf = 0; +static int initt = 1; +static int inittf = 1; - /* initializes state[MT_N] with a seed */ - void init_mersenne_twister (const uint32_t s) - { - int j; - state[0] = s & 0xffffffffUL; - for (j = 1; j < MT_N; j++) - { - state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array state[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ - state[j] &= 0xffffffffUL; /* for >32 bit machines */ - } - left = 1; - initf = 1; - } +/* initializes state[MT_N] with a seed */ +void init_mersenne_twister (const uint32_t s) +{ + int j; + state[0] = s & 0xffffffffUL; + for (j = 1; j < MT_N; j++) + { + state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array state[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + state[j] &= 0xffffffffUL; /* for >32 bit machines */ + } + left = 1; + initf = 1; +} - /* initialize by an array with array-length */ - /* init_key is the array for initializing keys */ - /* key_length is its length */ - void init_mersenne_twister (const uint32_t *init_key, const int key_length) - { - int i, j, k; - init_mersenne_twister (19650218UL); - i = 1; - j = 0; - k = (MT_N > key_length ? MT_N : key_length); - for (; k; k--) - { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL)) - + init_key[j] + j; /* non linear */ - state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - j++; - if (i >= MT_N) - { - state[0] = state[MT_N-1]; - i = 1; - } - if (j >= key_length) - j = 0; - } - for (k = MT_N - 1; k; k--) - { - state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL)) - - i; /* non linear */ - state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ - i++; - if (i >= MT_N) - { - state[0] = state[MT_N-1]; - i = 1; - } - } +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +void init_mersenne_twister (const uint32_t *init_key, const int key_length) +{ + int i, j, k; + init_mersenne_twister (19650218UL); + i = 1; + j = 0; + k = (MT_N > key_length ? MT_N : key_length); + for (; k; k--) + { + state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1664525UL)) + + init_key[j] + j; /* non linear */ + state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + i++; + j++; + if (i >= MT_N) + { + state[0] = state[MT_N-1]; + i = 1; + } + if (j >= key_length) + j = 0; + } + for (k = MT_N - 1; k; k--) + { + state[i] = (state[i] ^ ((state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL)) + - i; /* non linear */ + state[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + i++; + if (i >= MT_N) + { + state[0] = state[MT_N-1]; + i = 1; + } + } - state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */ - left = 1; - initf = 1; - } + state[0] = 0x80000000UL; /* MSB is 1; assuring nonzero initial array */ + left = 1; + initf = 1; +} - void init_mersenne_twister (void) - { - uint32_t entropy[MT_N]; - int n = 0; +void init_mersenne_twister (void) +{ + uint32_t entropy[MT_N]; + int n = 0; - // Gather some entropy from various sources + // Gather some entropy from various sources - sys::time now; + sys::time now; - // Current time in seconds - if (n < MT_N) - entropy[n++] = now.unix_time (); + // Current time in seconds + if (n < MT_N) + entropy[n++] = now.unix_time (); - // CPU time used (usec) - if (n < MT_N) - entropy[n++] = clock (); + // CPU time used (usec) + if (n < MT_N) + entropy[n++] = clock (); - // Fractional part of current time - if (n < MT_N) - entropy[n++] = now.usec (); + // Fractional part of current time + if (n < MT_N) + entropy[n++] = now.usec (); - // Include the PID to make sure that several processes reaching here at the - // same time use different random numbers. - if (n < MT_N) - entropy[n++] = sys::getpid (); + // Include the PID to make sure that several processes reaching here at the + // same time use different random numbers. + if (n < MT_N) + entropy[n++] = sys::getpid (); - if (n < MT_N) - { - try - { - // The standard doesn't *guarantee* that random_device provides - // non-deterministic random numbers. So add entropy from this - // source last to make sure we gathered at least some entropy from - // the earlier sources. - std::random_device rd; - std::uniform_int_distribution dist; - // Add 1024 bit of "true" entropy - int n_max = std::min (n + 32, MT_N); - while (n < n_max) - entropy[n++] = dist (rd); - } - catch (const std::exception&) - { - // Just ignore any exception and skip that source of entropy. - } - } + if (n < MT_N) + { + try + { + // The standard doesn't *guarantee* that random_device provides + // non-deterministic random numbers. So add entropy from this + // source last to make sure we gathered at least some entropy from + // the earlier sources. + std::random_device rd; + std::uniform_int_distribution dist; + // Add 1024 bit of "true" entropy + int n_max = std::min (n + 32, MT_N); + while (n < n_max) + entropy[n++] = dist (rd); + } + catch (const std::exception&) + { + // Just ignore any exception and skip that source of entropy. + } + } - // Send all the entropy into the initial state vector - init_mersenne_twister (entropy, n); - } + // Send all the entropy into the initial state vector + init_mersenne_twister (entropy, n); +} - void set_mersenne_twister_state (const uint32_t *save) - { - std::copy_n (save, MT_N, state); - left = save[MT_N]; - next = state + (MT_N - left + 1); - } +void set_mersenne_twister_state (const uint32_t *save) +{ + std::copy_n (save, MT_N, state); + left = save[MT_N]; + next = state + (MT_N - left + 1); +} - void get_mersenne_twister_state (uint32_t *save) - { - std::copy_n (state, MT_N, save); - save[MT_N] = left; - } +void get_mersenne_twister_state (uint32_t *save) +{ + std::copy_n (state, MT_N, save); + save[MT_N] = left; +} - static void next_state (void) - { - uint32_t *p = state; - int j; +static void next_state (void) +{ + uint32_t *p = state; + int j; - /* if init_by_int() has not been called, */ - /* a default initial seed is used */ - /* if (initf==0) init_by_int(5489UL); */ - /* Or better yet, a random seed! */ - if (initf == 0) - init_mersenne_twister (); + /* if init_by_int() has not been called, */ + /* a default initial seed is used */ + /* if (initf==0) init_by_int(5489UL); */ + /* Or better yet, a random seed! */ + if (initf == 0) + init_mersenne_twister (); - left = MT_N; - next = state; + left = MT_N; + next = state; - for (j = MT_N - MT_M + 1; --j; p++) - *p = p[MT_M] ^ TWIST(p[0], p[1]); + for (j = MT_N - MT_M + 1; --j; p++) + *p = p[MT_M] ^ TWIST(p[0], p[1]); - for (j = MT_M; --j; p++) - *p = p[MT_M-MT_N] ^ TWIST(p[0], p[1]); + for (j = MT_M; --j; p++) + *p = p[MT_M-MT_N] ^ TWIST(p[0], p[1]); - *p = p[MT_M-MT_N] ^ TWIST(p[0], state[0]); - } + *p = p[MT_M-MT_N] ^ TWIST(p[0], state[0]); +} - /* generates a random number on [0,0xffffffff]-interval */ - static uint32_t randmt (void) - { - uint32_t y; +/* generates a random number on [0,0xffffffff]-interval */ +static uint32_t randmt (void) +{ + uint32_t y; - if (--left == 0) - next_state (); - y = *next++; + if (--left == 0) + next_state (); + y = *next++; - /* Tempering */ - y ^= (y >> 11); - y ^= (y << 7) & 0x9d2c5680UL; - y ^= (y << 15) & 0xefc60000UL; - return (y ^ (y >> 18)); - } + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + return (y ^ (y >> 18)); +} - /* ===== Uniform generators ===== */ +/* ===== Uniform generators ===== */ - /* Select which 32 bit generator to use */ +/* Select which 32 bit generator to use */ #define randi32 randmt - static uint64_t randi53 (void) - { - const uint32_t lo = randi32 (); - const uint32_t hi = randi32 () & 0x1FFFFF; +static uint64_t randi53 (void) +{ + const uint32_t lo = randi32 (); + const uint32_t hi = randi32 () & 0x1FFFFF; #if defined (HAVE_X86_32) - uint64_t u; - uint32_t *p = (uint32_t *)&u; - p[0] = lo; - p[1] = hi; - return u; + uint64_t u; + uint32_t *p = (uint32_t *)&u; + p[0] = lo; + p[1] = hi; + return u; #else - return ((static_cast (hi) << 32) | lo); + return ((static_cast (hi) << 32) | lo); #endif - } +} - static uint64_t randi54 (void) - { - const uint32_t lo = randi32 (); - const uint32_t hi = randi32 () & 0x3FFFFF; +static uint64_t randi54 (void) +{ + const uint32_t lo = randi32 (); + const uint32_t hi = randi32 () & 0x3FFFFF; #if defined (HAVE_X86_32) - uint64_t u; - uint32_t *p = static_cast (&u); - p[0] = lo; - p[1] = hi; - return u; + uint64_t u; + uint32_t *p = static_cast (&u); + p[0] = lo; + p[1] = hi; + return u; #else - return ((static_cast (hi) << 32) | lo); + return ((static_cast (hi) << 32) | lo); #endif - } +} - /* generates a random number on (0,1)-real-interval */ - static float randu24 (void) - { - uint32_t i; +/* generates a random number on (0,1)-real-interval */ +static float randu24 (void) +{ + uint32_t i; - do - { - i = randi32 () & static_cast (0xFFFFFF); - } - while (i == 0); + do + { + i = randi32 () & static_cast (0xFFFFFF); + } + while (i == 0); - return i * (1.0f / 16777216.0f); - } + return i * (1.0f / 16777216.0f); +} - /* generates a random number on (0,1) with 53-bit resolution */ - static double randu53 (void) - { - int32_t a, b; +/* generates a random number on (0,1) with 53-bit resolution */ +static double randu53 (void) +{ + int32_t a, b; - do - { - a = randi32 () >> 5; - b = randi32 () >> 6; - } - while (a == 0 && b == 0); + do + { + a = randi32 () >> 5; + b = randi32 () >> 6; + } + while (a == 0 && b == 0); - return (a*67108864.0 + b) * (1.0/9007199254740992.0); - } + return (a*67108864.0 + b) * (1.0/9007199254740992.0); +} - /* Determine mantissa for uniform doubles */ - template <> - OCTAVE_API double - rand_uniform (void) - { - return randu53 (); - } +/* Determine mantissa for uniform doubles */ +template <> +OCTAVE_API double +rand_uniform (void) +{ + return randu53 (); +} - /* Determine mantissa for uniform floats */ - template <> - OCTAVE_API float - rand_uniform (void) - { - return randu24 (); - } +/* Determine mantissa for uniform floats */ +template <> +OCTAVE_API float +rand_uniform (void) +{ + return randu24 (); +} - /* ===== Ziggurat normal and exponential generators ===== */ +/* ===== Ziggurat normal and exponential generators ===== */ #define ZIGGURAT_TABLE_SIZE 256 @@ -460,232 +460,232 @@ #define NRANDI randi54() /* 53 bits for mantissa + 1 bit sign */ #define RANDU randu53() - static ZIGINT ki[ZIGGURAT_TABLE_SIZE]; - static double wi[ZIGGURAT_TABLE_SIZE], fi[ZIGGURAT_TABLE_SIZE]; - static ZIGINT ke[ZIGGURAT_TABLE_SIZE]; - static double we[ZIGGURAT_TABLE_SIZE], fe[ZIGGURAT_TABLE_SIZE]; +static ZIGINT ki[ZIGGURAT_TABLE_SIZE]; +static double wi[ZIGGURAT_TABLE_SIZE], fi[ZIGGURAT_TABLE_SIZE]; +static ZIGINT ke[ZIGGURAT_TABLE_SIZE]; +static double we[ZIGGURAT_TABLE_SIZE], fe[ZIGGURAT_TABLE_SIZE]; - /* - This code is based on the paper Marsaglia and Tsang, "The ziggurat method - for generating random variables", Journ. Statistical Software. Code was - presented in this paper for a Ziggurat of 127 levels and using a 32 bit - integer random number generator. This version of the code, uses the - Mersenne Twister as the integer generator and uses 256 levels in the - Ziggurat. This has several advantages. +/* + This code is based on the paper Marsaglia and Tsang, "The ziggurat method + for generating random variables", Journ. Statistical Software. Code was + presented in this paper for a Ziggurat of 127 levels and using a 32 bit + integer random number generator. This version of the code, uses the + Mersenne Twister as the integer generator and uses 256 levels in the + Ziggurat. This has several advantages. - 1) As Marsaglia and Tsang themselves states, the more levels the few - times the expensive tail algorithm must be called - 2) The cycle time of the generator is determined by the integer - generator, thus the use of a Mersenne Twister for the core random - generator makes this cycle extremely long. - 3) The license on the original code was unclear, thus rewriting the code - from the article means we are free of copyright issues. - 4) Compile flag for full 53-bit random mantissa. + 1) As Marsaglia and Tsang themselves states, the more levels the few + times the expensive tail algorithm must be called + 2) The cycle time of the generator is determined by the integer + generator, thus the use of a Mersenne Twister for the core random + generator makes this cycle extremely long. + 3) The license on the original code was unclear, thus rewriting the code + from the article means we are free of copyright issues. + 4) Compile flag for full 53-bit random mantissa. - It should be stated that the authors made my life easier, by the fact that - the algorithm developed in the text of the article is for a 256 level - ziggurat, even if the code itself isn't... + It should be stated that the authors made my life easier, by the fact that + the algorithm developed in the text of the article is for a 256 level + ziggurat, even if the code itself isn't... - One modification to the algorithm developed in the article, is that it is - assumed that 0 <= x < Inf, and "unsigned long"s are used, thus resulting in - terms like 2^32 in the code. As the normal distribution is defined between - -Inf < x < Inf, we effectively only have 31 bit integers plus a sign. Thus - in Marsaglia and Tsang, terms like 2^32 become 2^31. We use NMANTISSA for - this term. The exponential distribution is one sided so we use the - full 32 bits. We use EMANTISSA for this term. + One modification to the algorithm developed in the article, is that it is + assumed that 0 <= x < Inf, and "unsigned long"s are used, thus resulting in + terms like 2^32 in the code. As the normal distribution is defined between + -Inf < x < Inf, we effectively only have 31 bit integers plus a sign. Thus + in Marsaglia and Tsang, terms like 2^32 become 2^31. We use NMANTISSA for + this term. The exponential distribution is one sided so we use the + full 32 bits. We use EMANTISSA for this term. - It appears that I'm slightly slower than the code in the article, this - is partially due to a better generator of random integers than they - use. But might also be that the case of rapid return was optimized by - inlining the relevant code with a #define. As the basic Mersenne - Twister is only 25% faster than this code I suspect that the main - reason is just the use of the Mersenne Twister and not the inlining, - so I'm not going to try and optimize further. - */ + It appears that I'm slightly slower than the code in the article, this + is partially due to a better generator of random integers than they + use. But might also be that the case of rapid return was optimized by + inlining the relevant code with a #define. As the basic Mersenne + Twister is only 25% faster than this code I suspect that the main + reason is just the use of the Mersenne Twister and not the inlining, + so I'm not going to try and optimize further. +*/ - void create_ziggurat_tables (void) - { - int i; - double x, x1; +void create_ziggurat_tables (void) +{ + int i; + double x, x1; - /* Ziggurat tables for the normal distribution */ - x1 = ZIGGURAT_NOR_R; - wi[255] = x1 / NMANTISSA; - fi[255] = exp (-0.5 * x1 * x1); + /* Ziggurat tables for the normal distribution */ + x1 = ZIGGURAT_NOR_R; + wi[255] = x1 / NMANTISSA; + fi[255] = exp (-0.5 * x1 * x1); - /* Index zero is special for tail strip, where Marsaglia and Tsang - * defines this as - * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1, - * where v is the area of each strip of the ziggurat. - */ - ki[0] = static_cast (x1 * fi[255] / NOR_SECTION_AREA * NMANTISSA); - wi[0] = NOR_SECTION_AREA / fi[255] / NMANTISSA; - fi[0] = 1.; + /* Index zero is special for tail strip, where Marsaglia and Tsang + * defines this as + * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1, + * where v is the area of each strip of the ziggurat. + */ + ki[0] = static_cast (x1 * fi[255] / NOR_SECTION_AREA * NMANTISSA); + wi[0] = NOR_SECTION_AREA / fi[255] / NMANTISSA; + fi[0] = 1.; - for (i = 254; i > 0; i--) - { - /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus - * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y)) - */ - x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + fi[i+1])); - ki[i+1] = static_cast (x / x1 * NMANTISSA); - wi[i] = x / NMANTISSA; - fi[i] = exp (-0.5 * x * x); - x1 = x; - } + for (i = 254; i > 0; i--) + { + /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus + * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y)) + */ + x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + fi[i+1])); + ki[i+1] = static_cast (x / x1 * NMANTISSA); + wi[i] = x / NMANTISSA; + fi[i] = exp (-0.5 * x * x); + x1 = x; + } - ki[1] = 0; + ki[1] = 0; - /* Zigurrat tables for the exponential distribution */ - x1 = ZIGGURAT_EXP_R; - we[255] = x1 / EMANTISSA; - fe[255] = exp (-x1); + /* Zigurrat tables for the exponential distribution */ + x1 = ZIGGURAT_EXP_R; + we[255] = x1 / EMANTISSA; + fe[255] = exp (-x1); - /* Index zero is special for tail strip, where Marsaglia and Tsang - * defines this as - * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1, - * where v is the area of each strip of the ziggurat. - */ - ke[0] = static_cast (x1 * fe[255] / EXP_SECTION_AREA * EMANTISSA); - we[0] = EXP_SECTION_AREA / fe[255] / EMANTISSA; - fe[0] = 1.; + /* Index zero is special for tail strip, where Marsaglia and Tsang + * defines this as + * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1, + * where v is the area of each strip of the ziggurat. + */ + ke[0] = static_cast (x1 * fe[255] / EXP_SECTION_AREA * EMANTISSA); + we[0] = EXP_SECTION_AREA / fe[255] / EMANTISSA; + fe[0] = 1.; - for (i = 254; i > 0; i--) - { - /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus - * need inverse operator of y = exp(-x) -> x = -ln(y) - */ - x = - std::log (EXP_SECTION_AREA / x1 + fe[i+1]); - ke[i+1] = static_cast (x / x1 * EMANTISSA); - we[i] = x / EMANTISSA; - fe[i] = exp (-x); - x1 = x; - } - ke[1] = 0; + for (i = 254; i > 0; i--) + { + /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus + * need inverse operator of y = exp(-x) -> x = -ln(y) + */ + x = - std::log (EXP_SECTION_AREA / x1 + fe[i+1]); + ke[i+1] = static_cast (x / x1 * EMANTISSA); + we[i] = x / EMANTISSA; + fe[i] = exp (-x); + x1 = x; + } + ke[1] = 0; - initt = 0; - } + initt = 0; +} - /* - * Here is the guts of the algorithm. As Marsaglia and Tsang state the - * algorithm in their paper - * - * 1) Calculate a random signed integer j and let i be the index - * provided by the rightmost 8-bits of j - * 2) Set x = j * w_i. If j < k_i return x - * 3) If i = 0, then return x from the tail - * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x - * 5) goto step 1 - * - * Where f is the functional form of the distribution, which for a normal - * distribution is exp(-0.5*x*x) - */ +/* + * Here is the guts of the algorithm. As Marsaglia and Tsang state the + * algorithm in their paper + * + * 1) Calculate a random signed integer j and let i be the index + * provided by the rightmost 8-bits of j + * 2) Set x = j * w_i. If j < k_i return x + * 3) If i = 0, then return x from the tail + * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x + * 5) goto step 1 + * + * Where f is the functional form of the distribution, which for a normal + * distribution is exp(-0.5*x*x) + */ - template <> OCTAVE_API double rand_normal (void) - { - if (initt) - create_ziggurat_tables (); +template <> OCTAVE_API double rand_normal (void) +{ + if (initt) + create_ziggurat_tables (); - while (1) - { - /* The following code is specialized for 32-bit mantissa. - * Compared to the arbitrary mantissa code, there is a performance - * gain for 32-bits: PPC: 2%, MIPS: 8%, x86: 40% - * There is a bigger performance gain compared to using a full - * 53-bit mantissa: PPC: 60%, MIPS: 65%, x86: 240% - * Of course, different compilers and operating systems may - * have something to do with this. - */ + while (1) + { + /* The following code is specialized for 32-bit mantissa. + * Compared to the arbitrary mantissa code, there is a performance + * gain for 32-bits: PPC: 2%, MIPS: 8%, x86: 40% + * There is a bigger performance gain compared to using a full + * 53-bit mantissa: PPC: 60%, MIPS: 65%, x86: 240% + * Of course, different compilers and operating systems may + * have something to do with this. + */ # if defined (HAVE_X86_32) - /* 53-bit mantissa, 1-bit sign, x86 32-bit architecture */ - double x; - int si, idx; - uint32_t lo, hi; - int64_t rabs; - uint32_t *p = (uint32_t *)&rabs; - lo = randi32 (); - idx = lo & 0xFF; - hi = randi32 (); - si = hi & UMASK; - p[0] = lo; - p[1] = hi & 0x1FFFFF; - x = ( si ? -rabs : rabs ) * wi[idx]; + /* 53-bit mantissa, 1-bit sign, x86 32-bit architecture */ + double x; + int si, idx; + uint32_t lo, hi; + int64_t rabs; + uint32_t *p = (uint32_t *)&rabs; + lo = randi32 (); + idx = lo & 0xFF; + hi = randi32 (); + si = hi & UMASK; + p[0] = lo; + p[1] = hi & 0x1FFFFF; + x = ( si ? -rabs : rabs ) * wi[idx]; # else - /* arbitrary mantissa (selected by NRANDI, with 1 bit for sign) */ - const uint64_t r = NRANDI; - const int64_t rabs = r >> 1; - const int idx = static_cast (rabs & 0xFF); - const double x = ( (r & 1) ? -rabs : rabs) * wi[idx]; + /* arbitrary mantissa (selected by NRANDI, with 1 bit for sign) */ + const uint64_t r = NRANDI; + const int64_t rabs = r >> 1; + const int idx = static_cast (rabs & 0xFF); + const double x = ( (r & 1) ? -rabs : rabs) * wi[idx]; # endif - if (rabs < static_cast (ki[idx])) - return x; /* 99.3% of the time we return here 1st try */ - else if (idx == 0) - { - /* As stated in Marsaglia and Tsang - * - * For the normal tail, the method of Marsaglia[5] provides: - * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x, - * then return r+x. Except that r+x is always in the positive - * tail!!!! Any thing random might be used to determine the - * sign, but as we already have r we might as well use it - * - * [PAK] but not the bottom 8 bits, since they are all 0 here! - */ - double xx, yy; - do - { - xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU); - yy = - std::log (RANDU); - } - while ( yy+yy <= xx*xx); - return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx); - } - else if ((fi[idx-1] - fi[idx]) * RANDU + fi[idx] < exp (-0.5*x*x)) - return x; - } - } + if (rabs < static_cast (ki[idx])) + return x; /* 99.3% of the time we return here 1st try */ + else if (idx == 0) + { + /* As stated in Marsaglia and Tsang + * + * For the normal tail, the method of Marsaglia[5] provides: + * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x, + * then return r+x. Except that r+x is always in the positive + * tail!!!! Any thing random might be used to determine the + * sign, but as we already have r we might as well use it + * + * [PAK] but not the bottom 8 bits, since they are all 0 here! + */ + double xx, yy; + do + { + xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU); + yy = - std::log (RANDU); + } + while ( yy+yy <= xx*xx); + return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx); + } + else if ((fi[idx-1] - fi[idx]) * RANDU + fi[idx] < exp (-0.5*x*x)) + return x; + } +} - template <> OCTAVE_API double rand_exponential (void) - { - if (initt) - create_ziggurat_tables (); +template <> OCTAVE_API double rand_exponential (void) +{ + if (initt) + create_ziggurat_tables (); - while (1) - { - ZIGINT ri = ERANDI; - const int idx = static_cast (ri & 0xFF); - const double x = ri * we[idx]; - if (ri < ke[idx]) - return x; /* 98.9% of the time we return here 1st try */ - else if (idx == 0) - { - /* As stated in Marsaglia and Tsang - * - * For the exponential tail, the method of Marsaglia[5] provides: - * x = r - ln(U); - */ - return ZIGGURAT_EXP_R - std::log (RANDU); - } - else if ((fe[idx-1] - fe[idx]) * RANDU + fe[idx] < exp (-x)) - return x; - } - } + while (1) + { + ZIGINT ri = ERANDI; + const int idx = static_cast (ri & 0xFF); + const double x = ri * we[idx]; + if (ri < ke[idx]) + return x; /* 98.9% of the time we return here 1st try */ + else if (idx == 0) + { + /* As stated in Marsaglia and Tsang + * + * For the exponential tail, the method of Marsaglia[5] provides: + * x = r - ln(U); + */ + return ZIGGURAT_EXP_R - std::log (RANDU); + } + else if ((fe[idx-1] - fe[idx]) * RANDU + fe[idx] < exp (-x)) + return x; + } +} - template <> OCTAVE_API void rand_uniform (octave_idx_type n, double *p) - { - std::generate_n (p, n, [](void) { return rand_uniform (); }); - } +template <> OCTAVE_API void rand_uniform (octave_idx_type n, double *p) +{ + std::generate_n (p, n, [](void) { return rand_uniform (); }); +} - template <> OCTAVE_API void rand_normal (octave_idx_type n, double *p) - { - std::generate_n (p, n, [](void) { return rand_normal (); }); - } +template <> OCTAVE_API void rand_normal (octave_idx_type n, double *p) +{ + std::generate_n (p, n, [](void) { return rand_normal (); }); +} - template <> OCTAVE_API void rand_exponential (octave_idx_type n, double *p) - { - std::generate_n (p, n, [](void) { return rand_exponential (); }); - } +template <> OCTAVE_API void rand_exponential (octave_idx_type n, double *p) +{ + std::generate_n (p, n, [](void) { return rand_exponential (); }); +} #undef ZIGINT #undef EMANTISSA @@ -701,169 +701,169 @@ #define NRANDI randi32() /* 31 bits for mantissa + 1 bit sign */ #define RANDU randu24() - static ZIGINT fki[ZIGGURAT_TABLE_SIZE]; - static float fwi[ZIGGURAT_TABLE_SIZE], ffi[ZIGGURAT_TABLE_SIZE]; - static ZIGINT fke[ZIGGURAT_TABLE_SIZE]; - static float fwe[ZIGGURAT_TABLE_SIZE], ffe[ZIGGURAT_TABLE_SIZE]; +static ZIGINT fki[ZIGGURAT_TABLE_SIZE]; +static float fwi[ZIGGURAT_TABLE_SIZE], ffi[ZIGGURAT_TABLE_SIZE]; +static ZIGINT fke[ZIGGURAT_TABLE_SIZE]; +static float fwe[ZIGGURAT_TABLE_SIZE], ffe[ZIGGURAT_TABLE_SIZE]; - static void create_ziggurat_float_tables (void) - { - int i; - float x, x1; - - /* Ziggurat tables for the normal distribution */ - x1 = ZIGGURAT_NOR_R; - fwi[255] = x1 / NMANTISSA; - ffi[255] = exp (-0.5 * x1 * x1); +static void create_ziggurat_float_tables (void) +{ + int i; + float x, x1; - /* Index zero is special for tail strip, where Marsaglia and Tsang - * defines this as - * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1, - * where v is the area of each strip of the ziggurat. - */ - fki[0] = static_cast (x1 * ffi[255] / NOR_SECTION_AREA * NMANTISSA); - fwi[0] = NOR_SECTION_AREA / ffi[255] / NMANTISSA; - ffi[0] = 1.; + /* Ziggurat tables for the normal distribution */ + x1 = ZIGGURAT_NOR_R; + fwi[255] = x1 / NMANTISSA; + ffi[255] = exp (-0.5 * x1 * x1); - for (i = 254; i > 0; i--) - { - /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus - * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y)) - */ - x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + ffi[i+1])); - fki[i+1] = static_cast (x / x1 * NMANTISSA); - fwi[i] = x / NMANTISSA; - ffi[i] = exp (-0.5 * x * x); - x1 = x; - } - - fki[1] = 0; + /* Index zero is special for tail strip, where Marsaglia and Tsang + * defines this as + * k_0 = 2^31 * r * f(r) / v, w_0 = 0.5^31 * v / f(r), f_0 = 1, + * where v is the area of each strip of the ziggurat. + */ + fki[0] = static_cast (x1 * ffi[255] / NOR_SECTION_AREA * NMANTISSA); + fwi[0] = NOR_SECTION_AREA / ffi[255] / NMANTISSA; + ffi[0] = 1.; - /* Zigurrat tables for the exponential distribution */ - x1 = ZIGGURAT_EXP_R; - fwe[255] = x1 / EMANTISSA; - ffe[255] = exp (-x1); - - /* Index zero is special for tail strip, where Marsaglia and Tsang - * defines this as - * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1, - * where v is the area of each strip of the ziggurat. - */ - fke[0] = static_cast (x1 * ffe[255] / EXP_SECTION_AREA * EMANTISSA); - fwe[0] = EXP_SECTION_AREA / ffe[255] / EMANTISSA; - ffe[0] = 1.; + for (i = 254; i > 0; i--) + { + /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus + * need inverse operator of y = exp(-0.5*x*x) -> x = sqrt(-2*ln(y)) + */ + x = std::sqrt (-2. * std::log (NOR_SECTION_AREA / x1 + ffi[i+1])); + fki[i+1] = static_cast (x / x1 * NMANTISSA); + fwi[i] = x / NMANTISSA; + ffi[i] = exp (-0.5 * x * x); + x1 = x; + } - for (i = 254; i > 0; i--) - { - /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus - * need inverse operator of y = exp(-x) -> x = -ln(y) - */ - x = - std::log (EXP_SECTION_AREA / x1 + ffe[i+1]); - fke[i+1] = static_cast (x / x1 * EMANTISSA); - fwe[i] = x / EMANTISSA; - ffe[i] = exp (-x); - x1 = x; - } - fke[1] = 0; + fki[1] = 0; - inittf = 0; - } + /* Zigurrat tables for the exponential distribution */ + x1 = ZIGGURAT_EXP_R; + fwe[255] = x1 / EMANTISSA; + ffe[255] = exp (-x1); - /* - * Here is the guts of the algorithm. As Marsaglia and Tsang state the - * algorithm in their paper - * - * 1) Calculate a random signed integer j and let i be the index - * provided by the rightmost 8-bits of j - * 2) Set x = j * w_i. If j < k_i return x - * 3) If i = 0, then return x from the tail - * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x - * 5) goto step 1 - * - * Where f is the functional form of the distribution, which for a normal - * distribution is exp(-0.5*x*x) + /* Index zero is special for tail strip, where Marsaglia and Tsang + * defines this as + * k_0 = 2^32 * r * f(r) / v, w_0 = 0.5^32 * v / f(r), f_0 = 1, + * where v is the area of each strip of the ziggurat. */ + fke[0] = static_cast (x1 * ffe[255] / EXP_SECTION_AREA * EMANTISSA); + fwe[0] = EXP_SECTION_AREA / ffe[255] / EMANTISSA; + ffe[0] = 1.; - template <> OCTAVE_API float rand_normal (void) - { - if (inittf) - create_ziggurat_float_tables (); + for (i = 254; i > 0; i--) + { + /* New x is given by x = f^{-1}(v/x_{i+1} + f(x_{i+1})), thus + * need inverse operator of y = exp(-x) -> x = -ln(y) + */ + x = - std::log (EXP_SECTION_AREA / x1 + ffe[i+1]); + fke[i+1] = static_cast (x / x1 * EMANTISSA); + fwe[i] = x / EMANTISSA; + ffe[i] = exp (-x); + x1 = x; + } + fke[1] = 0; + + inittf = 0; +} - while (1) - { - /* 32-bit mantissa */ - const uint32_t r = randi32 (); - const uint32_t rabs = r & LMASK; - const int idx = static_cast (r & 0xFF); - const float x = static_cast (r) * fwi[idx]; - if (rabs < fki[idx]) - return x; /* 99.3% of the time we return here 1st try */ - else if (idx == 0) - { - /* As stated in Marsaglia and Tsang - * - * For the normal tail, the method of Marsaglia[5] provides: - * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x, - * then return r+x. Except that r+x is always in the positive - * tail!!!! Any thing random might be used to determine the - * sign, but as we already have r we might as well use it - * - * [PAK] but not the bottom 8 bits, since they are all 0 here! - */ - float xx, yy; - do - { - xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU); - yy = - std::log (RANDU); - } - while ( yy+yy <= xx*xx); - return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx); - } - else if ((ffi[idx-1] - ffi[idx]) * RANDU + ffi[idx] < exp (-0.5*x*x)) - return x; - } - } +/* + * Here is the guts of the algorithm. As Marsaglia and Tsang state the + * algorithm in their paper + * + * 1) Calculate a random signed integer j and let i be the index + * provided by the rightmost 8-bits of j + * 2) Set x = j * w_i. If j < k_i return x + * 3) If i = 0, then return x from the tail + * 4) If [f(x_{i-1}) - f(x_i)] * U < f(x) - f(x_i), return x + * 5) goto step 1 + * + * Where f is the functional form of the distribution, which for a normal + * distribution is exp(-0.5*x*x) + */ + +template <> OCTAVE_API float rand_normal (void) +{ + if (inittf) + create_ziggurat_float_tables (); - template <> OCTAVE_API float rand_exponential (void) - { - if (inittf) - create_ziggurat_float_tables (); + while (1) + { + /* 32-bit mantissa */ + const uint32_t r = randi32 (); + const uint32_t rabs = r & LMASK; + const int idx = static_cast (r & 0xFF); + const float x = static_cast (r) * fwi[idx]; + if (rabs < fki[idx]) + return x; /* 99.3% of the time we return here 1st try */ + else if (idx == 0) + { + /* As stated in Marsaglia and Tsang + * + * For the normal tail, the method of Marsaglia[5] provides: + * generate x = -ln(U_1)/r, y = -ln(U_2), until y+y > x*x, + * then return r+x. Except that r+x is always in the positive + * tail!!!! Any thing random might be used to determine the + * sign, but as we already have r we might as well use it + * + * [PAK] but not the bottom 8 bits, since they are all 0 here! + */ + float xx, yy; + do + { + xx = - ZIGGURAT_NOR_INV_R * std::log (RANDU); + yy = - std::log (RANDU); + } + while ( yy+yy <= xx*xx); + return ((rabs & 0x100) ? -ZIGGURAT_NOR_R-xx : ZIGGURAT_NOR_R+xx); + } + else if ((ffi[idx-1] - ffi[idx]) * RANDU + ffi[idx] < exp (-0.5*x*x)) + return x; + } +} - while (1) - { - ZIGINT ri = ERANDI; - const int idx = static_cast (ri & 0xFF); - const float x = ri * fwe[idx]; - if (ri < fke[idx]) - return x; /* 98.9% of the time we return here 1st try */ - else if (idx == 0) - { - /* As stated in Marsaglia and Tsang - * - * For the exponential tail, the method of Marsaglia[5] provides: - * x = r - ln(U); - */ - return ZIGGURAT_EXP_R - std::log (RANDU); - } - else if ((ffe[idx-1] - ffe[idx]) * RANDU + ffe[idx] < exp (-x)) - return x; - } - } +template <> OCTAVE_API float rand_exponential (void) +{ + if (inittf) + create_ziggurat_float_tables (); - template <> OCTAVE_API void rand_uniform (octave_idx_type n, float *p) - { - std::generate_n (p, n, [](void) { return rand_uniform (); }); - } + while (1) + { + ZIGINT ri = ERANDI; + const int idx = static_cast (ri & 0xFF); + const float x = ri * fwe[idx]; + if (ri < fke[idx]) + return x; /* 98.9% of the time we return here 1st try */ + else if (idx == 0) + { + /* As stated in Marsaglia and Tsang + * + * For the exponential tail, the method of Marsaglia[5] provides: + * x = r - ln(U); + */ + return ZIGGURAT_EXP_R - std::log (RANDU); + } + else if ((ffe[idx-1] - ffe[idx]) * RANDU + ffe[idx] < exp (-x)) + return x; + } +} - template <> OCTAVE_API void rand_normal (octave_idx_type n, float *p) - { - std::generate_n (p, n, [](void) { return rand_normal (); }); - } +template <> OCTAVE_API void rand_uniform (octave_idx_type n, float *p) +{ + std::generate_n (p, n, [](void) { return rand_uniform (); }); +} - template <> OCTAVE_API void rand_exponential (octave_idx_type n, float *p) - { - std::generate_n (p, n, [](void) { return rand_exponential (); }); - } +template <> OCTAVE_API void rand_normal (octave_idx_type n, float *p) +{ + std::generate_n (p, n, [](void) { return rand_normal (); }); +} + +template <> OCTAVE_API void rand_exponential (octave_idx_type n, float *p) +{ + std::generate_n (p, n, [](void) { return rand_exponential (); }); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/randmtzig.h --- a/liboctave/numeric/randmtzig.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/randmtzig.h Thu Dec 01 20:05:44 2022 -0800 @@ -73,50 +73,50 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Mersenne Twister. +// Mersenne Twister. - extern OCTAVE_API void init_mersenne_twister (void); - extern OCTAVE_API void init_mersenne_twister (const uint32_t seed); - extern OCTAVE_API void init_mersenne_twister (const uint32_t *init_key, - const int key_length); +extern OCTAVE_API void init_mersenne_twister (void); +extern OCTAVE_API void init_mersenne_twister (const uint32_t seed); +extern OCTAVE_API void init_mersenne_twister (const uint32_t *init_key, + const int key_length); - extern OCTAVE_API void set_mersenne_twister_state (const uint32_t *save); - extern OCTAVE_API void get_mersenne_twister_state (uint32_t *save); +extern OCTAVE_API void set_mersenne_twister_state (const uint32_t *save); +extern OCTAVE_API void get_mersenne_twister_state (uint32_t *save); - template OCTAVE_API T rand_uniform (void); - template OCTAVE_API T rand_normal (void); - template OCTAVE_API T rand_exponential (void); +template OCTAVE_API T rand_uniform (void); +template OCTAVE_API T rand_normal (void); +template OCTAVE_API T rand_exponential (void); - template OCTAVE_API void rand_uniform (octave_idx_type n, T *p); - template OCTAVE_API void rand_normal (octave_idx_type n, T *p); - template OCTAVE_API void - rand_exponential (octave_idx_type n, T *p); +template OCTAVE_API void rand_uniform (octave_idx_type n, T *p); +template OCTAVE_API void rand_normal (octave_idx_type n, T *p); +template OCTAVE_API void +rand_exponential (octave_idx_type n, T *p); - template <> OCTAVE_API double rand_uniform (void); - template <> OCTAVE_API double rand_normal (void); - template <> OCTAVE_API double rand_exponential (void); +template <> OCTAVE_API double rand_uniform (void); +template <> OCTAVE_API double rand_normal (void); +template <> OCTAVE_API double rand_exponential (void); - template <> OCTAVE_API float rand_uniform (void); - template <> OCTAVE_API float rand_normal (void); - template <> OCTAVE_API float rand_exponential (void); +template <> OCTAVE_API float rand_uniform (void); +template <> OCTAVE_API float rand_normal (void); +template <> OCTAVE_API float rand_exponential (void); - template <> OCTAVE_API void - rand_uniform (octave_idx_type n, double *p); +template <> OCTAVE_API void +rand_uniform (octave_idx_type n, double *p); - template <> OCTAVE_API void - rand_normal (octave_idx_type n, double *p); +template <> OCTAVE_API void +rand_normal (octave_idx_type n, double *p); - template <> OCTAVE_API void - rand_exponential (octave_idx_type n, double *p); +template <> OCTAVE_API void +rand_exponential (octave_idx_type n, double *p); - template <> OCTAVE_API void - rand_uniform (octave_idx_type n, float *p); +template <> OCTAVE_API void +rand_uniform (octave_idx_type n, float *p); - template <> OCTAVE_API void - rand_normal (octave_idx_type n, float *p); +template <> OCTAVE_API void +rand_normal (octave_idx_type n, float *p); - template <> OCTAVE_API void - rand_exponential (octave_idx_type n, float *p); +template <> OCTAVE_API void +rand_exponential (octave_idx_type n, float *p); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/randpoisson.cc --- a/liboctave/numeric/randpoisson.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/randpoisson.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,421 +41,435 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static double xlgamma (double x) - { - return std::lgamma (x); - } +static double xlgamma (double x) +{ + return std::lgamma (x); +} - /* ---- pprsc.c from Stadloeber's winrand --- */ +/* ---- pprsc.c from Stadloeber's winrand --- */ - /* flogfak(k) = ln(k!) */ - static double flogfak (double k) - { +/* flogfak(k) = ln(k!) */ +static double flogfak (double k) +{ #define C0 9.18938533204672742e-01 #define C1 8.33333333333333333e-02 #define C3 -2.77777777777777778e-03 #define C5 7.93650793650793651e-04 #define C7 -5.95238095238095238e-04 - static double logfak[30L] = - { - 0.00000000000000000, 0.00000000000000000, 0.69314718055994531, - 1.79175946922805500, 3.17805383034794562, 4.78749174278204599, - 6.57925121201010100, 8.52516136106541430, 10.60460290274525023, - 12.80182748008146961, 15.10441257307551530, 17.50230784587388584, - 19.98721449566188615, 22.55216385312342289, 25.19122118273868150, - 27.89927138384089157, 30.67186010608067280, 33.50507345013688888, - 36.39544520803305358, 39.33988418719949404, 42.33561646075348503, - 45.38013889847690803, 48.47118135183522388, 51.60667556776437357, - 54.78472939811231919, 58.00360522298051994, 61.26170176100200198, - 64.55753862700633106, 67.88974313718153498, 71.25703896716800901 - }; + static double logfak[30L] = + { + 0.00000000000000000, 0.00000000000000000, 0.69314718055994531, + 1.79175946922805500, 3.17805383034794562, 4.78749174278204599, + 6.57925121201010100, 8.52516136106541430, 10.60460290274525023, + 12.80182748008146961, 15.10441257307551530, 17.50230784587388584, + 19.98721449566188615, 22.55216385312342289, 25.19122118273868150, + 27.89927138384089157, 30.67186010608067280, 33.50507345013688888, + 36.39544520803305358, 39.33988418719949404, 42.33561646075348503, + 45.38013889847690803, 48.47118135183522388, 51.60667556776437357, + 54.78472939811231919, 58.00360522298051994, 61.26170176100200198, + 64.55753862700633106, 67.88974313718153498, 71.25703896716800901 + }; - double r, rr; + double r, rr; - if (k >= 30.0) - { - r = 1.0 / k; - rr = r * r; - return ((k + 0.5)*std::log (k) - k + C0 - + r*(C1 + rr*(C3 + rr*(C5 + rr*C7)))); - } - else - return (logfak[static_cast (k)]); - } + if (k >= 30.0) + { + r = 1.0 / k; + rr = r * r; + return ((k + 0.5)*std::log (k) - k + C0 + + r*(C1 + rr*(C3 + rr*(C5 + rr*C7)))); + } + else + return (logfak[static_cast (k)]); +} - /****************************************************************** - * * - * Poisson Distribution - Patchwork Rejection/Inversion * - * * - ****************************************************************** - * * - * For parameter my < 10, Tabulated Inversion is applied. * - * For my >= 10, Patchwork Rejection is employed: * - * The area below the histogram function f(x) is rearranged in * - * its body by certain point reflections. Within a large center * - * interval variates are sampled efficiently by rejection from * - * uniform hats. Rectangular immediate acceptance regions speed * - * up the generation. The remaining tails are covered by * - * exponential functions. * - * * - ****************************************************************** - * * - * FUNCTION : - pprsc samples a random number from the Poisson * - * distribution with parameter my > 0. * - * REFERENCE : - H. Zechner (1994): Efficient sampling from * - * continuous and discrete unimodal distributions, * - * Doctoral Dissertation, 156 pp., Technical * - * University Graz, Austria. * - * SUBPROGRAM : - drand(seed) ... (0,1)-Uniform generator with * - * unsigned long integer *seed. * - * * - * Implemented by H. Zechner, January 1994 * - * Revised by F. Niederl, July 1994 * - * * - ******************************************************************/ +/****************************************************************** + * * + * Poisson Distribution - Patchwork Rejection/Inversion * + * * + ****************************************************************** + * * + * For parameter my < 10, Tabulated Inversion is applied. * + * For my >= 10, Patchwork Rejection is employed: * + * The area below the histogram function f(x) is rearranged in * + * its body by certain point reflections. Within a large center * + * interval variates are sampled efficiently by rejection from * + * uniform hats. Rectangular immediate acceptance regions speed * + * up the generation. The remaining tails are covered by * + * exponential functions. * + * * + ****************************************************************** + * * + * FUNCTION : - pprsc samples a random number from the Poisson * + * distribution with parameter my > 0. * + * REFERENCE : - H. Zechner (1994): Efficient sampling from * + * continuous and discrete unimodal distributions, * + * Doctoral Dissertation, 156 pp., Technical * + * University Graz, Austria. * + * SUBPROGRAM : - drand(seed) ... (0,1)-Uniform generator with * + * unsigned long integer *seed. * + * * + * Implemented by H. Zechner, January 1994 * + * Revised by F. Niederl, July 1994 * + * * + ******************************************************************/ - static double f (double k, double l_nu, double c_pm) - { - return exp (k * l_nu - flogfak (k) - c_pm); - } +static double f (double k, double l_nu, double c_pm) +{ + return exp (k * l_nu - flogfak (k) - c_pm); +} - static double pprsc (double my) - { - static double my_last = -1.0; - static double m, k2, k4, k1, k5; - static double dl, dr, r1, r2, r4, r5, ll, lr, l_my, c_pm, - f1, f2, f4, f5, p1, p2, p3, p4, p5, p6; - double Dk, X, Y; - double Ds, U, V, W; +static double pprsc (double my) +{ + static double my_last = -1.0; + static double m, k2, k4, k1, k5; + static double dl, dr, r1, r2, r4, r5, ll, lr, l_my, c_pm, + f1, f2, f4, f5, p1, p2, p3, p4, p5, p6; + double Dk, X, Y; + double Ds, U, V, W; - if (my != my_last) - { /* set-up */ - my_last = my; - /* approximate deviation of reflection points k2, k4 from my - 1/2 */ - Ds = std::sqrt (my + 0.25); + if (my != my_last) + { + /* set-up */ + my_last = my; + /* approximate deviation of reflection points k2, k4 from my - 1/2 */ + Ds = std::sqrt (my + 0.25); - /* mode m, reflection points k2 and k4, and points k1 and k5, */ - /* which delimit the centre region of h(x) */ - m = std::floor (my); - k2 = ceil (my - 0.5 - Ds); - k4 = std::floor (my - 0.5 + Ds); - k1 = k2 + k2 - m + 1L; - k5 = k4 + k4 - m; + /* mode m, reflection points k2 and k4, and points k1 and k5, */ + /* which delimit the centre region of h(x) */ + m = std::floor (my); + k2 = ceil (my - 0.5 - Ds); + k4 = std::floor (my - 0.5 + Ds); + k1 = k2 + k2 - m + 1L; + k5 = k4 + k4 - m; - /* range width of the critical left and right centre region */ - dl = (k2 - k1); - dr = (k5 - k4); + /* range width of the critical left and right centre region */ + dl = (k2 - k1); + dr = (k5 - k4); - /* recurrence constants r(k)=p(k)/p(k-1) at k = k1, k2, k4+1, k5+1 */ - r1 = my / k1; - r2 = my / k2; - r4 = my / (k4 + 1.0); - r5 = my / (k5 + 1.0); + /* recurrence constants r(k)=p(k)/p(k-1) at k = k1, k2, k4+1, k5+1 */ + r1 = my / k1; + r2 = my / k2; + r4 = my / (k4 + 1.0); + r5 = my / (k5 + 1.0); - /* reciprocal values of the scale parameters of exp. tail envelope */ - ll = std::log (r1); /* expon. tail left */ - lr = -std::log (r5); /* expon. tail right*/ + /* reciprocal values of the scale parameters of exp. tail envelope */ + ll = std::log (r1); /* expon. tail left */ + lr = -std::log (r5); /* expon. tail right*/ - /* Poisson constants, necessary for computing function values f(k) */ - l_my = std::log (my); - c_pm = m * l_my - flogfak (m); + /* Poisson constants, necessary for computing function values f(k) */ + l_my = std::log (my); + c_pm = m * l_my - flogfak (m); - /* function values f(k) = p(k)/p(m) at k = k2, k4, k1, k5 */ - f2 = f (k2, l_my, c_pm); - f4 = f (k4, l_my, c_pm); - f1 = f (k1, l_my, c_pm); - f5 = f (k5, l_my, c_pm); + /* function values f(k) = p(k)/p(m) at k = k2, k4, k1, k5 */ + f2 = f (k2, l_my, c_pm); + f4 = f (k4, l_my, c_pm); + f1 = f (k1, l_my, c_pm); + f5 = f (k5, l_my, c_pm); - /* area of the two centre and the two exponential tail regions */ - /* area of the two immediate acceptance regions between k2, k4 */ - p1 = f2 * (dl + 1.0); /* immed. left */ - p2 = f2 * dl + p1; /* centre left */ - p3 = f4 * (dr + 1.0) + p2; /* immed. right */ - p4 = f4 * dr + p3; /* centre right */ - p5 = f1 / ll + p4; /* exp. tail left */ - p6 = f5 / lr + p5; /* exp. tail right*/ - } + /* area of the two centre and the two exponential tail regions */ + /* area of the two immediate acceptance regions between k2, k4 */ + p1 = f2 * (dl + 1.0); /* immed. left */ + p2 = f2 * dl + p1; /* centre left */ + p3 = f4 * (dr + 1.0) + p2; /* immed. right */ + p4 = f4 * dr + p3; /* centre right */ + p5 = f1 / ll + p4; /* exp. tail left */ + p6 = f5 / lr + p5; /* exp. tail right*/ + } - for (;;) - { - /* generate uniform number U -- U(0, p6) */ - /* case distinction corresponding to U */ - if ((U = rand_uniform () * p6) < p2) - { /* centre left */ + for (;;) + { + /* generate uniform number U -- U(0, p6) */ + /* case distinction corresponding to U */ + if ((U = rand_uniform () * p6) < p2) + { + /* centre left */ - /* immediate acceptance region - R2 = [k2, m) *[0, f2), X = k2, ... m -1 */ - if ((V = U - p1) < 0.0) return (k2 + std::floor (U/f2)); - /* immediate acceptance region - R1 = [k1, k2)*[0, f1), X = k1, ... k2-1 */ - if ((W = V / dl) < f1 ) return (k1 + std::floor (V/f1)); + /* immediate acceptance region + R2 = [k2, m) *[0, f2), X = k2, ... m -1 */ + if ((V = U - p1) < 0.0) return (k2 + std::floor (U/f2)); + /* immediate acceptance region + R1 = [k1, k2)*[0, f1), X = k1, ... k2-1 */ + if ((W = V / dl) < f1 ) return (k1 + std::floor (V/f1)); - /* computation of candidate X < k2, and its counterpart Y > k2 */ - /* either squeeze-acceptance of X or acceptance-rejection of Y */ - Dk = std::floor (dl * rand_uniform ()) + 1.0; - if (W <= f2 - Dk * (f2 - f2/r2)) - { /* quick accept of */ - return (k2 - Dk); /* X = k2 - Dk */ - } - if ((V = f2 + f2 - W) < 1.0) - { /* quick reject of Y*/ - Y = k2 + Dk; - if (V <= f2 + Dk * (1.0 - f2)/(dl + 1.0)) - { /* quick accept of */ - return (Y); /* Y = k2 + Dk */ - } - if (V <= f (Y, l_my, c_pm)) return (Y); /* final accept of Y*/ - } - X = k2 - Dk; - } - else if (U < p4) - { /* centre right */ - /* immediate acceptance region - R3 = [m, k4+1)*[0, f4), X = m, ... k4 */ - if ((V = U - p3) < 0.0) return (k4 - std::floor ((U - p2)/f4)); - /* immediate acceptance region - R4 = [k4+1, k5+1)*[0, f5) */ - if ((W = V / dr) < f5 ) return (k5 - std::floor (V/f5)); + /* computation of candidate X < k2, and its counterpart Y > k2 */ + /* either squeeze-acceptance of X or acceptance-rejection of Y */ + Dk = std::floor (dl * rand_uniform ()) + 1.0; + if (W <= f2 - Dk * (f2 - f2/r2)) + { + /* quick accept of */ + return (k2 - Dk); /* X = k2 - Dk */ + } + if ((V = f2 + f2 - W) < 1.0) + { + /* quick reject of Y*/ + Y = k2 + Dk; + if (V <= f2 + Dk * (1.0 - f2)/(dl + 1.0)) + { + /* quick accept of */ + return (Y); /* Y = k2 + Dk */ + } + if (V <= f (Y, l_my, c_pm)) return (Y); /* final accept of Y*/ + } + X = k2 - Dk; + } + else if (U < p4) + { + /* centre right */ + /* immediate acceptance region + R3 = [m, k4+1)*[0, f4), X = m, ... k4 */ + if ((V = U - p3) < 0.0) return (k4 - std::floor ((U - p2)/f4)); + /* immediate acceptance region + R4 = [k4+1, k5+1)*[0, f5) */ + if ((W = V / dr) < f5 ) return (k5 - std::floor (V/f5)); - /* computation of candidate X > k4, and its counterpart Y < k4 */ - /* either squeeze-acceptance of X or acceptance-rejection of Y */ - Dk = std::floor (dr * rand_uniform ()) + 1.0; - if (W <= f4 - Dk * (f4 - f4*r4)) - { /* quick accept of */ - return (k4 + Dk); /* X = k4 + Dk */ - } - if ((V = f4 + f4 - W) < 1.0) - { /* quick reject of Y*/ - Y = k4 - Dk; - if (V <= f4 + Dk * (1.0 - f4)/ dr) - { /* quick accept of */ - return (Y); /* Y = k4 - Dk */ - } - if (V <= f (Y, l_my, c_pm)) return (Y); /* final accept of Y*/ - } - X = k4 + Dk; - } - else - { - W = rand_uniform (); - if (U < p5) - { /* expon. tail left */ - Dk = std::floor (1.0 - std::log (W)/ll); - if ((X = k1 - Dk) < 0L) continue; /* 0 <= X <= k1 - 1 */ - W *= (U - p4) * ll; /* W -- U(0, h(x)) */ - if (W <= f1 - Dk * (f1 - f1/r1)) - return (X); /* quick accept of X*/ - } - else - { /* expon. tail right*/ - Dk = std::floor (1.0 - std::log (W)/lr); - X = k5 + Dk; /* X >= k5 + 1 */ - W *= (U - p5) * lr; /* W -- U(0, h(x)) */ - if (W <= f5 - Dk * (f5 - f5*r5)) - return (X); /* quick accept of X*/ - } - } + /* computation of candidate X > k4, and its counterpart Y < k4 */ + /* either squeeze-acceptance of X or acceptance-rejection of Y */ + Dk = std::floor (dr * rand_uniform ()) + 1.0; + if (W <= f4 - Dk * (f4 - f4*r4)) + { + /* quick accept of */ + return (k4 + Dk); /* X = k4 + Dk */ + } + if ((V = f4 + f4 - W) < 1.0) + { + /* quick reject of Y*/ + Y = k4 - Dk; + if (V <= f4 + Dk * (1.0 - f4)/ dr) + { + /* quick accept of */ + return (Y); /* Y = k4 - Dk */ + } + if (V <= f (Y, l_my, c_pm)) return (Y); /* final accept of Y*/ + } + X = k4 + Dk; + } + else + { + W = rand_uniform (); + if (U < p5) + { + /* expon. tail left */ + Dk = std::floor (1.0 - std::log (W)/ll); + if ((X = k1 - Dk) < 0L) continue; /* 0 <= X <= k1 - 1 */ + W *= (U - p4) * ll; /* W -- U(0, h(x)) */ + if (W <= f1 - Dk * (f1 - f1/r1)) + return (X); /* quick accept of X*/ + } + else + { + /* expon. tail right*/ + Dk = std::floor (1.0 - std::log (W)/lr); + X = k5 + Dk; /* X >= k5 + 1 */ + W *= (U - p5) * lr; /* W -- U(0, h(x)) */ + if (W <= f5 - Dk * (f5 - f5*r5)) + return (X); /* quick accept of X*/ + } + } - /* acceptance-rejection test of candidate X from the original area */ - /* test, whether W <= f(k), with W = U*h(x) and U -- U(0, 1)*/ - /* log f(X) = (X - m)*log(my) - log X! + log m! */ - if (std::log (W) <= X * l_my - flogfak (X) - c_pm) return (X); - } - } - /* ---- pprsc.c end ------ */ + /* acceptance-rejection test of candidate X from the original area */ + /* test, whether W <= f(k), with W = U*h(x) and U -- U(0, 1)*/ + /* log f(X) = (X - m)*log(my) - log X! + log m! */ + if (std::log (W) <= X * l_my - flogfak (X) - c_pm) return (X); + } +} +/* ---- pprsc.c end ------ */ - /* The remainder of the file is by Paul Kienzle */ +/* The remainder of the file is by Paul Kienzle */ - /* Table size is predicated on the maximum value of lambda - * we want to store in the table, and the maximum value of - * returned by the uniform random number generator on [0,1). - * With lambda==10 and u_max = 1 - 1/(2^32+1), we - * have poisson_pdf(lambda,36) < 1-u_max. If instead our - * generator uses more bits of mantissa or returns a value - * in the range [0,1], then for lambda==10 we need a table - * size of 46 instead. For long doubles, the table size - * will need to be longer still. */ +/* Table size is predicated on the maximum value of lambda + * we want to store in the table, and the maximum value of + * returned by the uniform random number generator on [0,1). + * With lambda==10 and u_max = 1 - 1/(2^32+1), we + * have poisson_pdf(lambda,36) < 1-u_max. If instead our + * generator uses more bits of mantissa or returns a value + * in the range [0,1], then for lambda==10 we need a table + * size of 46 instead. For long doubles, the table size + * will need to be longer still. */ #define TABLESIZE 46 - /* Given uniform u, find x such that CDF(L,x)==u. Return x. */ +/* Given uniform u, find x such that CDF(L,x)==u. Return x. */ - template - static void - poisson_cdf_lookup (double lambda, T *p, std::size_t n) - { - double t[TABLESIZE]; +template +static void +poisson_cdf_lookup (double lambda, T *p, std::size_t n) +{ + double t[TABLESIZE]; - /* Precompute the table for the u up to and including 0.458. - * We will almost certainly need it. */ - int intlambda = static_cast (std::floor (lambda)); - double P; - int tableidx; - std::size_t i = n; + /* Precompute the table for the u up to and including 0.458. + * We will almost certainly need it. */ + int intlambda = static_cast (std::floor (lambda)); + double P; + int tableidx; + std::size_t i = n; - t[0] = P = exp (-lambda); - for (tableidx = 1; tableidx <= intlambda; tableidx++) - { - P = P*lambda/static_cast (tableidx); - t[tableidx] = t[tableidx-1] + P; - } + t[0] = P = exp (-lambda); + for (tableidx = 1; tableidx <= intlambda; tableidx++) + { + P = P*lambda/static_cast (tableidx); + t[tableidx] = t[tableidx-1] + P; + } - while (i-- > 0) - { - double u = rand_uniform (); + while (i-- > 0) + { + double u = rand_uniform (); - /* If u > 0.458 we know we can jump to floor(lambda) before - * comparing (this observation is based on Stadlober's winrand - * code). For lambda >= 1, this will be a win. Lambda < 1 - * is already fast, so adding an extra comparison is not a - * problem. */ - int k = (u > 0.458 ? intlambda : 0); + /* If u > 0.458 we know we can jump to floor(lambda) before + * comparing (this observation is based on Stadlober's winrand + * code). For lambda >= 1, this will be a win. Lambda < 1 + * is already fast, so adding an extra comparison is not a + * problem. */ + int k = (u > 0.458 ? intlambda : 0); - /* We aren't using a for loop here because when we find the - * right k we want to jump to the next iteration of the - * outer loop, and the continue statement will only work for - * the inner loop. */ - nextk: - if (u <= t[k]) - { - p[i] = static_cast (k); - continue; - } - if (++k < tableidx) - goto nextk; + /* We aren't using a for loop here because when we find the + * right k we want to jump to the next iteration of the + * outer loop, and the continue statement will only work for + * the inner loop. */ + nextk: + if (u <= t[k]) + { + p[i] = static_cast (k); + continue; + } + if (++k < tableidx) + goto nextk; - /* We only need high values of the table very rarely so we - * don't automatically compute the entire table. */ - while (tableidx < TABLESIZE) - { - P = P*lambda/static_cast (tableidx); - t[tableidx] = t[tableidx-1] + P; - /* Make sure we converge to 1.0 just in case u is uniform - * on [0,1] rather than [0,1). */ - if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0; - tableidx++; - if (u <= t[tableidx-1]) break; - } + /* We only need high values of the table very rarely so we + * don't automatically compute the entire table. */ + while (tableidx < TABLESIZE) + { + P = P*lambda/static_cast (tableidx); + t[tableidx] = t[tableidx-1] + P; + /* Make sure we converge to 1.0 just in case u is uniform + * on [0,1] rather than [0,1). */ + if (t[tableidx] == t[tableidx-1]) t[tableidx] = 1.0; + tableidx++; + if (u <= t[tableidx-1]) break; + } - /* We are assuming that the table size is big enough here. - * This should be true even if rand_uniform is returning values in - * the range [0,1] rather than [0,1). */ - p[i] = static_cast (tableidx-1); - } - } + /* We are assuming that the table size is big enough here. + * This should be true even if rand_uniform is returning values in + * the range [0,1] rather than [0,1). */ + p[i] = static_cast (tableidx-1); + } +} - /* From Press, et al., Numerical Recipes */ - template - static void - poisson_rejection (double lambda, T *p, std::size_t n) - { - double sq = std::sqrt (2.0*lambda); - double alxm = std::log (lambda); - double g = lambda*alxm - xlgamma (lambda+1.0); - std::size_t i; +/* From Press, et al., Numerical Recipes */ +template +static void +poisson_rejection (double lambda, T *p, std::size_t n) +{ + double sq = std::sqrt (2.0*lambda); + double alxm = std::log (lambda); + double g = lambda*alxm - xlgamma (lambda+1.0); + std::size_t i; - for (i = 0; i < n; i++) - { - double y, em, t; - do - { - do - { - y = tan (M_PI*rand_uniform ()); - em = sq * y + lambda; - } while (em < 0.0); - em = std::floor (em); - t = 0.9*(1.0+y*y)*exp (em*alxm-flogfak (em)-g); - } while (rand_uniform () > t); - p[i] = em; - } - } + for (i = 0; i < n; i++) + { + double y, em, t; + do + { + do + { + y = tan (M_PI*rand_uniform ()); + em = sq * y + lambda; + } + while (em < 0.0); + em = std::floor (em); + t = 0.9*(1.0+y*y)* exp (em*alxm-flogfak (em)-g); + } + while (rand_uniform () > t); + p[i] = em; + } +} - /* The cutoff of L <= 1e8 in the following two functions before using - * the normal approximation is based on: - * > L=1e8; x=floor(linspace(0,2*L,1000)); - * > max(abs(normal_pdf(x,L,L)-poisson_pdf(x,L))) - * ans = 1.1376e-28 - * For L=1e7, the max is around 1e-9, which is within the step size of - * rand_uniform. For L>1e10 the pprsc function breaks down, as I saw - * from the histogram of a large sample, so 1e8 is both small enough - * and large enough. */ +/* The cutoff of L <= 1e8 in the following two functions before using + * the normal approximation is based on: + * > L=1e8; x=floor(linspace(0,2*L,1000)); + * > max(abs(normal_pdf(x,L,L)-poisson_pdf(x,L))) + * ans = 1.1376e-28 + * For L=1e7, the max is around 1e-9, which is within the step size of + * rand_uniform. For L>1e10 the pprsc function breaks down, as I saw + * from the histogram of a large sample, so 1e8 is both small enough + * and large enough. */ - /* Generate a set of poisson numbers with the same distribution */ - template void rand_poisson (T L_arg, octave_idx_type n, T *p) - { - double L = L_arg; - octave_idx_type i; - if (L < 0.0 || lo_ieee_isinf (L)) - { - for (i=0; i::NaN (); - } - else if (L <= 10.0) - { - poisson_cdf_lookup (L, p, n); - } - else if (L <= 1e8) - { - for (i=0; i () * sqrtL + L + 0.5); - if (p[i] < 0.0) - p[i] = 0.0; /* will probably never happen */ - } - } - } +/* Generate a set of poisson numbers with the same distribution */ +template void rand_poisson (T L_arg, octave_idx_type n, T *p) +{ + double L = L_arg; + octave_idx_type i; + if (L < 0.0 || lo_ieee_isinf (L)) + { + for (i=0; i::NaN (); + } + else if (L <= 10.0) + { + poisson_cdf_lookup (L, p, n); + } + else if (L <= 1e8) + { + for (i=0; i () * sqrtL + L + 0.5); + if (p[i] < 0.0) + p[i] = 0.0; /* will probably never happen */ + } + } +} - template void rand_poisson (double, octave_idx_type, double *); - template void rand_poisson (float, octave_idx_type, float *); +template void rand_poisson (double, octave_idx_type, double *); +template void rand_poisson (float, octave_idx_type, float *); - /* Generate one poisson variate */ - template T rand_poisson (T L_arg) - { - double L = L_arg; - T ret; - if (L < 0.0) ret = numeric_limits::NaN (); - else if (L <= 12.0) - { - /* From Press, et al. Numerical recipes */ - double g = exp (-L); - int em = -1; - double t = 1.0; - do - { - ++em; - t *= rand_uniform (); - } while (t > g); - ret = em; - } - else if (L <= 1e8) - { - /* numerical recipes */ - poisson_rejection (L, &ret, 1); - } - else if (lo_ieee_isinf (L)) - { - /* FIXME: R uses NaN, but the normal approximation suggests that - * limit should be Inf. Which is correct? */ - ret = numeric_limits::NaN (); - } - else - { - /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */ - ret = std::floor (rand_normal () * std::sqrt (L) + L + 0.5); - if (ret < 0.0) ret = 0.0; /* will probably never happen */ - } - return ret; - } +/* Generate one poisson variate */ +template T rand_poisson (T L_arg) +{ + double L = L_arg; + T ret; + if (L < 0.0) ret = numeric_limits::NaN (); + else if (L <= 12.0) + { + /* From Press, et al. Numerical recipes */ + double g = exp (-L); + int em = -1; + double t = 1.0; + do + { + ++em; + t *= rand_uniform (); + } + while (t > g); + ret = em; + } + else if (L <= 1e8) + { + /* numerical recipes */ + poisson_rejection (L, &ret, 1); + } + else if (lo_ieee_isinf (L)) + { + /* FIXME: R uses NaN, but the normal approximation suggests that + * limit should be Inf. Which is correct? */ + ret = numeric_limits::NaN (); + } + else + { + /* normal approximation: from Phys. Rev. D (1994) v50 p1284 */ + ret = std::floor (rand_normal () * std::sqrt (L) + L + 0.5); + if (ret < 0.0) ret = 0.0; /* will probably never happen */ + } + return ret; +} - template OCTAVE_API double rand_poisson (double); - template OCTAVE_API float rand_poisson (float); +template OCTAVE_API double rand_poisson (double); +template OCTAVE_API float rand_poisson (float); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/randpoisson.h --- a/liboctave/numeric/randpoisson.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/randpoisson.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,9 +33,9 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template OCTAVE_API void rand_poisson (T L, octave_idx_type n, T *p); +template OCTAVE_API void rand_poisson (T L, octave_idx_type n, T *p); - template OCTAVE_API T rand_poisson (T L); +template OCTAVE_API T rand_poisson (T L); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/schur.cc --- a/liboctave/numeric/schur.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/schur.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,471 +41,471 @@ OCTAVE_BEGIN_NAMESPACE(math) - // For real types. +// For real types. - static F77_INT - select_ana (const double& a, const double&) - { - return (a < 0.0); - } +static F77_INT +select_ana (const double& a, const double&) +{ + return (a < 0.0); +} + +static F77_INT +select_dig (const double& a, const double& b) +{ + return (hypot (a, b) < 1.0); +} - static F77_INT - select_dig (const double& a, const double& b) - { - return (hypot (a, b) < 1.0); - } +static F77_INT +select_ana (const float& a, const float&) +{ + return (a < 0.0); +} - static F77_INT - select_ana (const float& a, const float&) - { - return (a < 0.0); - } +static F77_INT +select_dig (const float& a, const float& b) +{ + return (hypot (a, b) < 1.0); +} - static F77_INT - select_dig (const float& a, const float& b) - { - return (hypot (a, b) < 1.0); - } +// For complex types. + +static F77_INT +select_ana (const F77_DBLE_CMPLX& a_arg) +{ + const Complex a = reinterpret_cast (a_arg); + return a.real () < 0.0; +} - // For complex types. +static F77_INT +select_dig (const F77_DBLE_CMPLX& a_arg) +{ + const Complex& a = reinterpret_cast (a_arg); + return (abs (a) < 1.0); +} + +static F77_INT +select_ana (const F77_CMPLX& a_arg) +{ + const FloatComplex& a = reinterpret_cast (a_arg); + return a.real () < 0.0; +} - static F77_INT - select_ana (const F77_DBLE_CMPLX& a_arg) - { - const Complex a = reinterpret_cast (a_arg); - return a.real () < 0.0; - } +static F77_INT +select_dig (const F77_CMPLX& a_arg) +{ + const FloatComplex& a = reinterpret_cast (a_arg); + return (abs (a) < 1.0); +} - static F77_INT - select_dig (const F77_DBLE_CMPLX& a_arg) +template <> +OCTAVE_API F77_INT +schur::init (const Matrix& a, const std::string& ord, + bool calc_unitary) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("schur: requires square matrix"); + + if (a_nr == 0) { - const Complex& a = reinterpret_cast (a_arg); - return (abs (a) < 1.0); - } - - static F77_INT - select_ana (const F77_CMPLX& a_arg) - { - const FloatComplex& a = reinterpret_cast (a_arg); - return a.real () < 0.0; - } - - static F77_INT - select_dig (const F77_CMPLX& a_arg) - { - const FloatComplex& a = reinterpret_cast (a_arg); - return (abs (a) < 1.0); + m_schur_mat.clear (); + m_unitary_schur_mat.clear (); + return 0; } - template <> - OCTAVE_API F77_INT - schur::init (const Matrix& a, const std::string& ord, - bool calc_unitary) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); + // Workspace requirements may need to be fixed if any of the + // following change. - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("schur: requires square matrix"); - - if (a_nr == 0) - { - m_schur_mat.clear (); - m_unitary_schur_mat.clear (); - return 0; - } - - // Workspace requirements may need to be fixed if any of the - // following change. + char jobvs; + char sense = 'N'; + char sort = 'N'; - char jobvs; - char sense = 'N'; - char sort = 'N'; - - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; - char ord_char = (ord.empty () ? 'U' : ord[0]); - - if (ord_char == 'A' || ord_char == 'D' - || ord_char == 'a' || ord_char == 'd') - sort = 'S'; + char ord_char = (ord.empty () ? 'U' : ord[0]); - volatile double_selector selector = nullptr; - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; + if (ord_char == 'A' || ord_char == 'D' + || ord_char == 'a' || ord_char == 'd') + sort = 'S'; - F77_INT n = a_nc; - F77_INT lwork = 8 * n; - F77_INT liwork = 1; - F77_INT info; - F77_INT sdim; - double rconde; - double rcondv; - - m_schur_mat = a; - - if (calc_unitary) - m_unitary_schur_mat.clear (n, n); - - double *s = m_schur_mat.fortran_vec (); - double *q = m_unitary_schur_mat.fortran_vec (); - - Array wr (dim_vector (n, 1)); - double *pwr = wr.fortran_vec (); + volatile double_selector selector = nullptr; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; - Array wi (dim_vector (n, 1)); - double *pwi = wi.fortran_vec (); - - Array work (dim_vector (lwork, 1)); - double *pwork = work.fortran_vec (); - - // BWORK is not referenced for the non-ordered Schur routine. - F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - F77_INT *pbwork = bwork.fortran_vec (); + F77_INT n = a_nc; + F77_INT lwork = 8 * n; + F77_INT liwork = 1; + F77_INT info; + F77_INT sdim; + double rconde; + double rcondv; - Array iwork (dim_vector (liwork, 1)); - F77_INT *piwork = iwork.fortran_vec (); + m_schur_mat = a; + + if (calc_unitary) + m_unitary_schur_mat.clear (n, n); - F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, - pwork, lwork, piwork, liwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + double *s = m_schur_mat.fortran_vec (); + double *q = m_unitary_schur_mat.fortran_vec (); + + Array wr (dim_vector (n, 1)); + double *pwr = wr.fortran_vec (); - return info; - } + Array wi (dim_vector (n, 1)); + double *pwi = wi.fortran_vec (); - template <> - OCTAVE_API F77_INT - schur::init (const FloatMatrix& a, const std::string& ord, - bool calc_unitary) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("SCHUR requires square matrix"); - - if (a_nr == 0) - { - m_schur_mat.clear (); - m_unitary_schur_mat.clear (); - return 0; - } + Array work (dim_vector (lwork, 1)); + double *pwork = work.fortran_vec (); - // Workspace requirements may need to be fixed if any of the - // following change. - - char jobvs; - char sense = 'N'; - char sort = 'N'; - - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; + // BWORK is not referenced for the non-ordered Schur routine. + F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + F77_INT *pbwork = bwork.fortran_vec (); - char ord_char = (ord.empty () ? 'U' : ord[0]); - - if (ord_char == 'A' || ord_char == 'D' - || ord_char == 'a' || ord_char == 'd') - sort = 'S'; - - volatile float_selector selector = nullptr; - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; + Array iwork (dim_vector (liwork, 1)); + F77_INT *piwork = iwork.fortran_vec (); - F77_INT n = a_nc; - F77_INT lwork = 8 * n; - F77_INT liwork = 1; - F77_INT info; - F77_INT sdim; - float rconde; - float rcondv; - - m_schur_mat = a; + F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, + pwork, lwork, piwork, liwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - if (calc_unitary) - m_unitary_schur_mat.clear (n, n); - - float *s = m_schur_mat.fortran_vec (); - float *q = m_unitary_schur_mat.fortran_vec (); - - Array wr (dim_vector (n, 1)); - float *pwr = wr.fortran_vec (); - - Array wi (dim_vector (n, 1)); - float *pwi = wi.fortran_vec (); + return info; +} - Array work (dim_vector (lwork, 1)); - float *pwork = work.fortran_vec (); - - // BWORK is not referenced for the non-ordered Schur routine. - F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - F77_INT *pbwork = bwork.fortran_vec (); - - Array iwork (dim_vector (liwork, 1)); - F77_INT *piwork = iwork.fortran_vec (); +template <> +OCTAVE_API F77_INT +schur::init (const FloatMatrix& a, const std::string& ord, + bool calc_unitary) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); - F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, - pwork, lwork, piwork, liwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("SCHUR requires square matrix"); - return info; + if (a_nr == 0) + { + m_schur_mat.clear (); + m_unitary_schur_mat.clear (); + return 0; } - template <> - OCTAVE_API F77_INT - schur::init (const ComplexMatrix& a, const std::string& ord, - bool calc_unitary) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); + // Workspace requirements may need to be fixed if any of the + // following change. - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("SCHUR requires square matrix"); + char jobvs; + char sense = 'N'; + char sort = 'N'; - if (a_nr == 0) - { - m_schur_mat.clear (); - m_unitary_schur_mat.clear (); - return 0; - } + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; - // Workspace requirements may need to be fixed if any of the - // following change. + char ord_char = (ord.empty () ? 'U' : ord[0]); - char jobvs; - char sense = 'N'; - char sort = 'N'; + if (ord_char == 'A' || ord_char == 'D' + || ord_char == 'a' || ord_char == 'd') + sort = 'S'; - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; - - char ord_char = (ord.empty () ? 'U' : ord[0]); - - if (ord_char == 'A' || ord_char == 'D' - || ord_char == 'a' || ord_char == 'd') - sort = 'S'; + volatile float_selector selector = nullptr; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; - volatile complex_selector selector = nullptr; - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; + F77_INT n = a_nc; + F77_INT lwork = 8 * n; + F77_INT liwork = 1; + F77_INT info; + F77_INT sdim; + float rconde; + float rcondv; - F77_INT n = a_nc; - F77_INT lwork = 8 * n; - F77_INT info; - F77_INT sdim; - double rconde; - double rcondv; + m_schur_mat = a; + + if (calc_unitary) + m_unitary_schur_mat.clear (n, n); - m_schur_mat = a; - if (calc_unitary) - m_unitary_schur_mat.clear (n, n); + float *s = m_schur_mat.fortran_vec (); + float *q = m_unitary_schur_mat.fortran_vec (); + + Array wr (dim_vector (n, 1)); + float *pwr = wr.fortran_vec (); - Complex *s = m_schur_mat.fortran_vec (); - Complex *q = m_unitary_schur_mat.fortran_vec (); + Array wi (dim_vector (n, 1)); + float *pwi = wi.fortran_vec (); - Array rwork (dim_vector (n, 1)); - double *prwork = rwork.fortran_vec (); + Array work (dim_vector (lwork, 1)); + float *pwork = work.fortran_vec (); - Array w (dim_vector (n, 1)); - Complex *pw = w.fortran_vec (); + // BWORK is not referenced for the non-ordered Schur routine. + F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + F77_INT *pbwork = bwork.fortran_vec (); - Array work (dim_vector (lwork, 1)); - Complex *pwork = work.fortran_vec (); - - // BWORK is not referenced for non-ordered Schur. - F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - F77_INT *pbwork = bwork.fortran_vec (); + Array iwork (dim_vector (liwork, 1)); + F77_INT *piwork = iwork.fortran_vec (); - F77_XFCN (zgeesx, ZGEESX, - (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, F77_DBLE_CMPLX_ARG (s), n, sdim, F77_DBLE_CMPLX_ARG (pw), - F77_DBLE_CMPLX_ARG (q), n, rconde, rcondv, - F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, s, n, sdim, pwr, pwi, q, n, rconde, rcondv, + pwork, lwork, piwork, liwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + return info; +} - return info; - } +template <> +OCTAVE_API F77_INT +schur::init (const ComplexMatrix& a, const std::string& ord, + bool calc_unitary) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); - template <> - OCTAVE_API schur - rsf2csf (const Matrix& s_arg, const Matrix& u_arg) + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("SCHUR requires square matrix"); + + if (a_nr == 0) { - ComplexMatrix s (s_arg); - ComplexMatrix u (u_arg); - - F77_INT n = to_f77_int (s.rows ()); - - if (s.columns () != n || u.rows () != n || u.columns () != n) - (*current_liboctave_error_handler) - ("rsf2csf: inconsistent matrix dimensions"); - - if (n > 0) - { - OCTAVE_LOCAL_BUFFER (double, c, n-1); - OCTAVE_LOCAL_BUFFER (double, sx, n-1); - - F77_XFCN (zrsf2csf, ZRSF2CSF, - (n, F77_DBLE_CMPLX_ARG (s.fortran_vec ()), - F77_DBLE_CMPLX_ARG (u.fortran_vec ()), c, sx)); - } - - return schur (s, u); + m_schur_mat.clear (); + m_unitary_schur_mat.clear (); + return 0; } - template <> - OCTAVE_API F77_INT - schur::init (const FloatComplexMatrix& a, - const std::string& ord, bool calc_unitary) - { - F77_INT a_nr = to_f77_int (a.rows ()); - F77_INT a_nc = to_f77_int (a.cols ()); + // Workspace requirements may need to be fixed if any of the + // following change. + + char jobvs; + char sense = 'N'; + char sort = 'N'; - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("SCHUR requires square matrix"); + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; - if (a_nr == 0) - { - m_schur_mat.clear (); - m_unitary_schur_mat.clear (); - return 0; - } + char ord_char = (ord.empty () ? 'U' : ord[0]); - // Workspace requirements may need to be fixed if any of the - // following change. + if (ord_char == 'A' || ord_char == 'D' + || ord_char == 'a' || ord_char == 'd') + sort = 'S'; - char jobvs; - char sense = 'N'; - char sort = 'N'; + volatile complex_selector selector = nullptr; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; - if (calc_unitary) - jobvs = 'V'; - else - jobvs = 'N'; + F77_INT n = a_nc; + F77_INT lwork = 8 * n; + F77_INT info; + F77_INT sdim; + double rconde; + double rcondv; - char ord_char = (ord.empty () ? 'U' : ord[0]); - - if (ord_char == 'A' || ord_char == 'D' - || ord_char == 'a' || ord_char == 'd') - sort = 'S'; + m_schur_mat = a; + if (calc_unitary) + m_unitary_schur_mat.clear (n, n); - volatile float_complex_selector selector = nullptr; - if (ord_char == 'A' || ord_char == 'a') - selector = select_ana; - else if (ord_char == 'D' || ord_char == 'd') - selector = select_dig; + Complex *s = m_schur_mat.fortran_vec (); + Complex *q = m_unitary_schur_mat.fortran_vec (); + + Array rwork (dim_vector (n, 1)); + double *prwork = rwork.fortran_vec (); + + Array w (dim_vector (n, 1)); + Complex *pw = w.fortran_vec (); - F77_INT n = a_nc; - F77_INT lwork = 8 * n; - F77_INT info; - F77_INT sdim; - float rconde; - float rcondv; + Array work (dim_vector (lwork, 1)); + Complex *pwork = work.fortran_vec (); + + // BWORK is not referenced for non-ordered Schur. + F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + F77_INT *pbwork = bwork.fortran_vec (); - m_schur_mat = a; - if (calc_unitary) - m_unitary_schur_mat.clear (n, n); - - FloatComplex *s = m_schur_mat.fortran_vec (); - FloatComplex *q = m_unitary_schur_mat.fortran_vec (); - - Array rwork (dim_vector (n, 1)); - float *prwork = rwork.fortran_vec (); - - Array w (dim_vector (n, 1)); - FloatComplex *pw = w.fortran_vec (); + F77_XFCN (zgeesx, ZGEESX, + (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, F77_DBLE_CMPLX_ARG (s), n, sdim, F77_DBLE_CMPLX_ARG (pw), + F77_DBLE_CMPLX_ARG (q), n, rconde, rcondv, + F77_DBLE_CMPLX_ARG (pwork), lwork, prwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); - Array work (dim_vector (lwork, 1)); - FloatComplex *pwork = work.fortran_vec (); + return info; +} - // BWORK is not referenced for non-ordered Schur. - F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; - Array bwork (dim_vector (ntmp, 1)); - F77_INT *pbwork = bwork.fortran_vec (); +template <> +OCTAVE_API schur +rsf2csf (const Matrix& s_arg, const Matrix& u_arg) +{ + ComplexMatrix s (s_arg); + ComplexMatrix u (u_arg); + + F77_INT n = to_f77_int (s.rows ()); - F77_XFCN (cgeesx, CGEESX, - (F77_CONST_CHAR_ARG2 (&jobvs, 1), - F77_CONST_CHAR_ARG2 (&sort, 1), - selector, - F77_CONST_CHAR_ARG2 (&sense, 1), - n, F77_CMPLX_ARG (s), n, sdim, F77_CMPLX_ARG (pw), - F77_CMPLX_ARG (q), n, - rconde, rcondv, - F77_CMPLX_ARG (pwork), lwork, prwork, pbwork, info - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1) - F77_CHAR_ARG_LEN (1))); + if (s.columns () != n || u.rows () != n || u.columns () != n) + (*current_liboctave_error_handler) + ("rsf2csf: inconsistent matrix dimensions"); - return info; + if (n > 0) + { + OCTAVE_LOCAL_BUFFER (double, c, n-1); + OCTAVE_LOCAL_BUFFER (double, sx, n-1); + + F77_XFCN (zrsf2csf, ZRSF2CSF, + (n, F77_DBLE_CMPLX_ARG (s.fortran_vec ()), + F77_DBLE_CMPLX_ARG (u.fortran_vec ()), c, sx)); } - template <> - OCTAVE_API schur - rsf2csf (const FloatMatrix& s_arg, - const FloatMatrix& u_arg) - { - FloatComplexMatrix s (s_arg); - FloatComplexMatrix u (u_arg); - - F77_INT n = to_f77_int (s.rows ()); + return schur (s, u); +} - if (s.columns () != n || u.rows () != n || u.columns () != n) - (*current_liboctave_error_handler) - ("rsf2csf: inconsistent matrix dimensions"); +template <> +OCTAVE_API F77_INT +schur::init (const FloatComplexMatrix& a, + const std::string& ord, bool calc_unitary) +{ + F77_INT a_nr = to_f77_int (a.rows ()); + F77_INT a_nc = to_f77_int (a.cols ()); - if (n > 0) - { - OCTAVE_LOCAL_BUFFER (float, c, n-1); - OCTAVE_LOCAL_BUFFER (float, sx, n-1); + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("SCHUR requires square matrix"); - F77_XFCN (crsf2csf, CRSF2CSF, - (n, F77_CMPLX_ARG (s.fortran_vec ()), - F77_CMPLX_ARG (u.fortran_vec ()), c, sx)); - } - - return schur (s, u); + if (a_nr == 0) + { + m_schur_mat.clear (); + m_unitary_schur_mat.clear (); + return 0; } - // Instantiations we need. + // Workspace requirements may need to be fixed if any of the + // following change. + + char jobvs; + char sense = 'N'; + char sort = 'N'; + + if (calc_unitary) + jobvs = 'V'; + else + jobvs = 'N'; + + char ord_char = (ord.empty () ? 'U' : ord[0]); + + if (ord_char == 'A' || ord_char == 'D' + || ord_char == 'a' || ord_char == 'd') + sort = 'S'; + + volatile float_complex_selector selector = nullptr; + if (ord_char == 'A' || ord_char == 'a') + selector = select_ana; + else if (ord_char == 'D' || ord_char == 'd') + selector = select_dig; - template class schur; + F77_INT n = a_nc; + F77_INT lwork = 8 * n; + F77_INT info; + F77_INT sdim; + float rconde; + float rcondv; + + m_schur_mat = a; + if (calc_unitary) + m_unitary_schur_mat.clear (n, n); + + FloatComplex *s = m_schur_mat.fortran_vec (); + FloatComplex *q = m_unitary_schur_mat.fortran_vec (); + + Array rwork (dim_vector (n, 1)); + float *prwork = rwork.fortran_vec (); + + Array w (dim_vector (n, 1)); + FloatComplex *pw = w.fortran_vec (); + + Array work (dim_vector (lwork, 1)); + FloatComplex *pwork = work.fortran_vec (); + + // BWORK is not referenced for non-ordered Schur. + F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n; + Array bwork (dim_vector (ntmp, 1)); + F77_INT *pbwork = bwork.fortran_vec (); - template class schur; + F77_XFCN (cgeesx, CGEESX, + (F77_CONST_CHAR_ARG2 (&jobvs, 1), + F77_CONST_CHAR_ARG2 (&sort, 1), + selector, + F77_CONST_CHAR_ARG2 (&sense, 1), + n, F77_CMPLX_ARG (s), n, sdim, F77_CMPLX_ARG (pw), + F77_CMPLX_ARG (q), n, + rconde, rcondv, + F77_CMPLX_ARG (pwork), lwork, prwork, pbwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + + return info; +} + +template <> +OCTAVE_API schur +rsf2csf (const FloatMatrix& s_arg, + const FloatMatrix& u_arg) +{ + FloatComplexMatrix s (s_arg); + FloatComplexMatrix u (u_arg); + + F77_INT n = to_f77_int (s.rows ()); - template class schur; + if (s.columns () != n || u.rows () != n || u.columns () != n) + (*current_liboctave_error_handler) + ("rsf2csf: inconsistent matrix dimensions"); + + if (n > 0) + { + OCTAVE_LOCAL_BUFFER (float, c, n-1); + OCTAVE_LOCAL_BUFFER (float, sx, n-1); - template class schur; + F77_XFCN (crsf2csf, CRSF2CSF, + (n, F77_CMPLX_ARG (s.fortran_vec ()), + F77_CMPLX_ARG (u.fortran_vec ()), c, sx)); + } + + return schur (s, u); +} + +// Instantiations we need. + +template class schur; + +template class schur; + +template class schur; + +template class schur; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/schur.h --- a/liboctave/numeric/schur.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/schur.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,69 +41,69 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - schur - { - public: +template +class +schur +{ +public: - schur (void) : m_schur_mat (), m_unitary_schur_mat () { } + schur (void) : m_schur_mat (), m_unitary_schur_mat () { } + + schur (const T& a, const std::string& ord, bool calc_unitary = true) + : m_schur_mat (), m_unitary_schur_mat () + { + init (a, ord, calc_unitary); + } - schur (const T& a, const std::string& ord, bool calc_unitary = true) - : m_schur_mat (), m_unitary_schur_mat () - { - init (a, ord, calc_unitary); - } + schur (const T& a, const std::string& ord, octave_f77_int_type& info, + bool calc_unitary = true) + : m_schur_mat (), m_unitary_schur_mat () + { + info = init (a, ord, calc_unitary); + } - schur (const T& a, const std::string& ord, octave_f77_int_type& info, - bool calc_unitary = true) - : m_schur_mat (), m_unitary_schur_mat () + // This one should really be protected or private but we need it in + // rsf2csf and I don't see how to make that function a friend of + // this class. + schur (const T& s, const T& u) : m_schur_mat (s), m_unitary_schur_mat (u) + { } + + schur (const schur& a) + : m_schur_mat (a.m_schur_mat), + m_unitary_schur_mat (a.m_unitary_schur_mat) + { } + + schur& operator = (const schur& a) + { + if (this != &a) { - info = init (a, ord, calc_unitary); + m_schur_mat = a.m_schur_mat; + m_unitary_schur_mat = a.m_unitary_schur_mat; } - // This one should really be protected or private but we need it in - // rsf2csf and I don't see how to make that function a friend of - // this class. - schur (const T& s, const T& u) : m_schur_mat (s), m_unitary_schur_mat (u) - { } + return *this; + } + + ~schur (void) = default; - schur (const schur& a) - : m_schur_mat (a.m_schur_mat), - m_unitary_schur_mat (a.m_unitary_schur_mat) - { } + T schur_matrix (void) const { return m_schur_mat; } - schur& operator = (const schur& a) - { - if (this != &a) - { - m_schur_mat = a.m_schur_mat; - m_unitary_schur_mat = a.m_unitary_schur_mat; - } + T unitary_schur_matrix (void) const { return m_unitary_schur_mat; } + +protected: - return *this; - } - - ~schur (void) = default; +private: - T schur_matrix (void) const { return m_schur_mat; } - - T unitary_schur_matrix (void) const { return m_unitary_schur_mat; } - - protected: + T m_schur_mat; + T m_unitary_schur_mat; - private: - - T m_schur_mat; - T m_unitary_schur_mat; + OCTAVE_API octave_f77_int_type + init (const T& a, const std::string& ord, bool calc_unitary); +}; - OCTAVE_API octave_f77_int_type - init (const T& a, const std::string& ord, bool calc_unitary); - }; - - template - extern OCTAVE_API schur - rsf2csf (const AT& s, const AT& u); +template +extern OCTAVE_API schur +rsf2csf (const AT& s, const AT& u); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/sparse-chol.cc --- a/liboctave/numeric/sparse-chol.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/sparse-chol.cc Thu Dec 01 20:05:44 2022 -0800 @@ -45,528 +45,528 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class sparse_chol::sparse_chol_rep - { - public: +template +class sparse_chol::sparse_chol_rep +{ +public: - sparse_chol_rep (void) - : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0) + sparse_chol_rep (void) + : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0) #if defined (HAVE_CHOLMOD) - , m_L (nullptr), m_common () + , m_L (nullptr), m_common () #endif - { } + { } - sparse_chol_rep (const chol_type& a, bool natural, bool force) - : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0) + sparse_chol_rep (const chol_type& a, bool natural, bool force) + : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0) #if defined (HAVE_CHOLMOD) - , m_L (nullptr), m_common () + , m_L (nullptr), m_common () #endif - { - init (a, natural, force); - } + { + init (a, natural, force); + } - sparse_chol_rep (const chol_type& a, octave_idx_type& info, - bool natural, bool force) - : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0) + sparse_chol_rep (const chol_type& a, octave_idx_type& info, + bool natural, bool force) + : m_is_pd (false), m_minor_p (0), m_perm (), m_rcond (0) #if defined (HAVE_CHOLMOD) - , m_L (nullptr), m_common () + , m_L (nullptr), m_common () #endif - { - info = init (a, natural, force); - } + { + info = init (a, natural, force); + } - // No copying! + // No copying! - sparse_chol_rep (const sparse_chol_rep&) = delete; + sparse_chol_rep (const sparse_chol_rep&) = delete; - sparse_chol_rep& operator = (const sparse_chol_rep&) = delete; + sparse_chol_rep& operator = (const sparse_chol_rep&) = delete; - ~sparse_chol_rep (void) - { + ~sparse_chol_rep (void) + { #if defined (HAVE_CHOLMOD) - if (m_L) - CHOLMOD_NAME (free_sparse) (&m_L, &m_common); + if (m_L) + CHOLMOD_NAME (free_sparse) (&m_L, &m_common); - CHOLMOD_NAME(finish) (&m_common); + CHOLMOD_NAME(finish) (&m_common); #endif - } + } #if defined (HAVE_CHOLMOD) - cholmod_sparse * L (void) const - { - return m_L; - } + cholmod_sparse * L (void) const + { + return m_L; + } #endif - octave_idx_type P (void) const - { + octave_idx_type P (void) const + { #if defined (HAVE_CHOLMOD) - return (m_minor_p == static_cast (m_L->ncol) ? - 0 : m_minor_p + 1); + return (m_minor_p == static_cast (m_L->ncol) ? + 0 : m_minor_p + 1); #else - return 0; + return 0; #endif - } + } - RowVector perm (void) const { return m_perm + 1; } + RowVector perm (void) const { return m_perm + 1; } - SparseMatrix Q (void) const; + SparseMatrix Q (void) const; - bool is_positive_definite (void) const { return m_is_pd; } + bool is_positive_definite (void) const { return m_is_pd; } - double rcond (void) const { return m_rcond; } + double rcond (void) const { return m_rcond; } - private: +private: - bool m_is_pd; + bool m_is_pd; - octave_idx_type m_minor_p; + octave_idx_type m_minor_p; - RowVector m_perm; + RowVector m_perm; - double m_rcond; + double m_rcond; #if defined (HAVE_CHOLMOD) - cholmod_sparse *m_L; + cholmod_sparse *m_L; - cholmod_common m_common; + cholmod_common m_common; - void drop_zeros (const cholmod_sparse *S); + void drop_zeros (const cholmod_sparse *S); #endif - octave_idx_type init (const chol_type& a, bool natural, bool force); - }; + octave_idx_type init (const chol_type& a, bool natural, bool force); +}; #if defined (HAVE_CHOLMOD) - // Can't use CHOLMOD_NAME(drop)(0.0, S, cm) because it doesn't treat - // complex matrices. +// Can't use CHOLMOD_NAME(drop)(0.0, S, cm) because it doesn't treat +// complex matrices. - template - void - sparse_chol::sparse_chol_rep::drop_zeros (const cholmod_sparse *S) +template +void +sparse_chol::sparse_chol_rep::drop_zeros (const cholmod_sparse *S) +{ + if (! S) + return; + + octave_idx_type *Sp = static_cast(S->p); + octave_idx_type *Si = static_cast(S->i); + chol_elt *Sx = static_cast(S->x); + + octave_idx_type pdest = 0; + octave_idx_type ncol = S->ncol; + + for (octave_idx_type k = 0; k < ncol; k++) { - if (! S) - return; + octave_idx_type p = Sp[k]; + octave_idx_type pend = Sp[k+1]; + Sp[k] = pdest; - octave_idx_type *Sp = static_cast(S->p); - octave_idx_type *Si = static_cast(S->i); - chol_elt *Sx = static_cast(S->x); - - octave_idx_type pdest = 0; - octave_idx_type ncol = S->ncol; - - for (octave_idx_type k = 0; k < ncol; k++) + for (; p < pend; p++) { - octave_idx_type p = Sp[k]; - octave_idx_type pend = Sp[k+1]; - Sp[k] = pdest; - - for (; p < pend; p++) - { - chol_elt sik = Sx[p]; + chol_elt sik = Sx[p]; - if (CHOLMOD_IS_NONZERO (sik)) + if (CHOLMOD_IS_NONZERO (sik)) + { + if (p != pdest) { - if (p != pdest) - { - Si[pdest] = Si[p]; - Sx[pdest] = sik; - } + Si[pdest] = Si[p]; + Sx[pdest] = sik; + } - pdest++; - } + pdest++; } } - - Sp[ncol] = pdest; } - // Must provide a specialization for this function. - template - int - get_xtype (void); + Sp[ncol] = pdest; +} + +// Must provide a specialization for this function. +template +int +get_xtype (void); - template <> - inline int - get_xtype (void) - { - return CHOLMOD_REAL; - } +template <> +inline int +get_xtype (void) +{ + return CHOLMOD_REAL; +} - template <> - inline int - get_xtype (void) - { - return CHOLMOD_COMPLEX; - } +template <> +inline int +get_xtype (void) +{ + return CHOLMOD_COMPLEX; +} #endif - template - octave_idx_type - sparse_chol::sparse_chol_rep::init (const chol_type& a, - bool natural, bool force) - { - volatile octave_idx_type info = 0; +template +octave_idx_type +sparse_chol::sparse_chol_rep::init (const chol_type& a, + bool natural, bool force) +{ + volatile octave_idx_type info = 0; #if defined (HAVE_CHOLMOD) - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) + ("sparse_chol requires square matrix"); + + cholmod_common *cm = &m_common; + + // Setup initial parameters + + CHOLMOD_NAME(start) (cm); + cm->prefer_zomplex = false; + + double spu = sparse_params::get_key ("spumoni"); - if (a_nr != a_nc) - (*current_liboctave_error_handler) - ("sparse_chol requires square matrix"); + if (spu == 0.) + { + cm->print = -1; + SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr); + } + else + { + cm->print = static_cast (spu) + 2; + SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, + &SparseCholPrint); + } + + cm->error_handler = &SparseCholError; - cholmod_common *cm = &m_common; + SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, + divcomplex); + + SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot); - // Setup initial parameters + cm->final_asis = false; + cm->final_super = false; + cm->final_ll = true; + cm->final_pack = true; + cm->final_monotonic = true; + cm->final_resymbol = false; + + cholmod_sparse A; + cholmod_sparse *ac = &A; + double dummy; + + ac->nrow = a_nr; + ac->ncol = a_nc; - CHOLMOD_NAME(start) (cm); - cm->prefer_zomplex = false; + ac->p = a.cidx (); + ac->i = a.ridx (); + ac->nzmax = a.nnz (); + ac->packed = true; + ac->sorted = true; + ac->nz = nullptr; +#if defined (OCTAVE_ENABLE_64) + ac->itype = CHOLMOD_LONG; +#else + ac->itype = CHOLMOD_INT; +#endif + ac->dtype = CHOLMOD_DOUBLE; + ac->stype = 1; + ac->xtype = get_xtype (); + + if (a_nr < 1) + ac->x = &dummy; + else + ac->x = a.data (); - double spu = sparse_params::get_key ("spumoni"); + // use natural ordering if no q output parameter + if (natural) + { + cm->nmethods = 1; + cm->method[0].ordering = CHOLMOD_NATURAL; + cm->postorder = false; + } + + cholmod_factor *Lfactor = CHOLMOD_NAME(analyze) (ac, cm); + CHOLMOD_NAME(factorize) (ac, Lfactor, cm); - if (spu == 0.) + m_is_pd = cm->status == CHOLMOD_OK; + info = (m_is_pd ? 0 : cm->status); + + if (m_is_pd || force) + { + m_rcond = CHOLMOD_NAME(rcond) (Lfactor, cm); + + m_minor_p = Lfactor->minor; + + m_L = CHOLMOD_NAME(factor_to_sparse) (Lfactor, cm); + + if (m_minor_p > 0 && m_minor_p < a_nr) { - cm->print = -1; - SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, nullptr); - } - else - { - cm->print = static_cast (spu) + 2; - SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, - &SparseCholPrint); + std::size_t n1 = a_nr + 1; + m_L->p = CHOLMOD_NAME(realloc) (m_minor_p+1, + sizeof(octave_idx_type), + m_L->p, &n1, cm); + + CHOLMOD_NAME(reallocate_sparse) + (static_cast(m_L->p)[m_minor_p], + m_L, cm); + + m_L->ncol = m_minor_p; } - cm->error_handler = &SparseCholError; - - SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, - divcomplex); - - SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot); - - cm->final_asis = false; - cm->final_super = false; - cm->final_ll = true; - cm->final_pack = true; - cm->final_monotonic = true; - cm->final_resymbol = false; - - cholmod_sparse A; - cholmod_sparse *ac = &A; - double dummy; - - ac->nrow = a_nr; - ac->ncol = a_nc; + drop_zeros (m_L); - ac->p = a.cidx (); - ac->i = a.ridx (); - ac->nzmax = a.nnz (); - ac->packed = true; - ac->sorted = true; - ac->nz = nullptr; -#if defined (OCTAVE_ENABLE_64) - ac->itype = CHOLMOD_LONG; -#else - ac->itype = CHOLMOD_INT; -#endif - ac->dtype = CHOLMOD_DOUBLE; - ac->stype = 1; - ac->xtype = get_xtype (); - - if (a_nr < 1) - ac->x = &dummy; - else - ac->x = a.data (); - - // use natural ordering if no q output parameter - if (natural) + if (! natural) { - cm->nmethods = 1; - cm->method[0].ordering = CHOLMOD_NATURAL; - cm->postorder = false; + m_perm.resize (a_nr); + for (octave_idx_type i = 0; i < a_nr; i++) + m_perm(i) = static_cast(Lfactor->Perm)[i]; } - - cholmod_factor *Lfactor = CHOLMOD_NAME(analyze) (ac, cm); - CHOLMOD_NAME(factorize) (ac, Lfactor, cm); - - m_is_pd = cm->status == CHOLMOD_OK; - info = (m_is_pd ? 0 : cm->status); - - if (m_is_pd || force) - { - m_rcond = CHOLMOD_NAME(rcond) (Lfactor, cm); - - m_minor_p = Lfactor->minor; - - m_L = CHOLMOD_NAME(factor_to_sparse) (Lfactor, cm); + } - if (m_minor_p > 0 && m_minor_p < a_nr) - { - std::size_t n1 = a_nr + 1; - m_L->p = CHOLMOD_NAME(realloc) (m_minor_p+1, - sizeof(octave_idx_type), - m_L->p, &n1, cm); - - CHOLMOD_NAME(reallocate_sparse) - (static_cast(m_L->p)[m_minor_p], - m_L, cm); - - m_L->ncol = m_minor_p; - } - - drop_zeros (m_L); + // NAME used to prefix statistics report from print_common + static char blank_name[] = " "; - if (! natural) - { - m_perm.resize (a_nr); - for (octave_idx_type i = 0; i < a_nr; i++) - m_perm(i) = static_cast(Lfactor->Perm)[i]; - } - } + CHOLMOD_NAME(print_common) (blank_name, cm); + CHOLMOD_NAME(free_factor) (&Lfactor, cm); - // NAME used to prefix statistics report from print_common - static char blank_name[] = " "; - - CHOLMOD_NAME(print_common) (blank_name, cm); - CHOLMOD_NAME(free_factor) (&Lfactor, cm); - - return info; + return info; #else - octave_unused_parameter (a); - octave_unused_parameter (natural); - octave_unused_parameter (force); + octave_unused_parameter (a); + octave_unused_parameter (natural); + octave_unused_parameter (force); - (*current_liboctave_error_handler) - ("support for CHOLMOD was unavailable or disabled when liboctave was built"); + (*current_liboctave_error_handler) + ("support for CHOLMOD was unavailable or disabled when liboctave was built"); - return info; + return info; #endif +} + +template +SparseMatrix +sparse_chol::sparse_chol_rep::Q (void) const +{ +#if defined (HAVE_CHOLMOD) + + octave_idx_type n = m_L->nrow; + SparseMatrix p (n, n, n); + + for (octave_idx_type i = 0; i < n; i++) + { + p.xcidx (i) = i; + p.xridx (i) = static_cast (m_perm (i)); + p.xdata (i) = 1; } - template - SparseMatrix - sparse_chol::sparse_chol_rep::Q (void) const - { -#if defined (HAVE_CHOLMOD) - - octave_idx_type n = m_L->nrow; - SparseMatrix p (n, n, n); + p.xcidx (n) = n; - for (octave_idx_type i = 0; i < n; i++) - { - p.xcidx (i) = i; - p.xridx (i) = static_cast (m_perm (i)); - p.xdata (i) = 1; - } - - p.xcidx (n) = n; - - return p; + return p; #else - return SparseMatrix (); + return SparseMatrix (); #endif +} + +template +sparse_chol::sparse_chol (void) + : m_rep (new typename sparse_chol::sparse_chol_rep ()) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, bool natural, + bool force) + : m_rep (new typename + sparse_chol::sparse_chol_rep (a, natural, force)) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, + octave_idx_type& info, + bool natural, bool force) + : m_rep (new typename + sparse_chol::sparse_chol_rep (a, info, natural, force)) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, + octave_idx_type& info, + bool natural) + : m_rep (new typename + sparse_chol::sparse_chol_rep (a, info, natural, false)) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, + octave_idx_type& info) + : m_rep (new typename + sparse_chol::sparse_chol_rep (a, info, false, false)) +{ } + +template +chol_type +sparse_chol::L (void) const +{ +#if defined (HAVE_CHOLMOD) + + cholmod_sparse *m = m_rep->L (); + + octave_idx_type nc = m->ncol; + octave_idx_type nnz = m->nzmax; + + chol_type ret (m->nrow, nc, nnz); + + for (octave_idx_type j = 0; j < nc+1; j++) + ret.xcidx (j) = static_cast(m->p)[j]; + + for (octave_idx_type i = 0; i < nnz; i++) + { + ret.xridx (i) = static_cast(m->i)[i]; + ret.xdata (i) = static_cast(m->x)[i]; } - template - sparse_chol::sparse_chol (void) - : m_rep (new typename sparse_chol::sparse_chol_rep ()) - { } - - template - sparse_chol::sparse_chol (const chol_type& a, bool natural, - bool force) - : m_rep (new typename - sparse_chol::sparse_chol_rep (a, natural, force)) - { } - - template - sparse_chol::sparse_chol (const chol_type& a, - octave_idx_type& info, - bool natural, bool force) - : m_rep (new typename - sparse_chol::sparse_chol_rep (a, info, natural, force)) - { } - - template - sparse_chol::sparse_chol (const chol_type& a, - octave_idx_type& info, - bool natural) - : m_rep (new typename - sparse_chol::sparse_chol_rep (a, info, natural, false)) - { } - - template - sparse_chol::sparse_chol (const chol_type& a, - octave_idx_type& info) - : m_rep (new typename - sparse_chol::sparse_chol_rep (a, info, false, false)) - { } - - template - chol_type - sparse_chol::L (void) const - { -#if defined (HAVE_CHOLMOD) - - cholmod_sparse *m = m_rep->L (); - - octave_idx_type nc = m->ncol; - octave_idx_type nnz = m->nzmax; - - chol_type ret (m->nrow, nc, nnz); - - for (octave_idx_type j = 0; j < nc+1; j++) - ret.xcidx (j) = static_cast(m->p)[j]; - - for (octave_idx_type i = 0; i < nnz; i++) - { - ret.xridx (i) = static_cast(m->i)[i]; - ret.xdata (i) = static_cast(m->x)[i]; - } - - return ret; + return ret; #else - return chol_type (); + return chol_type (); #endif - } +} - template - octave_idx_type - sparse_chol::P (void) const - { - return m_rep->P (); - } +template +octave_idx_type +sparse_chol::P (void) const +{ + return m_rep->P (); +} - template - RowVector - sparse_chol::perm (void) const - { - return m_rep->perm (); - } +template +RowVector +sparse_chol::perm (void) const +{ + return m_rep->perm (); +} - template - SparseMatrix - sparse_chol::Q (void) const - { - return m_rep->Q (); - } +template +SparseMatrix +sparse_chol::Q (void) const +{ + return m_rep->Q (); +} - template - bool - sparse_chol::is_positive_definite (void) const - { - return m_rep->is_positive_definite (); - } +template +bool +sparse_chol::is_positive_definite (void) const +{ + return m_rep->is_positive_definite (); +} - template - double - sparse_chol::rcond (void) const - { - return m_rep->rcond (); - } +template +double +sparse_chol::rcond (void) const +{ + return m_rep->rcond (); +} - template - chol_type - sparse_chol::inverse (void) const - { - chol_type retval; +template +chol_type +sparse_chol::inverse (void) const +{ + chol_type retval; #if defined (HAVE_CHOLMOD) - cholmod_sparse *m = m_rep->L (); - octave_idx_type n = m->ncol; - RowVector m_perm = m_rep->perm (); - double rcond2; - octave_idx_type info; - MatrixType mattype (MatrixType::Upper); - chol_type linv = L ().hermitian ().inverse (mattype, info, rcond2, 1, 0); + cholmod_sparse *m = m_rep->L (); + octave_idx_type n = m->ncol; + RowVector m_perm = m_rep->perm (); + double rcond2; + octave_idx_type info; + MatrixType mattype (MatrixType::Upper); + chol_type linv = L ().hermitian ().inverse (mattype, info, rcond2, 1, 0); - if (m_perm.numel () == n) - { - SparseMatrix Qc = Q (); + if (m_perm.numel () == n) + { + SparseMatrix Qc = Q (); - retval = Qc * linv * linv.hermitian () * Qc.transpose (); - } - else - retval = linv * linv.hermitian (); + retval = Qc * linv * linv.hermitian () * Qc.transpose (); + } + else + retval = linv * linv.hermitian (); #endif - return retval; - } + return retval; +} - template - chol_type - chol2inv (const chol_type& r) - { - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); - chol_type retval; +template +chol_type +chol2inv (const chol_type& r) +{ + octave_idx_type r_nr = r.rows (); + octave_idx_type r_nc = r.cols (); + chol_type retval; - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("U must be a square matrix"); + if (r_nr != r_nc) + (*current_liboctave_error_handler) ("U must be a square matrix"); - MatrixType mattype (r); - int typ = mattype.type (false); - double rcond; - octave_idx_type info; - chol_type rtra, multip; + MatrixType mattype (r); + int typ = mattype.type (false); + double rcond; + octave_idx_type info; + chol_type rtra, multip; - if (typ == MatrixType::Upper) - { - rtra = r.transpose (); - multip = (rtra*r); - } - else if (typ == MatrixType::Lower) - { - rtra = r.transpose (); - multip = (r*rtra); - } - else - (*current_liboctave_error_handler) ("U must be a triangular matrix"); + if (typ == MatrixType::Upper) + { + rtra = r.transpose (); + multip = (rtra*r); + } + else if (typ == MatrixType::Lower) + { + rtra = r.transpose (); + multip = (r*rtra); + } + else + (*current_liboctave_error_handler) ("U must be a triangular matrix"); - MatrixType mattypenew (multip); - retval = multip.inverse (mattypenew, info, rcond, true, false); - return retval; - } + MatrixType mattypenew (multip); + retval = multip.inverse (mattypenew, info, rcond, true, false); + return retval; +} - // SparseComplexMatrix specialization (the value for the NATURAL - // parameter in the sparse_chol::sparse_chol_rep constructor is - // different from the default). +// SparseComplexMatrix specialization (the value for the NATURAL +// parameter in the sparse_chol::sparse_chol_rep constructor is +// different from the default). - template <> - OCTAVE_API - sparse_chol::sparse_chol (const SparseComplexMatrix& a, - octave_idx_type& info) - : m_rep (new sparse_chol::sparse_chol_rep (a, info, - true, - false)) - { } +template <> +OCTAVE_API +sparse_chol::sparse_chol (const SparseComplexMatrix& a, + octave_idx_type& info) + : m_rep (new sparse_chol::sparse_chol_rep (a, info, + true, + false)) +{ } - // Instantiations we need. +// Instantiations we need. - template class OCTAVE_API sparse_chol; +template class OCTAVE_API sparse_chol; - template class sparse_chol; +template class sparse_chol; - template OCTAVE_API SparseMatrix - chol2inv (const SparseMatrix& r); +template OCTAVE_API SparseMatrix +chol2inv (const SparseMatrix& r); - template OCTAVE_API SparseComplexMatrix - chol2inv (const SparseComplexMatrix& r); +template OCTAVE_API SparseComplexMatrix +chol2inv (const SparseComplexMatrix& r); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/sparse-chol.h --- a/liboctave/numeric/sparse-chol.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/sparse-chol.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,67 +38,67 @@ OCTAVE_BEGIN_NAMESPACE(math) - // If the sparse matrix classes become templated on the element type - // (i.e., sparse_matrix), then it might be best to make the - // template parameter of this class also be the element type instead - // of the matrix type. +// If the sparse matrix classes become templated on the element type +// (i.e., sparse_matrix), then it might be best to make the +// template parameter of this class also be the element type instead +// of the matrix type. - template - class - OCTAVE_API - sparse_chol - { - public: +template +class +OCTAVE_API +sparse_chol +{ +public: - sparse_chol (void); + sparse_chol (void); - sparse_chol (const chol_type& a, bool natural, bool force); + sparse_chol (const chol_type& a, bool natural, bool force); - sparse_chol (const chol_type& a, octave_idx_type& info, - bool natural, bool force); + sparse_chol (const chol_type& a, octave_idx_type& info, + bool natural, bool force); - sparse_chol (const chol_type& a, octave_idx_type& info, bool natural); + sparse_chol (const chol_type& a, octave_idx_type& info, bool natural); - sparse_chol (const chol_type& a, octave_idx_type& info); + sparse_chol (const chol_type& a, octave_idx_type& info); - sparse_chol (const sparse_chol& a) = default; + sparse_chol (const sparse_chol& a) = default; - virtual ~sparse_chol (void) = default; + virtual ~sparse_chol (void) = default; - sparse_chol& - operator = (const sparse_chol& a) = default; + sparse_chol& + operator = (const sparse_chol& a) = default; - chol_type L (void) const; + chol_type L (void) const; - chol_type R (void) const { return L ().hermitian (); } + chol_type R (void) const { return L ().hermitian (); } - octave_idx_type P (void) const; + octave_idx_type P (void) const; - RowVector perm (void) const; + RowVector perm (void) const; - SparseMatrix Q (void) const; + SparseMatrix Q (void) const; - bool is_positive_definite (void) const; + bool is_positive_definite (void) const; - double rcond (void) const; + double rcond (void) const; - chol_type inverse (void) const; + chol_type inverse (void) const; - protected: +protected: - typedef typename chol_type::element_type chol_elt; + typedef typename chol_type::element_type chol_elt; - class sparse_chol_rep; + class sparse_chol_rep; - private: +private: - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; - template - OCTAVE_API - chol_type - chol2inv (const chol_type& r); +template +OCTAVE_API +chol_type +chol2inv (const chol_type& r); OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/sparse-lu.cc --- a/liboctave/numeric/sparse-lu.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/sparse-lu.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,455 +41,472 @@ OCTAVE_BEGIN_NAMESPACE(math) - // Wrappers for SuiteSparse (formerly UMFPACK) functions that have - // different names depending on the sparse matrix data type. - // - // All of these functions must be specialized to forward to the correct - // SuiteSparse functions. +// Wrappers for SuiteSparse (formerly UMFPACK) functions that have +// different names depending on the sparse matrix data type. +// +// All of these functions must be specialized to forward to the correct +// SuiteSparse functions. - template - void - umfpack_defaults (double *Control); +template +void +umfpack_defaults (double *Control); - template - void - umfpack_free_numeric (void **Numeric); +template +void +umfpack_free_numeric (void **Numeric); - template - void - umfpack_free_symbolic (void **Symbolic); +template +void +umfpack_free_symbolic (void **Symbolic); - template - octave_idx_type - umfpack_get_lunz (octave_idx_type *lnz, octave_idx_type *unz, - void *Numeric); +template +octave_idx_type +umfpack_get_lunz (octave_idx_type *lnz, octave_idx_type *unz, + void *Numeric); - template - octave_idx_type - umfpack_get_numeric (octave_idx_type *Lp, octave_idx_type *Lj, - T *Lx, // Or Lz_packed - octave_idx_type *Up, octave_idx_type *Ui, - T *Ux, // Or Uz_packed - octave_idx_type *p, octave_idx_type *q, - double *Dz_packed, octave_idx_type *do_recip, - double *Rs, void *Numeric); +template +octave_idx_type +umfpack_get_numeric (octave_idx_type *Lp, octave_idx_type *Lj, + T *Lx, // Or Lz_packed + octave_idx_type *Up, octave_idx_type *Ui, + T *Ux, // Or Uz_packed + octave_idx_type *p, octave_idx_type *q, + double *Dz_packed, octave_idx_type *do_recip, + double *Rs, void *Numeric); - template - octave_idx_type - umfpack_numeric (const octave_idx_type *Ap, const octave_idx_type *Ai, - const T *Ax, // Or Az_packed - void *Symbolic, void **Numeric, - const double *Control, double *Info); +template +octave_idx_type +umfpack_numeric (const octave_idx_type *Ap, const octave_idx_type *Ai, + const T *Ax, // Or Az_packed + void *Symbolic, void **Numeric, + const double *Control, double *Info); - template - octave_idx_type - umfpack_qsymbolic (octave_idx_type n_row, octave_idx_type n_col, - const octave_idx_type *Ap, const octave_idx_type *Ai, - const T *Ax, // Or Az_packed - const octave_idx_type *Qinit, void **Symbolic, - const double *Control, double *Info); +template +octave_idx_type +umfpack_qsymbolic (octave_idx_type n_row, octave_idx_type n_col, + const octave_idx_type *Ap, const octave_idx_type *Ai, + const T *Ax, // Or Az_packed + const octave_idx_type *Qinit, void **Symbolic, + const double *Control, double *Info); - template - void - umfpack_report_control (const double *Control); +template +void +umfpack_report_control (const double *Control); - template - void - umfpack_report_info (const double *Control, const double *Info); +template +void +umfpack_report_info (const double *Control, const double *Info); - template - void - umfpack_report_matrix (octave_idx_type n_row, octave_idx_type n_col, - const octave_idx_type *Ap, - const octave_idx_type *Ai, - const T *Ax, // Or Az_packed - octave_idx_type col_form, const double *Control); +template +void +umfpack_report_matrix (octave_idx_type n_row, octave_idx_type n_col, + const octave_idx_type *Ap, + const octave_idx_type *Ai, + const T *Ax, // Or Az_packed + octave_idx_type col_form, const double *Control); - template - void - umfpack_report_numeric (void *Numeric, const double *Control); +template +void +umfpack_report_numeric (void *Numeric, const double *Control); - template - void - umfpack_report_perm (octave_idx_type np, const octave_idx_type *Perm, - const double *Control); +template +void +umfpack_report_perm (octave_idx_type np, const octave_idx_type *Perm, + const double *Control); - template - void - umfpack_report_status (double *Control, octave_idx_type status); +template +void +umfpack_report_status (double *Control, octave_idx_type status); - template - void - umfpack_report_symbolic (void *Symbolic, const double *Control); +template +void +umfpack_report_symbolic (void *Symbolic, const double *Control); #if defined (HAVE_UMFPACK) - // SparseMatrix Specialization. +// SparseMatrix Specialization. - template <> - inline OCTAVE_API void - umfpack_defaults (double *Control) - { - UMFPACK_DNAME (defaults) (Control); - } +template <> +inline OCTAVE_API void +umfpack_defaults (double *Control) +{ + UMFPACK_DNAME (defaults) (Control); +} - template <> - inline OCTAVE_API void - umfpack_free_numeric (void **Numeric) - { - UMFPACK_DNAME (free_numeric) (Numeric); - } +template <> +inline OCTAVE_API void +umfpack_free_numeric (void **Numeric) +{ + UMFPACK_DNAME (free_numeric) (Numeric); +} - template <> - inline OCTAVE_API void - umfpack_free_symbolic (void **Symbolic) - { - UMFPACK_DNAME (free_symbolic) (Symbolic); - } +template <> +inline OCTAVE_API void +umfpack_free_symbolic (void **Symbolic) +{ + UMFPACK_DNAME (free_symbolic) (Symbolic); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_get_lunz - (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric) - { - suitesparse_integer ignore1, ignore2, ignore3; +template <> +inline OCTAVE_API octave_idx_type +umfpack_get_lunz +(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric) +{ + suitesparse_integer ignore1, ignore2, ignore3; - return UMFPACK_DNAME (get_lunz) (to_suitesparse_intptr (lnz), - to_suitesparse_intptr (unz), - &ignore1, &ignore2, &ignore3, Numeric); - } + return UMFPACK_DNAME (get_lunz) (to_suitesparse_intptr (lnz), + to_suitesparse_intptr (unz), + &ignore1, &ignore2, &ignore3, Numeric); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_get_numeric - (octave_idx_type *Lp, octave_idx_type *Lj, double *Lx, - octave_idx_type *Up, octave_idx_type *Ui, double *Ux, - octave_idx_type *p, octave_idx_type *q, double *Dx, - octave_idx_type *do_recip, double *Rs, void *Numeric) - { - return UMFPACK_DNAME (get_numeric) (to_suitesparse_intptr (Lp), - to_suitesparse_intptr (Lj), - Lx, to_suitesparse_intptr (Up), - to_suitesparse_intptr (Ui), Ux, - to_suitesparse_intptr (p), - to_suitesparse_intptr (q), Dx, - to_suitesparse_intptr (do_recip), - Rs, Numeric); - } +template <> +inline OCTAVE_API octave_idx_type +umfpack_get_numeric +(octave_idx_type *Lp, octave_idx_type *Lj, double *Lx, + octave_idx_type *Up, octave_idx_type *Ui, double *Ux, + octave_idx_type *p, octave_idx_type *q, double *Dx, + octave_idx_type *do_recip, double *Rs, void *Numeric) +{ + return UMFPACK_DNAME (get_numeric) (to_suitesparse_intptr (Lp), + to_suitesparse_intptr (Lj), + Lx, to_suitesparse_intptr (Up), + to_suitesparse_intptr (Ui), Ux, + to_suitesparse_intptr (p), + to_suitesparse_intptr (q), Dx, + to_suitesparse_intptr (do_recip), + Rs, Numeric); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_numeric - (const octave_idx_type *Ap, const octave_idx_type *Ai, - const double *Ax, void *Symbolic, void **Numeric, - const double *Control, double *Info) - { - return UMFPACK_DNAME (numeric) (to_suitesparse_intptr (Ap), - to_suitesparse_intptr (Ai), - Ax, Symbolic, Numeric, Control, Info); - } +template <> +inline OCTAVE_API octave_idx_type +umfpack_numeric +(const octave_idx_type *Ap, const octave_idx_type *Ai, + const double *Ax, void *Symbolic, void **Numeric, + const double *Control, double *Info) +{ + return UMFPACK_DNAME (numeric) (to_suitesparse_intptr (Ap), + to_suitesparse_intptr (Ai), + Ax, Symbolic, Numeric, Control, Info); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_qsymbolic - (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, - const octave_idx_type *Ai, const double *Ax, - const octave_idx_type *Qinit, void **Symbolic, - const double *Control, double *Info) - { - return UMFPACK_DNAME (qsymbolic) (n_row, n_col, - to_suitesparse_intptr (Ap), - to_suitesparse_intptr (Ai), Ax, - to_suitesparse_intptr (Qinit), - Symbolic, Control, Info); - } +template <> +inline OCTAVE_API octave_idx_type +umfpack_qsymbolic +(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, + const octave_idx_type *Ai, const double *Ax, + const octave_idx_type *Qinit, void **Symbolic, + const double *Control, double *Info) +{ + return UMFPACK_DNAME (qsymbolic) (n_row, n_col, + to_suitesparse_intptr (Ap), + to_suitesparse_intptr (Ai), Ax, + to_suitesparse_intptr (Qinit), + Symbolic, Control, Info); +} - template <> - inline OCTAVE_API void - umfpack_report_control (const double *Control) - { - UMFPACK_DNAME (report_control) (Control); - } +template <> +inline OCTAVE_API void +umfpack_report_control (const double *Control) +{ + UMFPACK_DNAME (report_control) (Control); +} - template <> - inline OCTAVE_API void - umfpack_report_info (const double *Control, const double *Info) - { - UMFPACK_DNAME (report_info) (Control, Info); - } +template <> +inline OCTAVE_API void +umfpack_report_info (const double *Control, const double *Info) +{ + UMFPACK_DNAME (report_info) (Control, Info); +} - template <> - inline OCTAVE_API void - umfpack_report_matrix - (octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, - const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form, - const double *Control) - { - UMFPACK_DNAME (report_matrix) (n_row, n_col, - to_suitesparse_intptr (Ap), - to_suitesparse_intptr (Ai), Ax, - col_form, Control); - } +template <> +inline OCTAVE_API void +umfpack_report_matrix +(octave_idx_type n_row, octave_idx_type n_col, const octave_idx_type *Ap, + const octave_idx_type *Ai, const double *Ax, octave_idx_type col_form, + const double *Control) +{ + UMFPACK_DNAME (report_matrix) (n_row, n_col, + to_suitesparse_intptr (Ap), + to_suitesparse_intptr (Ai), Ax, + col_form, Control); +} - template <> - inline OCTAVE_API void - umfpack_report_numeric (void *Numeric, const double *Control) - { - UMFPACK_DNAME (report_numeric) (Numeric, Control); - } +template <> +inline OCTAVE_API void +umfpack_report_numeric (void *Numeric, const double *Control) +{ + UMFPACK_DNAME (report_numeric) (Numeric, Control); +} - template <> - inline OCTAVE_API void - umfpack_report_perm - (octave_idx_type np, const octave_idx_type *Perm, const double *Control) - { - UMFPACK_DNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control); - } +template <> +inline OCTAVE_API void +umfpack_report_perm +(octave_idx_type np, const octave_idx_type *Perm, const double *Control) +{ + UMFPACK_DNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control); +} - template <> - inline OCTAVE_API void - umfpack_report_status (double *Control, octave_idx_type status) - { - UMFPACK_DNAME (report_status) (Control, status); - } +template <> +inline OCTAVE_API void +umfpack_report_status (double *Control, octave_idx_type status) +{ + UMFPACK_DNAME (report_status) (Control, status); +} - template <> - inline OCTAVE_API void - umfpack_report_symbolic (void *Symbolic, const double *Control) - { - UMFPACK_DNAME (report_symbolic) (Symbolic, Control); - } +template <> +inline OCTAVE_API void +umfpack_report_symbolic (void *Symbolic, const double *Control) +{ + UMFPACK_DNAME (report_symbolic) (Symbolic, Control); +} - // SparseComplexMatrix specialization. +// SparseComplexMatrix specialization. - template <> - inline OCTAVE_API void - umfpack_defaults (double *Control) - { - UMFPACK_ZNAME (defaults) (Control); - } +template <> +inline OCTAVE_API void +umfpack_defaults (double *Control) +{ + UMFPACK_ZNAME (defaults) (Control); +} - template <> - inline OCTAVE_API void - umfpack_free_numeric (void **Numeric) - { - UMFPACK_ZNAME (free_numeric) (Numeric); - } +template <> +inline OCTAVE_API void +umfpack_free_numeric (void **Numeric) +{ + UMFPACK_ZNAME (free_numeric) (Numeric); +} - template <> - inline OCTAVE_API void - umfpack_free_symbolic (void **Symbolic) - { - UMFPACK_ZNAME (free_symbolic) (Symbolic); - } +template <> +inline OCTAVE_API void +umfpack_free_symbolic (void **Symbolic) +{ + UMFPACK_ZNAME (free_symbolic) (Symbolic); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_get_lunz - (octave_idx_type *lnz, octave_idx_type *unz, void *Numeric) - { - suitesparse_integer ignore1, ignore2, ignore3; +template <> +inline OCTAVE_API octave_idx_type +umfpack_get_lunz +(octave_idx_type *lnz, octave_idx_type *unz, void *Numeric) +{ + suitesparse_integer ignore1, ignore2, ignore3; - return UMFPACK_ZNAME (get_lunz) (to_suitesparse_intptr (lnz), - to_suitesparse_intptr (unz), - &ignore1, &ignore2, &ignore3, Numeric); - } + return UMFPACK_ZNAME (get_lunz) (to_suitesparse_intptr (lnz), + to_suitesparse_intptr (unz), + &ignore1, &ignore2, &ignore3, Numeric); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_get_numeric - (octave_idx_type *Lp, octave_idx_type *Lj, Complex *Lz, - octave_idx_type *Up, octave_idx_type *Ui, Complex *Uz, - octave_idx_type *p, octave_idx_type *q, double *Dz, - octave_idx_type *do_recip, double *Rs, void *Numeric) - { - return UMFPACK_ZNAME (get_numeric) (to_suitesparse_intptr (Lp), - to_suitesparse_intptr (Lj), - reinterpret_cast (Lz), - nullptr, to_suitesparse_intptr (Up), - to_suitesparse_intptr (Ui), - reinterpret_cast (Uz), - nullptr, to_suitesparse_intptr (p), - to_suitesparse_intptr (q), - reinterpret_cast (Dz), - nullptr, to_suitesparse_intptr (do_recip), - Rs, Numeric); - } +template <> +inline OCTAVE_API octave_idx_type +umfpack_get_numeric +(octave_idx_type *Lp, octave_idx_type *Lj, Complex *Lz, + octave_idx_type *Up, octave_idx_type *Ui, Complex *Uz, + octave_idx_type *p, octave_idx_type *q, double *Dz, + octave_idx_type *do_recip, double *Rs, void *Numeric) +{ + return UMFPACK_ZNAME (get_numeric) (to_suitesparse_intptr (Lp), + to_suitesparse_intptr (Lj), + reinterpret_cast (Lz), + nullptr, to_suitesparse_intptr (Up), + to_suitesparse_intptr (Ui), + reinterpret_cast (Uz), + nullptr, to_suitesparse_intptr (p), + to_suitesparse_intptr (q), + reinterpret_cast (Dz), + nullptr, to_suitesparse_intptr (do_recip), + Rs, Numeric); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_numeric - (const octave_idx_type *Ap, const octave_idx_type *Ai, - const Complex *Az, void *Symbolic, void **Numeric, - const double *Control, double *Info) - { - return UMFPACK_ZNAME (numeric) (to_suitesparse_intptr (Ap), - to_suitesparse_intptr (Ai), - reinterpret_cast (Az), - nullptr, Symbolic, Numeric, Control, Info); - } +template <> +inline OCTAVE_API octave_idx_type +umfpack_numeric +(const octave_idx_type *Ap, const octave_idx_type *Ai, + const Complex *Az, void *Symbolic, void **Numeric, + const double *Control, double *Info) +{ + return UMFPACK_ZNAME (numeric) (to_suitesparse_intptr (Ap), + to_suitesparse_intptr (Ai), + reinterpret_cast (Az), + nullptr, Symbolic, Numeric, Control, Info); +} - template <> - inline OCTAVE_API octave_idx_type - umfpack_qsymbolic - (octave_idx_type n_row, octave_idx_type n_col, - const octave_idx_type *Ap, const octave_idx_type *Ai, - const Complex *Az, const octave_idx_type *Qinit, - void **Symbolic, const double *Control, double *Info) - { - return UMFPACK_ZNAME (qsymbolic) (n_row, n_col, - to_suitesparse_intptr (Ap), - to_suitesparse_intptr (Ai), - reinterpret_cast (Az), - nullptr, to_suitesparse_intptr (Qinit), - Symbolic, Control, Info); - } +template <> +inline OCTAVE_API octave_idx_type +umfpack_qsymbolic +(octave_idx_type n_row, octave_idx_type n_col, + const octave_idx_type *Ap, const octave_idx_type *Ai, + const Complex *Az, const octave_idx_type *Qinit, + void **Symbolic, const double *Control, double *Info) +{ + return UMFPACK_ZNAME (qsymbolic) (n_row, n_col, + to_suitesparse_intptr (Ap), + to_suitesparse_intptr (Ai), + reinterpret_cast (Az), + nullptr, to_suitesparse_intptr (Qinit), + Symbolic, Control, Info); +} - template <> - inline OCTAVE_API void - umfpack_report_control (const double *Control) - { - UMFPACK_ZNAME (report_control) (Control); - } +template <> +inline OCTAVE_API void +umfpack_report_control (const double *Control) +{ + UMFPACK_ZNAME (report_control) (Control); +} - template <> - inline OCTAVE_API void - umfpack_report_info (const double *Control, const double *Info) - { - UMFPACK_ZNAME (report_info) (Control, Info); - } +template <> +inline OCTAVE_API void +umfpack_report_info (const double *Control, const double *Info) +{ + UMFPACK_ZNAME (report_info) (Control, Info); +} - template <> - inline OCTAVE_API void - umfpack_report_matrix - (octave_idx_type n_row, octave_idx_type n_col, - const octave_idx_type *Ap, const octave_idx_type *Ai, - const Complex *Az, octave_idx_type col_form, const double *Control) - { - UMFPACK_ZNAME (report_matrix) (n_row, n_col, - to_suitesparse_intptr (Ap), - to_suitesparse_intptr (Ai), - reinterpret_cast (Az), - nullptr, col_form, Control); - } +template <> +inline OCTAVE_API void +umfpack_report_matrix +(octave_idx_type n_row, octave_idx_type n_col, + const octave_idx_type *Ap, const octave_idx_type *Ai, + const Complex *Az, octave_idx_type col_form, const double *Control) +{ + UMFPACK_ZNAME (report_matrix) (n_row, n_col, + to_suitesparse_intptr (Ap), + to_suitesparse_intptr (Ai), + reinterpret_cast (Az), + nullptr, col_form, Control); +} - template <> - inline OCTAVE_API void - umfpack_report_numeric (void *Numeric, const double *Control) - { - UMFPACK_ZNAME (report_numeric) (Numeric, Control); - } +template <> +inline OCTAVE_API void +umfpack_report_numeric (void *Numeric, const double *Control) +{ + UMFPACK_ZNAME (report_numeric) (Numeric, Control); +} - template <> - inline OCTAVE_API void - umfpack_report_perm - (octave_idx_type np, const octave_idx_type *Perm, const double *Control) - { - UMFPACK_ZNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control); - } +template <> +inline OCTAVE_API void +umfpack_report_perm +(octave_idx_type np, const octave_idx_type *Perm, const double *Control) +{ + UMFPACK_ZNAME (report_perm) (np, to_suitesparse_intptr (Perm), Control); +} - template <> - inline OCTAVE_API void - umfpack_report_status (double *Control, octave_idx_type status) - { - UMFPACK_ZNAME (report_status) (Control, status); - } +template <> +inline OCTAVE_API void +umfpack_report_status (double *Control, octave_idx_type status) +{ + UMFPACK_ZNAME (report_status) (Control, status); +} - template <> - inline OCTAVE_API void - umfpack_report_symbolic (void *Symbolic, const double *Control) - { - UMFPACK_ZNAME (report_symbolic) (Symbolic, Control); - } +template <> +inline OCTAVE_API void +umfpack_report_symbolic (void *Symbolic, const double *Control) +{ + UMFPACK_ZNAME (report_symbolic) (Symbolic, Control); +} #endif - template - sparse_lu::sparse_lu (const lu_type& a, const Matrix& piv_thres, - bool scale) - : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () - { +template +sparse_lu::sparse_lu (const lu_type& a, const Matrix& piv_thres, + bool scale) + : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () +{ #if defined (HAVE_UMFPACK) - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.cols (); + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.cols (); + + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_defaults (control); + + double tmp = sparse_params::get_key ("spumoni"); + if (! math::isnan (tmp)) + Control (UMFPACK_PRL) = tmp; - // Setup the control parameters - Matrix Control (UMFPACK_CONTROL, 1); - double *control = Control.fortran_vec (); - umfpack_defaults (control); + if (piv_thres.numel () == 2) + { + tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0)); + if (! math::isnan (tmp)) + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; - double tmp = sparse_params::get_key ("spumoni"); + tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1)); if (! math::isnan (tmp)) - Control (UMFPACK_PRL) = tmp; + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + } + else + { + tmp = sparse_params::get_key ("piv_tol"); + if (! math::isnan (tmp)) + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; - if (piv_thres.numel () == 2) - { - tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0)); - if (! math::isnan (tmp)) - Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + tmp = sparse_params::get_key ("sym_tol"); + if (! math::isnan (tmp)) + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + } - tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1)); - if (! math::isnan (tmp)) - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; - } - else - { - tmp = sparse_params::get_key ("piv_tol"); - if (! math::isnan (tmp)) - Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + // Set whether we are allowed to modify Q or not + tmp = sparse_params::get_key ("autoamd"); + if (! math::isnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; - tmp = sparse_params::get_key ("sym_tol"); - if (! math::isnan (tmp)) - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; - } + // Turn-off UMFPACK scaling for LU + if (scale) + Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; + else + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_report_control (control); - // Set whether we are allowed to modify Q or not - tmp = sparse_params::get_key ("autoamd"); - if (! math::isnan (tmp)) - Control (UMFPACK_FIXQ) = tmp; + const octave_idx_type *Ap = a.cidx (); + const octave_idx_type *Ai = a.ridx (); + const lu_elt_type *Ax = a.data (); + + umfpack_report_matrix (nr, nc, Ap, Ai, Ax, + static_cast (1), + control); - // Turn-off UMFPACK scaling for LU - if (scale) - Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; - else - Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status = umfpack_qsymbolic (nr, nc, Ap, Ai, Ax, nullptr, + &Symbolic, control, info); - umfpack_report_control (control); + if (status < 0) + { + umfpack_report_status (control, status); + umfpack_report_info (control, info); + + umfpack_free_symbolic (&Symbolic); - const octave_idx_type *Ap = a.cidx (); - const octave_idx_type *Ai = a.ridx (); - const lu_elt_type *Ax = a.data (); + (*current_liboctave_error_handler) + ("sparse_lu: symbolic factorization failed"); + } + else + { + umfpack_report_symbolic (Symbolic, control); - umfpack_report_matrix (nr, nc, Ap, Ai, Ax, - static_cast (1), - control); + void *Numeric; + status = umfpack_numeric (Ap, Ai, Ax, Symbolic, + &Numeric, control, info); + umfpack_free_symbolic (&Symbolic); - void *Symbolic; - Matrix Info (1, UMFPACK_INFO); - double *info = Info.fortran_vec (); - int status = umfpack_qsymbolic (nr, nc, Ap, Ai, Ax, nullptr, - &Symbolic, control, info); + m_cond = Info (UMFPACK_RCOND); if (status < 0) { umfpack_report_status (control, status); umfpack_report_info (control, info); - umfpack_free_symbolic (&Symbolic); + umfpack_free_numeric (&Numeric); (*current_liboctave_error_handler) - ("sparse_lu: symbolic factorization failed"); + ("sparse_lu: numeric factorization failed"); } else { - umfpack_report_symbolic (Symbolic, control); + umfpack_report_numeric (Numeric, control); - void *Numeric; - status = umfpack_numeric (Ap, Ai, Ax, Symbolic, - &Numeric, control, info); - umfpack_free_symbolic (&Symbolic); - - m_cond = Info (UMFPACK_RCOND); + octave_idx_type lnz, unz; + status = umfpack_get_lunz (&lnz, &unz, Numeric); if (status < 0) { @@ -499,235 +516,235 @@ umfpack_free_numeric (&Numeric); (*current_liboctave_error_handler) - ("sparse_lu: numeric factorization failed"); + ("sparse_lu: extracting LU factors failed"); } else { - umfpack_report_numeric (Numeric, control); + octave_idx_type n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + m_L = lu_type (n_inner, nr, + static_cast (1)); + else + m_L = lu_type (n_inner, nr, lnz); + + octave_idx_type *Ltp = m_L.cidx (); + octave_idx_type *Ltj = m_L.ridx (); + lu_elt_type *Ltx = m_L.data (); + + if (unz < 1) + m_U = lu_type (n_inner, nc, + static_cast (1)); + else + m_U = lu_type (n_inner, nc, unz); + + octave_idx_type *Up = m_U.cidx (); + octave_idx_type *Uj = m_U.ridx (); + lu_elt_type *Ux = m_U.data (); - octave_idx_type lnz, unz; - status = umfpack_get_lunz (&lnz, &unz, Numeric); + m_R = SparseMatrix (nr, nr, nr); + for (octave_idx_type i = 0; i < nr; i++) + { + m_R.xridx (i) = i; + m_R.xcidx (i) = i; + } + m_R.xcidx (nr) = nr; + double *Rx = m_R.data (); + + m_P.resize (dim_vector (nr, 1)); + octave_idx_type *p = m_P.fortran_vec (); + + m_Q.resize (dim_vector (nc, 1)); + octave_idx_type *q = m_Q.fortran_vec (); + + octave_idx_type do_recip; + status = umfpack_get_numeric (Ltp, Ltj, Ltx, + Up, Uj, Ux, + p, q, nullptr, + &do_recip, Rx, + Numeric); + + umfpack_free_numeric (&Numeric); if (status < 0) { umfpack_report_status (control, status); - umfpack_report_info (control, info); - - umfpack_free_numeric (&Numeric); (*current_liboctave_error_handler) ("sparse_lu: extracting LU factors failed"); } else { - octave_idx_type n_inner = (nr < nc ? nr : nc); - - if (lnz < 1) - m_L = lu_type (n_inner, nr, - static_cast (1)); - else - m_L = lu_type (n_inner, nr, lnz); - - octave_idx_type *Ltp = m_L.cidx (); - octave_idx_type *Ltj = m_L.ridx (); - lu_elt_type *Ltx = m_L.data (); - - if (unz < 1) - m_U = lu_type (n_inner, nc, - static_cast (1)); - else - m_U = lu_type (n_inner, nc, unz); + m_L = m_L.transpose (); - octave_idx_type *Up = m_U.cidx (); - octave_idx_type *Uj = m_U.ridx (); - lu_elt_type *Ux = m_U.data (); - - m_R = SparseMatrix (nr, nr, nr); - for (octave_idx_type i = 0; i < nr; i++) - { - m_R.xridx (i) = i; - m_R.xcidx (i) = i; - } - m_R.xcidx (nr) = nr; - double *Rx = m_R.data (); - - m_P.resize (dim_vector (nr, 1)); - octave_idx_type *p = m_P.fortran_vec (); - - m_Q.resize (dim_vector (nc, 1)); - octave_idx_type *q = m_Q.fortran_vec (); + if (do_recip) + for (octave_idx_type i = 0; i < nr; i++) + Rx[i] = 1.0 / Rx[i]; - octave_idx_type do_recip; - status = umfpack_get_numeric (Ltp, Ltj, Ltx, - Up, Uj, Ux, - p, q, nullptr, - &do_recip, Rx, - Numeric); - - umfpack_free_numeric (&Numeric); - - if (status < 0) - { - umfpack_report_status (control, status); - - (*current_liboctave_error_handler) - ("sparse_lu: extracting LU factors failed"); - } - else - { - m_L = m_L.transpose (); + umfpack_report_matrix (nr, n_inner, + m_L.cidx (), + m_L.ridx (), + m_L.data (), + static_cast (1), + control); + umfpack_report_matrix (n_inner, nc, + m_U.cidx (), + m_U.ridx (), + m_U.data (), + static_cast (1), + control); + umfpack_report_perm (nr, p, control); + umfpack_report_perm (nc, q, control); + } - if (do_recip) - for (octave_idx_type i = 0; i < nr; i++) - Rx[i] = 1.0 / Rx[i]; - - umfpack_report_matrix (nr, n_inner, - m_L.cidx (), - m_L.ridx (), - m_L.data (), - static_cast (1), - control); - umfpack_report_matrix (n_inner, nc, - m_U.cidx (), - m_U.ridx (), - m_U.data (), - static_cast (1), - control); - umfpack_report_perm (nr, p, control); - umfpack_report_perm (nc, q, control); - } - - umfpack_report_info (control, info); - } + umfpack_report_info (control, info); } } + } #else - octave_unused_parameter (a); - octave_unused_parameter (piv_thres); - octave_unused_parameter (scale); + octave_unused_parameter (a); + octave_unused_parameter (piv_thres); + octave_unused_parameter (scale); - (*current_liboctave_error_handler) - ("support for UMFPACK was unavailable or disabled when liboctave was built"); + (*current_liboctave_error_handler) + ("support for UMFPACK was unavailable or disabled when liboctave was built"); #endif - } +} - template - sparse_lu::sparse_lu (const lu_type& a, - const ColumnVector& Qinit, - const Matrix& piv_thres, bool scale, - bool FixedQ, double droptol, - bool milu, bool udiag) - : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () - { +template +sparse_lu::sparse_lu (const lu_type& a, + const ColumnVector& Qinit, + const Matrix& piv_thres, bool scale, + bool FixedQ, double droptol, + bool milu, bool udiag) + : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () +{ #if defined (HAVE_UMFPACK) - if (milu) - (*current_liboctave_error_handler) - ("Modified incomplete LU not implemented"); + if (milu) + (*current_liboctave_error_handler) + ("Modified incomplete LU not implemented"); - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.cols (); + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.cols (); - // Setup the control parameters - Matrix Control (UMFPACK_CONTROL, 1); - double *control = Control.fortran_vec (); - umfpack_defaults (control); + // Setup the control parameters + Matrix Control (UMFPACK_CONTROL, 1); + double *control = Control.fortran_vec (); + umfpack_defaults (control); - double tmp = sparse_params::get_key ("spumoni"); - if (! math::isnan (tmp)) - Control (UMFPACK_PRL) = tmp; + double tmp = sparse_params::get_key ("spumoni"); + if (! math::isnan (tmp)) + Control (UMFPACK_PRL) = tmp; - if (piv_thres.numel () == 2) - { - tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0)); - if (! math::isnan (tmp)) - Control (UMFPACK_PIVOT_TOLERANCE) = tmp; - tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1)); - if (! math::isnan (tmp)) - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; - } - else - { - tmp = sparse_params::get_key ("piv_tol"); - if (! math::isnan (tmp)) - Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + if (piv_thres.numel () == 2) + { + tmp = (piv_thres (0) > 1. ? 1. : piv_thres (0)); + if (! math::isnan (tmp)) + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; + tmp = (piv_thres (1) > 1. ? 1. : piv_thres (1)); + if (! math::isnan (tmp)) + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + } + else + { + tmp = sparse_params::get_key ("piv_tol"); + if (! math::isnan (tmp)) + Control (UMFPACK_PIVOT_TOLERANCE) = tmp; - tmp = sparse_params::get_key ("sym_tol"); - if (! math::isnan (tmp)) - Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; - } + tmp = sparse_params::get_key ("sym_tol"); + if (! math::isnan (tmp)) + Control (UMFPACK_SYM_PIVOT_TOLERANCE) = tmp; + } + + if (droptol >= 0.) + Control (UMFPACK_DROPTOL) = droptol; - if (droptol >= 0.) - Control (UMFPACK_DROPTOL) = droptol; + // Set whether we are allowed to modify Q or not + if (FixedQ) + Control (UMFPACK_FIXQ) = 1.0; + else + { + tmp = sparse_params::get_key ("autoamd"); + if (! math::isnan (tmp)) + Control (UMFPACK_FIXQ) = tmp; + } - // Set whether we are allowed to modify Q or not - if (FixedQ) - Control (UMFPACK_FIXQ) = 1.0; - else - { - tmp = sparse_params::get_key ("autoamd"); - if (! math::isnan (tmp)) - Control (UMFPACK_FIXQ) = tmp; - } + // Turn-off UMFPACK scaling for LU + if (scale) + Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; + else + Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + + umfpack_report_control (control); + + const octave_idx_type *Ap = a.cidx (); + const octave_idx_type *Ai = a.ridx (); + const lu_elt_type *Ax = a.data (); - // Turn-off UMFPACK scaling for LU - if (scale) - Control (UMFPACK_SCALE) = UMFPACK_SCALE_SUM; - else - Control (UMFPACK_SCALE) = UMFPACK_SCALE_NONE; + umfpack_report_matrix (nr, nc, Ap, Ai, Ax, + static_cast (1), + control); - umfpack_report_control (control); + void *Symbolic; + Matrix Info (1, UMFPACK_INFO); + double *info = Info.fortran_vec (); + int status; - const octave_idx_type *Ap = a.cidx (); - const octave_idx_type *Ai = a.ridx (); - const lu_elt_type *Ax = a.data (); + // Null loop so that qinit is immediately deallocated when not needed + do + { + OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc); - umfpack_report_matrix (nr, nc, Ap, Ai, Ax, - static_cast (1), - control); + for (octave_idx_type i = 0; i < nc; i++) + qinit[i] = static_cast (Qinit (i)); - void *Symbolic; - Matrix Info (1, UMFPACK_INFO); - double *info = Info.fortran_vec (); - int status; + status = umfpack_qsymbolic (nr, nc, Ap, Ai, Ax, + qinit, &Symbolic, control, + info); + } + while (0); + + if (status < 0) + { + umfpack_report_status (control, status); + umfpack_report_info (control, info); - // Null loop so that qinit is immediately deallocated when not needed - do - { - OCTAVE_LOCAL_BUFFER (octave_idx_type, qinit, nc); + umfpack_free_symbolic (&Symbolic); - for (octave_idx_type i = 0; i < nc; i++) - qinit[i] = static_cast (Qinit (i)); + (*current_liboctave_error_handler) + ("sparse_lu: symbolic factorization failed"); + } + else + { + umfpack_report_symbolic (Symbolic, control); - status = umfpack_qsymbolic (nr, nc, Ap, Ai, Ax, - qinit, &Symbolic, control, - info); - } - while (0); + void *Numeric; + status = umfpack_numeric (Ap, Ai, Ax, Symbolic, + &Numeric, control, info); + umfpack_free_symbolic (&Symbolic); + + m_cond = Info (UMFPACK_RCOND); if (status < 0) { umfpack_report_status (control, status); umfpack_report_info (control, info); - umfpack_free_symbolic (&Symbolic); + umfpack_free_numeric (&Numeric); (*current_liboctave_error_handler) - ("sparse_lu: symbolic factorization failed"); + ("sparse_lu: numeric factorization failed"); } else { - umfpack_report_symbolic (Symbolic, control); + umfpack_report_numeric (Numeric, control); - void *Numeric; - status = umfpack_numeric (Ap, Ai, Ax, Symbolic, - &Numeric, control, info); - umfpack_free_symbolic (&Symbolic); - - m_cond = Info (UMFPACK_RCOND); + octave_idx_type lnz, unz; + status = umfpack_get_lunz (&lnz, &unz, Numeric); if (status < 0) { @@ -737,253 +754,236 @@ umfpack_free_numeric (&Numeric); (*current_liboctave_error_handler) - ("sparse_lu: numeric factorization failed"); + ("sparse_lu: extracting LU factors failed"); } else { - umfpack_report_numeric (Numeric, control); + octave_idx_type n_inner = (nr < nc ? nr : nc); + + if (lnz < 1) + m_L = lu_type (n_inner, nr, + static_cast (1)); + else + m_L = lu_type (n_inner, nr, lnz); + + octave_idx_type *Ltp = m_L.cidx (); + octave_idx_type *Ltj = m_L.ridx (); + lu_elt_type *Ltx = m_L.data (); + + if (unz < 1) + m_U = lu_type (n_inner, nc, + static_cast (1)); + else + m_U = lu_type (n_inner, nc, unz); + + octave_idx_type *Up = m_U.cidx (); + octave_idx_type *Uj = m_U.ridx (); + lu_elt_type *Ux = m_U.data (); - octave_idx_type lnz, unz; - status = umfpack_get_lunz (&lnz, &unz, Numeric); + m_R = SparseMatrix (nr, nr, nr); + for (octave_idx_type i = 0; i < nr; i++) + { + m_R.xridx (i) = i; + m_R.xcidx (i) = i; + } + m_R.xcidx (nr) = nr; + double *Rx = m_R.data (); + + m_P.resize (dim_vector (nr, 1)); + octave_idx_type *p = m_P.fortran_vec (); + + m_Q.resize (dim_vector (nc, 1)); + octave_idx_type *q = m_Q.fortran_vec (); + + octave_idx_type do_recip; + status = umfpack_get_numeric (Ltp, Ltj, Ltx, + Up, Uj, Ux, + p, q, nullptr, + &do_recip, + Rx, Numeric); + + umfpack_free_numeric (&Numeric); if (status < 0) { umfpack_report_status (control, status); - umfpack_report_info (control, info); - - umfpack_free_numeric (&Numeric); (*current_liboctave_error_handler) ("sparse_lu: extracting LU factors failed"); } else { - octave_idx_type n_inner = (nr < nc ? nr : nc); - - if (lnz < 1) - m_L = lu_type (n_inner, nr, - static_cast (1)); - else - m_L = lu_type (n_inner, nr, lnz); - - octave_idx_type *Ltp = m_L.cidx (); - octave_idx_type *Ltj = m_L.ridx (); - lu_elt_type *Ltx = m_L.data (); - - if (unz < 1) - m_U = lu_type (n_inner, nc, - static_cast (1)); - else - m_U = lu_type (n_inner, nc, unz); + m_L = m_L.transpose (); - octave_idx_type *Up = m_U.cidx (); - octave_idx_type *Uj = m_U.ridx (); - lu_elt_type *Ux = m_U.data (); - - m_R = SparseMatrix (nr, nr, nr); - for (octave_idx_type i = 0; i < nr; i++) - { - m_R.xridx (i) = i; - m_R.xcidx (i) = i; - } - m_R.xcidx (nr) = nr; - double *Rx = m_R.data (); - - m_P.resize (dim_vector (nr, 1)); - octave_idx_type *p = m_P.fortran_vec (); - - m_Q.resize (dim_vector (nc, 1)); - octave_idx_type *q = m_Q.fortran_vec (); + if (do_recip) + for (octave_idx_type i = 0; i < nr; i++) + Rx[i] = 1.0 / Rx[i]; - octave_idx_type do_recip; - status = umfpack_get_numeric (Ltp, Ltj, Ltx, - Up, Uj, Ux, - p, q, nullptr, - &do_recip, - Rx, Numeric); - - umfpack_free_numeric (&Numeric); - - if (status < 0) - { - umfpack_report_status (control, status); - - (*current_liboctave_error_handler) - ("sparse_lu: extracting LU factors failed"); - } - else - { - m_L = m_L.transpose (); + umfpack_report_matrix (nr, n_inner, + m_L.cidx (), + m_L.ridx (), + m_L.data (), + static_cast (1), + control); + umfpack_report_matrix (n_inner, nc, + m_U.cidx (), + m_U.ridx (), + m_U.data (), + static_cast (1), + control); + umfpack_report_perm (nr, p, control); + umfpack_report_perm (nc, q, control); + } - if (do_recip) - for (octave_idx_type i = 0; i < nr; i++) - Rx[i] = 1.0 / Rx[i]; - - umfpack_report_matrix (nr, n_inner, - m_L.cidx (), - m_L.ridx (), - m_L.data (), - static_cast (1), - control); - umfpack_report_matrix (n_inner, nc, - m_U.cidx (), - m_U.ridx (), - m_U.data (), - static_cast (1), - control); - umfpack_report_perm (nr, p, control); - umfpack_report_perm (nc, q, control); - } - - umfpack_report_info (control, info); - } + umfpack_report_info (control, info); } } + } - if (udiag) - (*current_liboctave_error_handler) - ("Option udiag of incomplete LU not implemented"); + if (udiag) + (*current_liboctave_error_handler) + ("Option udiag of incomplete LU not implemented"); #else - octave_unused_parameter (a); - octave_unused_parameter (Qinit); - octave_unused_parameter (piv_thres); - octave_unused_parameter (scale); - octave_unused_parameter (FixedQ); - octave_unused_parameter (droptol); - octave_unused_parameter (milu); - octave_unused_parameter (udiag); + octave_unused_parameter (a); + octave_unused_parameter (Qinit); + octave_unused_parameter (piv_thres); + octave_unused_parameter (scale); + octave_unused_parameter (FixedQ); + octave_unused_parameter (droptol); + octave_unused_parameter (milu); + octave_unused_parameter (udiag); - (*current_liboctave_error_handler) - ("support for UMFPACK was unavailable or disabled when liboctave was built"); + (*current_liboctave_error_handler) + ("support for UMFPACK was unavailable or disabled when liboctave was built"); #endif - } +} - template - lu_type - sparse_lu::Y (void) const +template +lu_type +sparse_lu::Y (void) const +{ + octave_idx_type nr = m_L.rows (); + octave_idx_type nz = m_L.cols (); + octave_idx_type nc = m_U.cols (); + + lu_type Yout (nr, nc, m_L.nnz () + m_U.nnz () - (nr - SparseMatrix - sparse_lu::Pr (void) const - { - octave_idx_type nr = m_L.rows (); - - SparseMatrix Pout (nr, nr, nr); - - for (octave_idx_type i = 0; i < nr; i++) + if (j < nz) { - Pout.cidx (i) = i; - Pout.ridx (m_P(i)) = i; - Pout.data (i) = 1; + // Note the +1 skips the 1.0 on the diagonal + for (octave_idx_type i = m_L.cidx (j) + 1; + i < m_L.cidx (j +1); i++) + { + Yout.xridx (ii) = m_L.ridx (i); + Yout.xdata (ii++) = m_L.data (i); + } } - Pout.cidx (nr) = nr; - - return Pout; + Yout.xcidx (j + 1) = ii; } - template - ColumnVector - sparse_lu::Pr_vec (void) const - { - octave_idx_type nr = m_L.rows (); - - ColumnVector Pout (nr); + return Yout; +} - for (octave_idx_type i = 0; i < nr; i++) - Pout.xelem (i) = static_cast (m_P(i) + 1); - - return Pout; - } +template +SparseMatrix +sparse_lu::Pr (void) const +{ + octave_idx_type nr = m_L.rows (); - template - PermMatrix - sparse_lu::Pr_mat (void) const + SparseMatrix Pout (nr, nr, nr); + + for (octave_idx_type i = 0; i < nr; i++) { - return PermMatrix (m_P, false); + Pout.cidx (i) = i; + Pout.ridx (m_P(i)) = i; + Pout.data (i) = 1; } - template - SparseMatrix - sparse_lu::Pc (void) const - { - octave_idx_type nc = m_U.cols (); + Pout.cidx (nr) = nr; + + return Pout; +} - SparseMatrix Pout (nc, nc, nc); +template +ColumnVector +sparse_lu::Pr_vec (void) const +{ + octave_idx_type nr = m_L.rows (); + + ColumnVector Pout (nr); + + for (octave_idx_type i = 0; i < nr; i++) + Pout.xelem (i) = static_cast (m_P(i) + 1); + + return Pout; +} - for (octave_idx_type i = 0; i < nc; i++) - { - Pout.cidx (i) = i; - Pout.ridx (i) = m_Q(i); - Pout.data (i) = 1; - } +template +PermMatrix +sparse_lu::Pr_mat (void) const +{ + return PermMatrix (m_P, false); +} - Pout.cidx (nc) = nc; +template +SparseMatrix +sparse_lu::Pc (void) const +{ + octave_idx_type nc = m_U.cols (); - return Pout; + SparseMatrix Pout (nc, nc, nc); + + for (octave_idx_type i = 0; i < nc; i++) + { + Pout.cidx (i) = i; + Pout.ridx (i) = m_Q(i); + Pout.data (i) = 1; } - template - ColumnVector - sparse_lu::Pc_vec (void) const - { - octave_idx_type nc = m_U.cols (); + Pout.cidx (nc) = nc; + + return Pout; +} - ColumnVector Pout (nc); +template +ColumnVector +sparse_lu::Pc_vec (void) const +{ + octave_idx_type nc = m_U.cols (); - for (octave_idx_type i = 0; i < nc; i++) - Pout.xelem (i) = static_cast (m_Q(i) + 1); + ColumnVector Pout (nc); - return Pout; - } + for (octave_idx_type i = 0; i < nc; i++) + Pout.xelem (i) = static_cast (m_Q(i) + 1); + + return Pout; +} - template - PermMatrix - sparse_lu::Pc_mat (void) const - { - return PermMatrix (m_Q, true); - } +template +PermMatrix +sparse_lu::Pc_mat (void) const +{ + return PermMatrix (m_Q, true); +} - // Instantiations we need. - template class OCTAVE_API sparse_lu; +// Instantiations we need. +template class OCTAVE_API sparse_lu; - template class OCTAVE_API sparse_lu; +template class OCTAVE_API sparse_lu; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/sparse-lu.h --- a/liboctave/numeric/sparse-lu.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/sparse-lu.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,91 +38,91 @@ OCTAVE_BEGIN_NAMESPACE(math) - // If the sparse matrix classes become templated on the element type - // (i.e., sparse_matrix), then it might be best to make the - // template parameter of this class also be the element type instead - // of the matrix type. +// If the sparse matrix classes become templated on the element type +// (i.e., sparse_matrix), then it might be best to make the +// template parameter of this class also be the element type instead +// of the matrix type. - template - class - OCTAVE_API - sparse_lu - { - public: +template +class +OCTAVE_API +sparse_lu +{ +public: - typedef typename lu_type::element_type lu_elt_type; + typedef typename lu_type::element_type lu_elt_type; - sparse_lu (void) - : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () { } + sparse_lu (void) + : m_L (), m_U (), m_R (), m_cond (0), m_P (), m_Q () { } - OCTAVE_API - sparse_lu (const lu_type& a, const Matrix& piv_thres = Matrix (), - bool scale = false); + OCTAVE_API + sparse_lu (const lu_type& a, const Matrix& piv_thres = Matrix (), + bool scale = false); - OCTAVE_API - sparse_lu (const lu_type& a, const ColumnVector& Qinit, - const Matrix& piv_thres, bool scale = false, - bool FixedQ = false, double droptol = -1.0, - bool milu = false, bool udiag = false); - - sparse_lu (const sparse_lu& a) - : m_L (a.m_L), m_U (a.m_U), m_R (), - m_cond (a.m_cond), m_P (a.m_P), m_Q (a.m_Q) - { } + OCTAVE_API + sparse_lu (const lu_type& a, const ColumnVector& Qinit, + const Matrix& piv_thres, bool scale = false, + bool FixedQ = false, double droptol = -1.0, + bool milu = false, bool udiag = false); - sparse_lu& operator = (const sparse_lu& a) + sparse_lu (const sparse_lu& a) + : m_L (a.m_L), m_U (a.m_U), m_R (), + m_cond (a.m_cond), m_P (a.m_P), m_Q (a.m_Q) + { } + + sparse_lu& operator = (const sparse_lu& a) + { + if (this != &a) { - if (this != &a) - { - m_L = a.m_L; - m_U = a.m_U; - m_cond = a.m_cond; - m_P = a.m_P; - m_Q = a.m_Q; - } - - return *this; + m_L = a.m_L; + m_U = a.m_U; + m_cond = a.m_cond; + m_P = a.m_P; + m_Q = a.m_Q; } - virtual ~sparse_lu (void) = default; - - lu_type L (void) const { return m_L; } + return *this; + } - lu_type U (void) const { return m_U; } + virtual ~sparse_lu (void) = default; - SparseMatrix R (void) const { return m_R; } + lu_type L (void) const { return m_L; } - OCTAVE_API lu_type Y (void) const; + lu_type U (void) const { return m_U; } - OCTAVE_API SparseMatrix Pc (void) const; + SparseMatrix R (void) const { return m_R; } - OCTAVE_API SparseMatrix Pr (void) const; + OCTAVE_API lu_type Y (void) const; + + OCTAVE_API SparseMatrix Pc (void) const; - OCTAVE_API ColumnVector Pc_vec (void) const; + OCTAVE_API SparseMatrix Pr (void) const; - OCTAVE_API ColumnVector Pr_vec (void) const; + OCTAVE_API ColumnVector Pc_vec (void) const; - OCTAVE_API PermMatrix Pc_mat (void) const; + OCTAVE_API ColumnVector Pr_vec (void) const; - OCTAVE_API PermMatrix Pr_mat (void) const; + OCTAVE_API PermMatrix Pc_mat (void) const; - const octave_idx_type * row_perm (void) const { return m_P.data (); } + OCTAVE_API PermMatrix Pr_mat (void) const; - const octave_idx_type * col_perm (void) const { return m_Q.data (); } + const octave_idx_type * row_perm (void) const { return m_P.data (); } - double rcond (void) const { return m_cond; } + const octave_idx_type * col_perm (void) const { return m_Q.data (); } - protected: + double rcond (void) const { return m_cond; } - lu_type m_L; - lu_type m_U; - SparseMatrix m_R; +protected: + + lu_type m_L; + lu_type m_U; + SparseMatrix m_R; - double m_cond; + double m_cond; - MArray m_P; - MArray m_Q; - }; + MArray m_P; + MArray m_Q; +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/sparse-qr.cc --- a/liboctave/numeric/sparse-qr.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/sparse-qr.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,3311 +44,3311 @@ OCTAVE_BEGIN_NAMESPACE(math) #if defined (HAVE_CXSPARSE) - template - class - cxsparse_types - { }; - - template <> - class - cxsparse_types - { - public: - typedef CXSPARSE_DNAME (s) symbolic_type; - typedef CXSPARSE_DNAME (n) numeric_type; - }; - - template <> - class - cxsparse_types - { - public: - typedef CXSPARSE_ZNAME (s) symbolic_type; - typedef CXSPARSE_ZNAME (n) numeric_type; - }; +template +class +cxsparse_types +{ }; + +template <> +class +cxsparse_types +{ +public: + typedef CXSPARSE_DNAME (s) symbolic_type; + typedef CXSPARSE_DNAME (n) numeric_type; +}; + +template <> +class +cxsparse_types +{ +public: + typedef CXSPARSE_ZNAME (s) symbolic_type; + typedef CXSPARSE_ZNAME (n) numeric_type; +}; #endif - template - class sparse_qr::sparse_qr_rep - { - public: - - sparse_qr_rep (const SPARSE_T& a, int order); - - // No copying! - - sparse_qr_rep (const sparse_qr_rep&) = delete; - - sparse_qr_rep& operator = (const sparse_qr_rep&) = delete; - - ~sparse_qr_rep (void); - - bool ok (void) const - { +template +class sparse_qr::sparse_qr_rep +{ +public: + + sparse_qr_rep (const SPARSE_T& a, int order); + + // No copying! + + sparse_qr_rep (const sparse_qr_rep&) = delete; + + sparse_qr_rep& operator = (const sparse_qr_rep&) = delete; + + ~sparse_qr_rep (void); + + bool ok (void) const + { #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - return (m_H && m_Htau && m_HPinv && m_R && m_E); + return (m_H && m_Htau && m_HPinv && m_R && m_E); #elif defined (HAVE_CXSPARSE) - return (N && S); + return (N && S); #else - return false; + return false; #endif - } - - SPARSE_T V (void) const; - - ColumnVector Pinv (void) const; - - ColumnVector P (void) const; - - ColumnVector E (void) const; - - SPARSE_T R (bool econ) const; - - typename SPARSE_T::dense_matrix_type - C (const typename SPARSE_T::dense_matrix_type& b, bool econ = false); - - typename SPARSE_T::dense_matrix_type Q (bool econ = false); - - octave_idx_type nrows; - octave_idx_type ncols; + } + + SPARSE_T V (void) const; + + ColumnVector Pinv (void) const; + + ColumnVector P (void) const; + + ColumnVector E (void) const; + + SPARSE_T R (bool econ) const; + + typename SPARSE_T::dense_matrix_type + C (const typename SPARSE_T::dense_matrix_type& b, bool econ = false); + + typename SPARSE_T::dense_matrix_type Q (bool econ = false); + + octave_idx_type nrows; + octave_idx_type ncols; #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - template - RET_T solve (const RHS_T& b, octave_idx_type& info) const; + template + RET_T solve (const RHS_T& b, octave_idx_type& info) const; #endif #if defined (HAVE_CXSPARSE) - typename cxsparse_types::symbolic_type *S; - typename cxsparse_types::numeric_type *N; + typename cxsparse_types::symbolic_type *S; + typename cxsparse_types::numeric_type *N; #endif - template - RET_T tall_solve (const RHS_T& b, octave_idx_type& info); - - template - RET_T wide_solve (const RHS_T& b, octave_idx_type& info) const; + template + RET_T tall_solve (const RHS_T& b, octave_idx_type& info); + + template + RET_T wide_solve (const RHS_T& b, octave_idx_type& info) const; #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - private: - - cholmod_common m_cc; - cholmod_sparse *m_R; // R factor - // Column permutation for A. Fill-reducing ordering. - SuiteSparse_long *m_E; - cholmod_sparse *m_H; // Householder vectors - cholmod_dense *m_Htau; // beta scalars - SuiteSparse_long *m_HPinv; +private: + + cholmod_common m_cc; + cholmod_sparse *m_R; // R factor + // Column permutation for A. Fill-reducing ordering. + SuiteSparse_long *m_E; + cholmod_sparse *m_H; // Householder vectors + cholmod_dense *m_Htau; // beta scalars + SuiteSparse_long *m_HPinv; #endif - }; - - template - ColumnVector - sparse_qr::sparse_qr_rep::Pinv (void) const - { +}; + +template +ColumnVector +sparse_qr::sparse_qr_rep::Pinv (void) const +{ #if defined (HAVE_CXSPARSE) - ColumnVector ret (N->L->m); - - for (octave_idx_type i = 0; i < N->L->m; i++) - ret.xelem (i) = S->pinv[i]; - - return ret; + ColumnVector ret (N->L->m); + + for (octave_idx_type i = 0; i < N->L->m; i++) + ret.xelem (i) = S->pinv[i]; + + return ret; #else - return ColumnVector (); + return ColumnVector (); #endif - } - - template - ColumnVector - sparse_qr::sparse_qr_rep::P (void) const - { +} + +template +ColumnVector +sparse_qr::sparse_qr_rep::P (void) const +{ #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - ColumnVector ret (nrows); - - // FIXME: Is ret.xelem (m_HPinv[i]) = i + 1 correct? - for (octave_idx_type i = 0; i < nrows; i++) - ret.xelem (from_suitesparse_long (m_HPinv[i])) = i + 1; - - return ret; + ColumnVector ret (nrows); + + // FIXME: Is ret.xelem (m_HPinv[i]) = i + 1 correct? + for (octave_idx_type i = 0; i < nrows; i++) + ret.xelem (from_suitesparse_long (m_HPinv[i])) = i + 1; + + return ret; #elif defined (HAVE_CXSPARSE) - ColumnVector ret (N->L->m); - - for (octave_idx_type i = 0; i < N->L->m; i++) - ret.xelem (S->pinv[i]) = i; - - return ret; + ColumnVector ret (N->L->m); + + for (octave_idx_type i = 0; i < N->L->m; i++) + ret.xelem (S->pinv[i]) = i; + + return ret; #else - return ColumnVector (); + return ColumnVector (); #endif - } - - template - ColumnVector - sparse_qr::sparse_qr_rep::E (void) const - { +} + +template +ColumnVector +sparse_qr::sparse_qr_rep::E (void) const +{ #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - ColumnVector ret (ncols); - - if (m_E) - for (octave_idx_type i = 0; i < ncols; i++) - ret(i) = from_suitesparse_long (m_E[i]) + 1; - else - for (octave_idx_type i = 0; i < ncols; i++) - ret(i) = i + 1; - - return ret; + ColumnVector ret (ncols); + + if (m_E) + for (octave_idx_type i = 0; i < ncols; i++) + ret(i) = from_suitesparse_long (m_E[i]) + 1; + else + for (octave_idx_type i = 0; i < ncols; i++) + ret(i) = i + 1; + + return ret; #else - return ColumnVector (); + return ColumnVector (); #endif - } +} #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - // Convert real sparse octave matrix to real sparse cholmod matrix. - // Returns a "shallow" copy of a. - static cholmod_sparse - ros2rcs (const SparseMatrix& a) +// Convert real sparse octave matrix to real sparse cholmod matrix. +// Returns a "shallow" copy of a. +static cholmod_sparse +ros2rcs (const SparseMatrix& a) +{ + cholmod_sparse A; + + octave_idx_type ncols = a.cols (); + octave_idx_type nnz = a.nnz (); + + A.ncol = ncols; + A.nrow = a.rows (); + A.itype = CHOLMOD_LONG; + A.nzmax = nnz; + A.sorted = 0; + A.packed = 1; + A.stype = 0; + A.xtype = CHOLMOD_REAL; + A.dtype = CHOLMOD_DOUBLE; + A.nz = nullptr; + A.z = nullptr; + if (sizeof (octave_idx_type) == sizeof (SuiteSparse_long)) + { + A.p = reinterpret_cast (a.cidx ()); + A.i = reinterpret_cast (a.ridx ()); + } + else { - cholmod_sparse A; - - octave_idx_type ncols = a.cols (); - octave_idx_type nnz = a.nnz (); - - A.ncol = ncols; - A.nrow = a.rows (); - A.itype = CHOLMOD_LONG; - A.nzmax = nnz; - A.sorted = 0; - A.packed = 1; - A.stype = 0; - A.xtype = CHOLMOD_REAL; - A.dtype = CHOLMOD_DOUBLE; - A.nz = nullptr; - A.z = nullptr; - if (sizeof (octave_idx_type) == sizeof (SuiteSparse_long)) - { - A.p = reinterpret_cast (a.cidx ()); - A.i = reinterpret_cast (a.ridx ()); - } - else - { - SuiteSparse_long *A_p; - A_p = new SuiteSparse_long[ncols+1]; - for (octave_idx_type i = 0; i < ncols+1; i++) - A_p[i] = a.cidx (i); - A.p = A_p; - SuiteSparse_long *A_i; - A_i = new SuiteSparse_long[nnz]; - for (octave_idx_type i = 0; i < nnz; i++) - A_i[i] = a.ridx (i); - A.i = A_i; - } - A.x = const_cast (a.data ()); - - return A; + SuiteSparse_long *A_p; + A_p = new SuiteSparse_long[ncols+1]; + for (octave_idx_type i = 0; i < ncols+1; i++) + A_p[i] = a.cidx (i); + A.p = A_p; + SuiteSparse_long *A_i; + A_i = new SuiteSparse_long[nnz]; + for (octave_idx_type i = 0; i < nnz; i++) + A_i[i] = a.ridx (i); + A.i = A_i; } - - // Convert complex sparse octave matrix to complex sparse cholmod matrix. - // Returns a "shallow" copy of a. - static cholmod_sparse - cos2ccs (const SparseComplexMatrix& a) + A.x = const_cast (a.data ()); + + return A; +} + +// Convert complex sparse octave matrix to complex sparse cholmod matrix. +// Returns a "shallow" copy of a. +static cholmod_sparse +cos2ccs (const SparseComplexMatrix& a) +{ + cholmod_sparse A; + + octave_idx_type ncols = a.cols (); + octave_idx_type nnz = a.nnz (); + + A.ncol = ncols; + A.nrow = a.rows (); + A.itype = CHOLMOD_LONG; + A.nzmax = nnz; + A.sorted = 0; + A.packed = 1; + A.stype = 0; + A.xtype = CHOLMOD_COMPLEX; + A.dtype = CHOLMOD_DOUBLE; + A.nz = nullptr; + A.z = nullptr; + if (sizeof (octave_idx_type) == sizeof (SuiteSparse_long)) + { + A.p = reinterpret_cast (a.cidx ()); + A.i = reinterpret_cast (a.ridx ()); + } + else { - cholmod_sparse A; - - octave_idx_type ncols = a.cols (); - octave_idx_type nnz = a.nnz (); - - A.ncol = ncols; - A.nrow = a.rows (); - A.itype = CHOLMOD_LONG; - A.nzmax = nnz; - A.sorted = 0; - A.packed = 1; - A.stype = 0; - A.xtype = CHOLMOD_COMPLEX; - A.dtype = CHOLMOD_DOUBLE; - A.nz = nullptr; - A.z = nullptr; - if (sizeof (octave_idx_type) == sizeof (SuiteSparse_long)) - { - A.p = reinterpret_cast (a.cidx ()); - A.i = reinterpret_cast (a.ridx ()); - } - else - { - SuiteSparse_long *A_p; - A_p = new SuiteSparse_long[ncols+1]; - for (octave_idx_type i = 0; i < ncols+1; i++) - A_p[i] = a.cidx (i); - A.p = A_p; - SuiteSparse_long *A_i; - A_i = new SuiteSparse_long[nnz]; - for (octave_idx_type i = 0; i < nnz; i++) - A_i[i] = a.ridx (i); - A.i = A_i; - } - A.x = const_cast - (reinterpret_cast (a.data ())); - - return A; + SuiteSparse_long *A_p; + A_p = new SuiteSparse_long[ncols+1]; + for (octave_idx_type i = 0; i < ncols+1; i++) + A_p[i] = a.cidx (i); + A.p = A_p; + SuiteSparse_long *A_i; + A_i = new SuiteSparse_long[nnz]; + for (octave_idx_type i = 0; i < nnz; i++) + A_i[i] = a.ridx (i); + A.i = A_i; } - - // Convert real dense octave matrix to complex dense cholmod matrix. - // Returns a "deep" copy of a. - static cholmod_dense * - rod2ccd (const MArray& a, cholmod_common *cc1) + A.x = const_cast + (reinterpret_cast (a.data ())); + + return A; +} + +// Convert real dense octave matrix to complex dense cholmod matrix. +// Returns a "deep" copy of a. +static cholmod_dense * +rod2ccd (const MArray& a, cholmod_common *cc1) +{ + cholmod_dense *A + = cholmod_l_allocate_dense (a.rows (), a.cols (), a.rows(), + CHOLMOD_COMPLEX, cc1); + + const double *a_x = a.data (); + + Complex *A_x = reinterpret_cast (A->x); + for (octave_idx_type j = 0; j < a.cols() * a.rows() ; j++) + A_x[j] = Complex (a_x[j], 0.0); + + return A; +} + +// Convert real dense octave matrix to real dense cholmod matrix. +// Returns a "shallow" copy of a. +static cholmod_dense +rod2rcd (const MArray& a) +{ + cholmod_dense A; + + A.ncol = a.cols (); + A.nrow = a.rows (); + A.nzmax = a.cols () * a.rows (); + A.xtype = CHOLMOD_REAL; + A.dtype = CHOLMOD_DOUBLE; + A.z = nullptr; + A.d = a.rows (); + A.x = const_cast (a.data ()); + + return A; +} + +// Convert complex dense octave matrix to complex dense cholmod matrix. +// Returns a "shallow" copy of a. +static cholmod_dense +cod2ccd (const ComplexMatrix& a) +{ + cholmod_dense A; + + A.ncol = a.cols (); + A.nrow = a.rows (); + A.nzmax = a.cols () * a.rows (); + A.xtype = CHOLMOD_COMPLEX; + A.dtype = CHOLMOD_DOUBLE; + A.z = nullptr; + A.d = a.rows (); + A.x = const_cast (reinterpret_cast (a.data ())); + + return A; +} + +// Convert real sparse cholmod matrix to real sparse octave matrix. +// Returns a "shallow" copy of y. +static SparseMatrix +rcs2ros (const cholmod_sparse *y) +{ + octave_idx_type nrow = from_size_t (y->nrow); + octave_idx_type ncol = from_size_t (y->ncol); + octave_idx_type nz = from_size_t (y->nzmax); + SparseMatrix ret (nrow, ncol, nz); + + SuiteSparse_long *y_p = reinterpret_cast (y->p); + for (octave_idx_type j = 0; j < ncol + 1; j++) + ret.xcidx (j) = from_suitesparse_long (y_p[j]); + + SuiteSparse_long *y_i = reinterpret_cast (y->i); + double *y_x = reinterpret_cast (y->x); + for (octave_idx_type j = 0; j < nz; j++) + { + ret.xridx (j) = from_suitesparse_long (y_i[j]); + ret.xdata (j) = y_x[j]; + } + + return ret; +} + +// Convert complex sparse cholmod matrix to complex sparse octave matrix. +// Returns a "deep" copy of a. +static SparseComplexMatrix +ccs2cos (const cholmod_sparse *a) +{ + octave_idx_type nrow = from_size_t (a->nrow); + octave_idx_type ncol = from_size_t (a->ncol); + octave_idx_type nz = from_size_t (a->nzmax); + SparseComplexMatrix ret (nrow, ncol, nz); + + SuiteSparse_long *a_p = reinterpret_cast (a->p); + for (octave_idx_type j = 0; j < ncol + 1; j++) + ret.xcidx(j) = from_suitesparse_long (a_p[j]); + + SuiteSparse_long *a_i = reinterpret_cast (a->i); + Complex *a_x = reinterpret_cast (a->x); + for (octave_idx_type j = 0; j < nz; j++) { - cholmod_dense *A - = cholmod_l_allocate_dense (a.rows (), a.cols (), a.rows(), - CHOLMOD_COMPLEX, cc1); - - const double *a_x = a.data (); - - Complex *A_x = reinterpret_cast (A->x); - for (octave_idx_type j = 0; j < a.cols() * a.rows() ; j++) - A_x[j] = Complex (a_x[j], 0.0); - - return A; + ret.xridx(j) = from_suitesparse_long (a_i[j]); + ret.xdata(j) = a_x[j]; } - // Convert real dense octave matrix to real dense cholmod matrix. - // Returns a "shallow" copy of a. - static cholmod_dense - rod2rcd (const MArray& a) + return ret; +} + +// Convert real sparse octave matrix to complex sparse cholmod matrix. +// Returns a "deep" copy of a. +static cholmod_sparse * +ros2ccs (const SparseMatrix& a, cholmod_common *cc) +{ + cholmod_sparse *A + = cholmod_l_allocate_sparse (a.rows (), a.cols (), a.nnz (), 0, 1, 0, + CHOLMOD_COMPLEX, cc); + + octave_idx_type ncol = a.cols (); + SuiteSparse_long *A_p = reinterpret_cast (A->p); + for (octave_idx_type j = 0; j < ncol + 1; j++) + A_p[j] = a.cidx(j); + + const double *a_x = a.data (); + Complex *A_x = reinterpret_cast (A->x); + SuiteSparse_long *A_i = reinterpret_cast (A->i); + for (octave_idx_type j = 0; j < a.nnz (); j++) + { + A_x[j] = Complex (a_x[j], 0.0); + A_i[j] = a.ridx(j); + } + return A; +} + +static suitesparse_integer +suitesparse_long_to_suitesparse_integer (SuiteSparse_long x) +{ + if (x < std::numeric_limits::min () + || x > std::numeric_limits::max ()) + (*current_liboctave_error_handler) + ("integer dimension or index out of range for SuiteSparse's indexing type"); + + return static_cast (x); +} + +static void +spqr_error_handler (const cholmod_common *cc) +{ + if (cc->status >= 0) + return; + + switch (cc->status) { - cholmod_dense A; - - A.ncol = a.cols (); - A.nrow = a.rows (); - A.nzmax = a.cols () * a.rows (); - A.xtype = CHOLMOD_REAL; - A.dtype = CHOLMOD_DOUBLE; - A.z = nullptr; - A.d = a.rows (); - A.x = const_cast (a.data ()); - - return A; + case CHOLMOD_OUT_OF_MEMORY: + (*current_liboctave_error_handler) + ("sparse_qr: sparse matrix QR factorization failed" + " - out of memory"); + case CHOLMOD_TOO_LARGE: + (*current_liboctave_error_handler) + ("sparse_qr: sparse matrix QR factorization failed" + " - integer overflow occurred"); + default: + (*current_liboctave_error_handler) + ("sparse_qr: sparse matrix QR factorization failed" + " - error %d", cc->status); } - // Convert complex dense octave matrix to complex dense cholmod matrix. - // Returns a "shallow" copy of a. - static cholmod_dense - cod2ccd (const ComplexMatrix& a) - { - cholmod_dense A; - - A.ncol = a.cols (); - A.nrow = a.rows (); - A.nzmax = a.cols () * a.rows (); - A.xtype = CHOLMOD_COMPLEX; - A.dtype = CHOLMOD_DOUBLE; - A.z = nullptr; - A.d = a.rows (); - A.x = const_cast (reinterpret_cast (a.data ())); - - return A; - } - - // Convert real sparse cholmod matrix to real sparse octave matrix. - // Returns a "shallow" copy of y. - static SparseMatrix - rcs2ros (const cholmod_sparse* y) + // FIXME: Free memory? + // FIXME: Can cc-status > 0 (CHOLMOD_NOT_POSDEF, CHOLMOD_DSMALL) occur? +} +#endif + +// Specializations. + +// Real-valued matrices. + +// Arguments for parameter order (taken from SuiteSparseQR documentation). +// 0: fixed ordering 0 (no permutation of columns) +// 1: natural ordering 1 (only singleton columns are permuted to the left of +// the matrix) +// 2: colamd +// 3: +// 4: CHOLMOD best-effort (COLAMD, METIS,...) +// 5: AMD(a'*a) +// 6: metis(a'*a) +// 7: SuiteSparseQR default ordering +// 8: try COLAMD, AMD, and METIS; pick best +// 9: try COLAMD and AMD; pick best +//FIXME: What is order = 3? +template <> +sparse_qr::sparse_qr_rep::sparse_qr_rep +(const SparseMatrix& a, int order) + : nrows (a.rows ()), ncols (a.columns ()) +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + , m_cc (), m_R (nullptr), m_E (nullptr), m_H (nullptr), m_Htau (nullptr), + m_HPinv (nullptr) +{ + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.cols (); + + if (nr < 0 || nc < 0) + (*current_liboctave_error_handler) + ("matrix dimension with negative size"); + + if (order < 0 || order > 9) + (*current_liboctave_error_handler) + ("ordering %d is not supported by SPQR", order); + + cholmod_l_start (&m_cc); + cholmod_sparse A = ros2rcs (a); + + SuiteSparseQR (order, static_cast (SPQR_DEFAULT_TOL), + static_cast (A.nrow), + &A, &m_R, &m_E, &m_H, &m_HPinv, &m_Htau, &m_cc); + spqr_error_handler (&m_cc); + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) { - octave_idx_type nrow = from_size_t (y->nrow); - octave_idx_type ncol = from_size_t (y->ncol); - octave_idx_type nz = from_size_t (y->nzmax); - SparseMatrix ret (nrow, ncol, nz); - - SuiteSparse_long *y_p = reinterpret_cast (y->p); - for (octave_idx_type j = 0; j < ncol + 1; j++) - ret.xcidx (j) = from_suitesparse_long (y_p[j]); - - SuiteSparse_long *y_i = reinterpret_cast (y->i); - double *y_x = reinterpret_cast (y->x); - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx (j) = from_suitesparse_long (y_i[j]); - ret.xdata (j) = y_x[j]; - } - - return ret; + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); } - - // Convert complex sparse cholmod matrix to complex sparse octave matrix. - // Returns a "deep" copy of a. - static SparseComplexMatrix - ccs2cos (const cholmod_sparse *a) +} + +#elif defined (HAVE_CXSPARSE) + , S (nullptr), N (nullptr) +{ + CXSPARSE_DNAME () A; + + A.nzmax = a.nnz (); + A.m = nrows; + A.n = ncols; + // Cast away const on A, with full knowledge that CSparse won't touch it + // Prevents the methods below making a copy of the data. + A.p = const_cast + (to_suitesparse_intptr (a.cidx ())); + A.i = const_cast + (to_suitesparse_intptr (a.ridx ())); + A.x = const_cast (a.data ()); + A.nz = -1; + + S = CXSPARSE_DNAME (_sqr) (order, &A, 1); + N = CXSPARSE_DNAME (_qr) (&A, S); + + if (! N) + (*current_liboctave_error_handler) + ("sparse_qr: sparse matrix QR factorization filled"); + +} + +#else + +{ + octave_unused_parameter (order); + + (*current_liboctave_error_handler) + ("sparse_qr: support for SPQR or CXSparse was unavailable or disabled when liboctave was built"); +} + +#endif + +template <> +sparse_qr::sparse_qr_rep::~sparse_qr_rep (void) +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + cholmod_l_free_sparse (&m_R, &m_cc); + cholmod_l_free_sparse (&m_H, &m_cc); + cholmod_l_free_dense (&m_Htau, &m_cc); + free (m_E); // FIXME: use cholmod_l_free + free (m_HPinv); + cholmod_l_finish (&m_cc); + +#elif defined (HAVE_CXSPARSE) + + CXSPARSE_DNAME (_sfree) (S); + CXSPARSE_DNAME (_nfree) (N); + +#endif +} + +template <> +SparseMatrix +sparse_qr::sparse_qr_rep::V (void) const +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + return rcs2ros (m_H); + +#elif defined (HAVE_CXSPARSE) + + // Drop zeros from V and sort + // FIXME: Is the double transpose to sort necessary? + + CXSPARSE_DNAME (_dropzeros) (N->L); + CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->L, 1); + CXSPARSE_DNAME (_spfree) (N->L); + N->L = CXSPARSE_DNAME (_transpose) (D, 1); + CXSPARSE_DNAME (_spfree) (D); + + octave_idx_type nc = N->L->n; + octave_idx_type nz = N->L->nzmax; + SparseMatrix ret (N->L->m, nc, nz); + + for (octave_idx_type j = 0; j < nc+1; j++) + ret.xcidx (j) = N->L->p[j]; + + for (octave_idx_type j = 0; j < nz; j++) { - octave_idx_type nrow = from_size_t (a->nrow); - octave_idx_type ncol = from_size_t (a->ncol); - octave_idx_type nz = from_size_t (a->nzmax); - SparseComplexMatrix ret (nrow, ncol, nz); - - SuiteSparse_long *a_p = reinterpret_cast (a->p); - for (octave_idx_type j = 0; j < ncol + 1; j++) - ret.xcidx(j) = from_suitesparse_long (a_p[j]); - - SuiteSparse_long *a_i = reinterpret_cast (a->i); - Complex *a_x = reinterpret_cast (a->x); - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx(j) = from_suitesparse_long (a_i[j]); - ret.xdata(j) = a_x[j]; - } - - return ret; + ret.xridx (j) = N->L->i[j]; + ret.xdata (j) = N->L->x[j]; } - // Convert real sparse octave matrix to complex sparse cholmod matrix. - // Returns a "deep" copy of a. - static cholmod_sparse * - ros2ccs (const SparseMatrix& a, cholmod_common *cc) + return ret; + +#else + + return SparseMatrix (); + +#endif +} + +template <> +SparseMatrix +sparse_qr::sparse_qr_rep::R (bool econ) const +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + octave_idx_type nr = static_cast (m_R->nrow); + octave_idx_type nc = static_cast (m_R->ncol); + octave_idx_type nz = static_cast (m_R->nzmax); + + // FIXME: Does this work if econ = true? + SparseMatrix ret ((econ ? (nc > nr ? nr : nc) : nr), nc, nz); + SuiteSparse_long *Rp = reinterpret_cast (m_R->p); + SuiteSparse_long *Ri = reinterpret_cast (m_R->i); + + for (octave_idx_type j = 0; j < nc + 1; j++) + ret.xcidx (j) = from_suitesparse_long (Rp[j]); + + for (octave_idx_type j = 0; j < nz; j++) { - cholmod_sparse *A - = cholmod_l_allocate_sparse (a.rows (), a.cols (), a.nnz (), 0, 1, 0, - CHOLMOD_COMPLEX, cc); - - octave_idx_type ncol = a.cols (); - SuiteSparse_long *A_p = reinterpret_cast (A->p); - for (octave_idx_type j = 0; j < ncol + 1; j++) - A_p[j] = a.cidx(j); - - const double *a_x = a.data (); - Complex *A_x = reinterpret_cast (A->x); - SuiteSparse_long *A_i = reinterpret_cast (A->i); - for (octave_idx_type j = 0; j < a.nnz (); j++) - { - A_x[j] = Complex (a_x[j], 0.0); - A_i[j] = a.ridx(j); - } - return A; + ret.xridx (j) = from_suitesparse_long (Ri[j]); + ret.xdata (j) = (reinterpret_cast (m_R->x))[j]; } - static suitesparse_integer - suitesparse_long_to_suitesparse_integer (SuiteSparse_long x) + return ret; + +#elif defined (HAVE_CXSPARSE) + + // Drop zeros from R and sort + // FIXME: Is the double transpose to sort necessary? + + CXSPARSE_DNAME (_dropzeros) (N->U); + CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->U, 1); + CXSPARSE_DNAME (_spfree) (N->U); + N->U = CXSPARSE_DNAME (_transpose) (D, 1); + CXSPARSE_DNAME (_spfree) (D); + + octave_idx_type nc = N->U->n; + octave_idx_type nz = N->U->nzmax; + + SparseMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows), nc, nz); + + for (octave_idx_type j = 0; j < nc+1; j++) + ret.xcidx (j) = N->U->p[j]; + + for (octave_idx_type j = 0; j < nz; j++) { - if (x < std::numeric_limits::min () - || x > std::numeric_limits::max ()) - (*current_liboctave_error_handler) - ("integer dimension or index out of range for SuiteSparse's indexing type"); - - return static_cast (x); + ret.xridx (j) = N->U->i[j]; + ret.xdata (j) = N->U->x[j]; } - static void - spqr_error_handler (const cholmod_common *cc) - { - if (cc->status >= 0) - return; - - switch (cc->status) - { - case CHOLMOD_OUT_OF_MEMORY: - (*current_liboctave_error_handler) - ("sparse_qr: sparse matrix QR factorization failed" - " - out of memory"); - case CHOLMOD_TOO_LARGE: - (*current_liboctave_error_handler) - ("sparse_qr: sparse matrix QR factorization failed" - " - integer overflow occurred"); - default: - (*current_liboctave_error_handler) - ("sparse_qr: sparse matrix QR factorization failed" - " - error %d", cc->status); - } - - // FIXME: Free memory? - // FIXME: Can cc-status > 0 (CHOLMOD_NOT_POSDEF, CHOLMOD_DSMALL) occur? - } + return ret; + +#else + + octave_unused_parameter (econ); + + return SparseMatrix (); + #endif - - // Specializations. - - // Real-valued matrices. - - // Arguments for parameter order (taken from SuiteSparseQR documentation). - // 0: fixed ordering 0 (no permutation of columns) - // 1: natural ordering 1 (only singleton columns are permuted to the left of - // the matrix) - // 2: colamd - // 3: - // 4: CHOLMOD best-effort (COLAMD, METIS,...) - // 5: AMD(a'*a) - // 6: metis(a'*a) - // 7: SuiteSparseQR default ordering - // 8: try COLAMD, AMD, and METIS; pick best - // 9: try COLAMD and AMD; pick best - //FIXME: What is order = 3? - template <> - sparse_qr::sparse_qr_rep::sparse_qr_rep - (const SparseMatrix& a, int order) - : nrows (a.rows ()), ncols (a.columns ()) +} + +template <> +Matrix +sparse_qr::sparse_qr_rep::C (const Matrix& b, bool econ) +{ #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - , m_cc (), m_R (nullptr), m_E (nullptr), m_H (nullptr), m_Htau (nullptr), - m_HPinv (nullptr) + octave_idx_type nr = (econ + ? (ncols > nrows ? nrows : ncols) + : nrows); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + Matrix ret (nr, b_nc); + + if (nrows != b_nr) + (*current_liboctave_error_handler) + ("sparse_qr: matrix dimension mismatch"); + else if (b_nc < 0 || b_nr < 0) + (*current_liboctave_error_handler) + ("sparse_qr: matrix dimension with negative size"); + + cholmod_dense *QTB; // Q' * B + cholmod_dense B = rod2rcd (b); + + QTB = SuiteSparseQR_qmult (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, + &m_cc); + spqr_error_handler (&m_cc); + + // copy QTB into ret + double *QTB_x = reinterpret_cast (QTB->x); + double *ret_vec = reinterpret_cast (ret.fortran_vec ()); + for (octave_idx_type j = 0; j < b_nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + ret_vec[j * nr + i] = QTB_x[j * b_nr + i]; + + cholmod_l_free_dense (&QTB, &m_cc); + + return ret; + +#elif defined (HAVE_CXSPARSE) + + if (econ) + (*current_liboctave_error_handler) + ("sparse-qr: economy mode with CXSparse not supported"); + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + octave_idx_type nc = N->L->n; + octave_idx_type nr = nrows; + + const double *bvec = b.data (); + + Matrix ret (b_nr, b_nc); + double *vec = ret.fortran_vec (); + + if (nr < 0 || nc < 0 || nr != b_nr) + (*current_liboctave_error_handler) ("matrix dimension mismatch"); + + if (nr == 0 || nc == 0 || b_nc == 0) + ret = Matrix (nc, b_nc, 0.0); + else { - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.cols (); - - if (nr < 0 || nc < 0) - (*current_liboctave_error_handler) - ("matrix dimension with negative size"); - - if (order < 0 || order > 9) - (*current_liboctave_error_handler) - ("ordering %d is not supported by SPQR", order); - - cholmod_l_start (&m_cc); - cholmod_sparse A = ros2rcs (a); - - SuiteSparseQR (order, static_cast (SPQR_DEFAULT_TOL), - static_cast (A.nrow), - &A, &m_R, &m_E, &m_H, &m_HPinv, &m_Htau, &m_cc); - spqr_error_handler (&m_cc); - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + OCTAVE_LOCAL_BUFFER (double, buf, S->m2); + + for (volatile octave_idx_type j = 0, idx = 0; + j < b_nc; + j++, idx += b_nr) { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); + octave_quit (); + + for (octave_idx_type i = nr; i < S->m2; i++) + buf[i] = 0.; + + volatile octave_idx_type nm = (nr < nc ? nr : nc); + + CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + idx, buf, b_nr); + + for (volatile octave_idx_type i = 0; i < nm; i++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf); + } + + for (octave_idx_type i = 0; i < b_nr; i++) + vec[i+idx] = buf[i]; + } + } + + return ret; + +#else + + octave_unused_parameter (b); + octave_unused_parameter (econ); + + return Matrix (); + +#endif +} + +template <> +Matrix +sparse_qr::sparse_qr_rep::Q (bool econ) +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + octave_idx_type nc = (econ + ? (ncols > nrows ? nrows : ncols) + : nrows); + Matrix ret (nrows, nc); + cholmod_dense *q; + + // I is nrows x nrows identity matrix + cholmod_dense *I + = cholmod_l_allocate_dense (nrows, nrows, nrows, CHOLMOD_REAL, &m_cc); + + for (octave_idx_type i = 0; i < nrows * nrows; i++) + (reinterpret_cast (I->x))[i] = 0.0; + + for (octave_idx_type i = 0; i < nrows; i++) + (reinterpret_cast (I->x))[i * nrows + i] = 1.0; + + q = SuiteSparseQR_qmult (SPQR_QX, m_H, m_Htau, m_HPinv, I, &m_cc); + spqr_error_handler (&m_cc); + + double *q_x = reinterpret_cast (q->x); + double *ret_vec = const_cast (ret.fortran_vec ()); + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nrows; i++) + ret_vec[j * nrows + i] = q_x[j * nrows + i]; + + cholmod_l_free_dense (&q, &m_cc); + cholmod_l_free_dense (&I, &m_cc); + + return ret; + +#elif defined (HAVE_CXSPARSE) + + if (econ) + (*current_liboctave_error_handler) + ("sparse-qr: economy mode with CXSparse not supported"); + + octave_idx_type nc = N->L->n; + octave_idx_type nr = nrows; + Matrix ret (nr, nr); + double *ret_vec = ret.fortran_vec (); + + if (nr < 0 || nc < 0) + (*current_liboctave_error_handler) ("matrix dimension mismatch"); + + if (nr == 0 || nc == 0) + ret = Matrix (nc, nr, 0.0); + else + { + OCTAVE_LOCAL_BUFFER (double, bvec, nr + 1); + + for (octave_idx_type i = 0; i < nr; i++) + bvec[i] = 0.; + + OCTAVE_LOCAL_BUFFER (double, buf, S->m2); + + for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx += nr) + { + octave_quit (); + + bvec[j] = 1.0; + for (octave_idx_type i = nr; i < S->m2; i++) + buf[i] = 0.; + + volatile octave_idx_type nm = (nr < nc ? nr : nc); + + CXSPARSE_DNAME (_ipvec) (S->pinv, bvec, buf, nr); + + for (volatile octave_idx_type i = 0; i < nm; i++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf); + } + + for (octave_idx_type i = 0; i < nr; i++) + ret_vec[i+idx] = buf[i]; + + bvec[j] = 0.0; } } -#elif defined (HAVE_CXSPARSE) - , S (nullptr), N (nullptr) - { - CXSPARSE_DNAME () A; - - A.nzmax = a.nnz (); - A.m = nrows; - A.n = ncols; - // Cast away const on A, with full knowledge that CSparse won't touch it - // Prevents the methods below making a copy of the data. - A.p = const_cast - (to_suitesparse_intptr (a.cidx ())); - A.i = const_cast - (to_suitesparse_intptr (a.ridx ())); - A.x = const_cast (a.data ()); - A.nz = -1; - - S = CXSPARSE_DNAME (_sqr) (order, &A, 1); - N = CXSPARSE_DNAME (_qr) (&A, S); - - if (! N) - (*current_liboctave_error_handler) - ("sparse_qr: sparse matrix QR factorization filled"); - - } + return ret.transpose (); #else - { - octave_unused_parameter (order); - - (*current_liboctave_error_handler) - ("sparse_qr: support for SPQR or CXSparse was unavailable or disabled when liboctave was built"); - } - -#endif - - template <> - sparse_qr::sparse_qr_rep::~sparse_qr_rep (void) - { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - cholmod_l_free_sparse (&m_R, &m_cc); - cholmod_l_free_sparse (&m_H, &m_cc); - cholmod_l_free_dense (&m_Htau, &m_cc); - free (m_E); // FIXME: use cholmod_l_free - free (m_HPinv); - cholmod_l_finish (&m_cc); - -#elif defined (HAVE_CXSPARSE) - - CXSPARSE_DNAME (_sfree) (S); - CXSPARSE_DNAME (_nfree) (N); + octave_unused_parameter (econ); + + return Matrix (); #endif - } - - template <> - SparseMatrix - sparse_qr::sparse_qr_rep::V (void) const +} + +template <> +template <> +Matrix +sparse_qr::sparse_qr_rep::tall_solve, Matrix> +(const MArray& b, octave_idx_type& info) +{ + info = -1; + +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD) && defined (HAVE_CXSPARSE)) + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + Matrix x (ncols, b_nc); // X = m_E'*(m_R\(Q'*B)) + + if (nrows < 0 || ncols < 0 || b_nc < 0 || b_nr < 0) + (*current_liboctave_error_handler) + ("matrix dimension with negative size"); + + if (nrows < 0 || ncols < 0 || nrows != b_nr) + (*current_liboctave_error_handler) ("matrix dimension mismatch"); + + cholmod_dense *QTB; // Q' * B + cholmod_dense B = rod2rcd (b); + + // FIXME: Process b column by column as in the CXSPARSE version below. + // This avoids a large dense matrix Q' * B in memory. + QTB = SuiteSparseQR_qmult (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, + &m_cc); + + spqr_error_handler (&m_cc); + + // convert m_R into CXSPARSE matrix R2 + CXSPARSE_DNAME (_sparse) R2; + R2.n = ncols; + R2.m = ncols; + R2.nzmax = m_R->nzmax; + R2.x = reinterpret_cast (m_R->x); + suitesparse_integer *R2_p; + suitesparse_integer *R2_i; + if (sizeof (suitesparse_integer) == sizeof (SuiteSparse_long)) { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - return rcs2ros (m_H); - -#elif defined (HAVE_CXSPARSE) - - // Drop zeros from V and sort - // FIXME: Is the double transpose to sort necessary? - - CXSPARSE_DNAME (_dropzeros) (N->L); - CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->L, 1); - CXSPARSE_DNAME (_spfree) (N->L); - N->L = CXSPARSE_DNAME (_transpose) (D, 1); - CXSPARSE_DNAME (_spfree) (D); - - octave_idx_type nc = N->L->n; - octave_idx_type nz = N->L->nzmax; - SparseMatrix ret (N->L->m, nc, nz); - - for (octave_idx_type j = 0; j < nc+1; j++) - ret.xcidx (j) = N->L->p[j]; - - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx (j) = N->L->i[j]; - ret.xdata (j) = N->L->x[j]; - } - - return ret; - -#else - - return SparseMatrix (); - -#endif + R2.p = reinterpret_cast (m_R->p); + R2.i = reinterpret_cast (m_R->i); + } + else + { + R2_p = new suitesparse_integer[ncols+1]; + SuiteSparse_long *R_p = reinterpret_cast (m_R->p); + for (octave_idx_type i = 0; i < ncols+1; i++) + R2_p[i] = suitesparse_long_to_suitesparse_integer (R_p[i]); + R2.p = R2_p; + octave_idx_type nnz = m_R->nzmax; + R2_i = new suitesparse_integer[nnz]; + SuiteSparse_long *R_i = reinterpret_cast (m_R->i); + for (octave_idx_type i = 0; i < nnz; i++) + R2_i[i] = suitesparse_long_to_suitesparse_integer (R_i[i]); + R2.i = R2_i; + } + R2.nz = -1; + double *x_vec = const_cast (x.fortran_vec ()); + suitesparse_integer *E; + if (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long)) + { + E = new suitesparse_integer [ncols]; + for (octave_idx_type i = 0; i < ncols; i++) + E[i] = suitesparse_long_to_suitesparse_integer (m_E[i]); } - - template <> - SparseMatrix - sparse_qr::sparse_qr_rep::R (bool econ) const + else + E = reinterpret_cast (m_E); + for (volatile octave_idx_type j = 0; j < b_nc; j++) { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - octave_idx_type nr = static_cast (m_R->nrow); - octave_idx_type nc = static_cast (m_R->ncol); - octave_idx_type nz = static_cast (m_R->nzmax); - - // FIXME: Does this work if econ = true? - SparseMatrix ret ((econ ? (nc > nr ? nr : nc) : nr), nc, nz); - SuiteSparse_long *Rp = reinterpret_cast (m_R->p); - SuiteSparse_long *Ri = reinterpret_cast (m_R->i); - - for (octave_idx_type j = 0; j < nc + 1; j++) - ret.xcidx (j) = from_suitesparse_long (Rp[j]); - - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx (j) = from_suitesparse_long (Ri[j]); - ret.xdata (j) = (reinterpret_cast (m_R->x))[j]; - } - - return ret; + // fill x(:,j) + // solve (m_R\(Q'*B(:,j)) and store result in QTB(:,j) + CXSPARSE_DNAME (_usolve) + (&R2, &(reinterpret_cast (QTB->x)[j * b_nr])); + // x(:,j) = m_E' * (m_R\(Q'*B(:,j)) + CXSPARSE_DNAME (_ipvec) + (E, &(reinterpret_cast (QTB->x)[j * b_nr]), + &x_vec[j * ncols], ncols); + } + + if (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long)) + { + delete [] R2_p; + delete [] R2_i; + delete [] E; + } + cholmod_l_free_dense (&QTB, &m_cc); + + info = 0; + + return x; #elif defined (HAVE_CXSPARSE) - // Drop zeros from R and sort - // FIXME: Is the double transpose to sort necessary? - - CXSPARSE_DNAME (_dropzeros) (N->U); - CXSPARSE_DNAME () *D = CXSPARSE_DNAME (_transpose) (N->U, 1); - CXSPARSE_DNAME (_spfree) (N->U); - N->U = CXSPARSE_DNAME (_transpose) (D, 1); - CXSPARSE_DNAME (_spfree) (D); - - octave_idx_type nc = N->U->n; - octave_idx_type nz = N->U->nzmax; - - SparseMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows), nc, nz); - - for (octave_idx_type j = 0; j < nc+1; j++) - ret.xcidx (j) = N->U->p[j]; - - for (octave_idx_type j = 0; j < nz; j++) + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + const double *bvec = b.data (); + + Matrix x (nc, b_nc); + double *vec = x.fortran_vec (); + + OCTAVE_LOCAL_BUFFER (double, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; + i++, idx+=nc, bidx+=b_nr) + { + octave_quit (); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) { - ret.xridx (j) = N->U->i[j]; - ret.xdata (j) = N->U->x[j]; + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); } - return ret; + CXSPARSE_DNAME (_usolve) (N->U, buf); + CXSPARSE_DNAME (_ipvec) (S->q, buf, vec + idx, nc); + } + + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return Matrix (); + +#endif +} + +template <> +template <> +Matrix +sparse_qr::sparse_qr_rep::wide_solve, Matrix> +(const MArray& b, octave_idx_type& info) const +{ + info = -1; +#if defined (HAVE_CXSPARSE) + + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + const double *bvec = b.data (); + + Matrix x (nc, b_nc); + double *vec = x.fortran_vec (); + + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); + + for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; + i++, idx+=nc, bidx+=b_nr) + { + octave_quit (); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_pvec) (S->q, bvec + bidx, buf, nr); + CXSPARSE_DNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_pvec) (S->pinv, buf, vec + idx, nc); + } + + info = 0; + + return x; #else - - octave_unused_parameter (econ); - - return SparseMatrix (); + octave_unused_parameter (b); + + return Matrix (); + +#endif +} + +template <> +template <> +SparseMatrix +sparse_qr::sparse_qr_rep::tall_solve +(const SparseMatrix& b, octave_idx_type& info) +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + SparseMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_usolve) (N->U, buf); + CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + double tmp = Xx[j]; + + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; + } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; + } + } + + x.xcidx (i+1) = ii; + } + + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return SparseMatrix (); + +#endif +} + +template <> +template <> +SparseMatrix +sparse_qr::sparse_qr_rep::wide_solve +(const SparseMatrix& b, octave_idx_type& info) const +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + SparseMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr); + CXSPARSE_DNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + double tmp = Xx[j]; + + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; + } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; + } + } + + x.xcidx (i+1) = ii; + } + + info = 0; + + x.maybe_compress (); + + return x; + +#else + + octave_unused_parameter (b); + + return SparseMatrix (); #endif +} + +template <> +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::tall_solve, ComplexMatrix> +(const MArray& b, octave_idx_type& info) +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + ComplexMatrix x (nc, b_nc); + Complex *vec = x.fortran_vec (); + + OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + { + Complex c = b.xelem (j, i); + Xx[j] = c.real (); + Xz[j] = c.imag (); + } + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_usolve) (N->U, buf); + CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_usolve) (N->U, buf); + CXSPARSE_DNAME (_ipvec) (S->q, buf, Xz, nc); + + for (octave_idx_type j = 0; j < nc; j++) + vec[j+idx] = Complex (Xx[j], Xz[j]); } - template <> - Matrix - sparse_qr::sparse_qr_rep::C (const Matrix& b, bool econ) + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return ComplexMatrix (); + +#endif +} + +template <> +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::wide_solve, ComplexMatrix> +(const MArray& b, octave_idx_type& info) const +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + ComplexMatrix x (nc, b_nc); + Complex *vec = x.fortran_vec (); + + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + { + Complex c = b.xelem (j, i); + Xx[j] = c.real (); + Xz[j] = c.imag (); + } + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr); + CXSPARSE_DNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr); + CXSPARSE_DNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xz, nc); + + for (octave_idx_type j = 0; j < nc; j++) + vec[j+idx] = Complex (Xx[j], Xz[j]); + } + + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return ComplexMatrix (); + +#endif +} + +// Complex-valued matrices. + +template <> +sparse_qr::sparse_qr_rep::sparse_qr_rep +(const SparseComplexMatrix& a, int order) + : nrows (a.rows ()), ncols (a.columns ()) #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - octave_idx_type nr = (econ - ? (ncols > nrows ? nrows : ncols) - : nrows); - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - Matrix ret (nr, b_nc); - - if (nrows != b_nr) - (*current_liboctave_error_handler) - ("sparse_qr: matrix dimension mismatch"); - else if (b_nc < 0 || b_nr < 0) - (*current_liboctave_error_handler) - ("sparse_qr: matrix dimension with negative size"); - - cholmod_dense *QTB; // Q' * B - cholmod_dense B = rod2rcd (b); - - QTB = SuiteSparseQR_qmult (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, - &m_cc); - spqr_error_handler (&m_cc); - - // copy QTB into ret - double *QTB_x = reinterpret_cast (QTB->x); - double *ret_vec = reinterpret_cast (ret.fortran_vec ()); - for (octave_idx_type j = 0; j < b_nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - ret_vec[j * nr + i] = QTB_x[j * b_nr + i]; - - cholmod_l_free_dense (&QTB, &m_cc); - - return ret; + , m_cc (), m_R (nullptr), m_E (nullptr), m_H (nullptr), + m_Htau (nullptr), m_HPinv (nullptr) +{ + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.cols (); + + if (nr < 0 || nc < 0) + (*current_liboctave_error_handler) + ("matrix dimension with negative size"); + + if (order < 0 || order > 9) + (*current_liboctave_error_handler) + ("ordering %d is not supported by SPQR", order); + + cholmod_l_start (&m_cc); + cholmod_sparse A = cos2ccs (a); + + SuiteSparseQR (order, static_cast (SPQR_DEFAULT_TOL), + static_cast (A.nrow), + &A, &m_R, &m_E, &m_H, + &m_HPinv, &m_Htau, &m_cc); + spqr_error_handler (&m_cc); + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); + } +} #elif defined (HAVE_CXSPARSE) - - if (econ) - (*current_liboctave_error_handler) - ("sparse-qr: economy mode with CXSparse not supported"); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - octave_idx_type nc = N->L->n; - octave_idx_type nr = nrows; - - const double *bvec = b.data (); - - Matrix ret (b_nr, b_nc); - double *vec = ret.fortran_vec (); - - if (nr < 0 || nc < 0 || nr != b_nr) - (*current_liboctave_error_handler) ("matrix dimension mismatch"); - - if (nr == 0 || nc == 0 || b_nc == 0) - ret = Matrix (nc, b_nc, 0.0); - else - { - OCTAVE_LOCAL_BUFFER (double, buf, S->m2); - - for (volatile octave_idx_type j = 0, idx = 0; - j < b_nc; - j++, idx += b_nr) - { - octave_quit (); - - for (octave_idx_type i = nr; i < S->m2; i++) - buf[i] = 0.; - - volatile octave_idx_type nm = (nr < nc ? nr : nc); - - CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + idx, buf, b_nr); - - for (volatile octave_idx_type i = 0; i < nm; i++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf); - } - - for (octave_idx_type i = 0; i < b_nr; i++) - vec[i+idx] = buf[i]; - } - } - - return ret; + , S (nullptr), N (nullptr) +{ + CXSPARSE_ZNAME () A; + + A.nzmax = a.nnz (); + A.m = nrows; + A.n = ncols; + // Cast away const on A, with full knowledge that CSparse won't touch it + // Prevents the methods below making a copy of the data. + A.p = const_cast + (to_suitesparse_intptr (a.cidx ())); + A.i = const_cast + (to_suitesparse_intptr (a.ridx ())); + A.x = const_cast + (reinterpret_cast (a.data ())); + A.nz = -1; + + S = CXSPARSE_ZNAME (_sqr) (order, &A, 1); + N = CXSPARSE_ZNAME (_qr) (&A, S); + + if (! N) + (*current_liboctave_error_handler) + ("sparse_qr: sparse matrix QR factorization filled"); + +} #else - octave_unused_parameter (b); - octave_unused_parameter (econ); - - return Matrix (); +{ + octave_unused_parameter (order); + + (*current_liboctave_error_handler) + ("sparse_qr: support for CXSparse was unavailable or disabled when liboctave was built"); +} + +#endif + +template <> +sparse_qr::sparse_qr_rep::~sparse_qr_rep (void) +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + cholmod_l_free_sparse (&m_R, &m_cc); + cholmod_l_free_sparse (&m_H, &m_cc); + cholmod_l_free_dense (&m_Htau, &m_cc); + free (m_E); // FIXME: use cholmod_l_free + free (m_HPinv); + cholmod_l_finish (&m_cc); + +#elif defined (HAVE_CXSPARSE) + + CXSPARSE_ZNAME (_sfree) (S); + CXSPARSE_ZNAME (_nfree) (N); + +#endif +} + +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::V (void) const +{ +#if defined (HAVE_CXSPARSE) + // Drop zeros from V and sort + // FIXME: Is the double transpose to sort necessary? + + CXSPARSE_ZNAME (_dropzeros) (N->L); + CXSPARSE_ZNAME () *D = CXSPARSE_ZNAME (_transpose) (N->L, 1); + CXSPARSE_ZNAME (_spfree) (N->L); + N->L = CXSPARSE_ZNAME (_transpose) (D, 1); + CXSPARSE_ZNAME (_spfree) (D); + + octave_idx_type nc = N->L->n; + octave_idx_type nz = N->L->nzmax; + SparseComplexMatrix ret (N->L->m, nc, nz); + + for (octave_idx_type j = 0; j < nc+1; j++) + ret.xcidx (j) = N->L->p[j]; + + for (octave_idx_type j = 0; j < nz; j++) + { + ret.xridx (j) = N->L->i[j]; + ret.xdata (j) = reinterpret_cast (N->L->x)[j]; + } + + return ret; + +#else + + return SparseComplexMatrix (); + +#endif +} + +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::R (bool econ) const +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + octave_idx_type nr = from_size_t (m_R->nrow); + octave_idx_type nc = from_size_t (m_R->ncol); + octave_idx_type nz = from_size_t (m_R->nzmax); + + // FIXME: Does this work if econ = true? + SparseComplexMatrix ret ((econ ? (nc > nr ? nr : nc) : nr), nc, nz); + SuiteSparse_long *Rp = reinterpret_cast (m_R->p); + SuiteSparse_long *Ri = reinterpret_cast (m_R->i); + + for (octave_idx_type j = 0; j < nc + 1; j++) + ret.xcidx (j) = from_suitesparse_long (Rp[j]); + + for (octave_idx_type j = 0; j < nz; j++) + { + ret.xridx (j) = from_suitesparse_long (Ri[j]); + ret.xdata (j) = (reinterpret_cast (m_R->x))[j]; + } + + return ret; + +#elif defined (HAVE_CXSPARSE) + + // Drop zeros from R and sort + // FIXME: Is the double transpose to sort necessary? + + CXSPARSE_ZNAME (_dropzeros) (N->U); + CXSPARSE_ZNAME () *D = CXSPARSE_ZNAME (_transpose) (N->U, 1); + CXSPARSE_ZNAME (_spfree) (N->U); + N->U = CXSPARSE_ZNAME (_transpose) (D, 1); + CXSPARSE_ZNAME (_spfree) (D); + + octave_idx_type nc = N->U->n; + octave_idx_type nz = N->U->nzmax; + + SparseComplexMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows), + nc, nz); + + for (octave_idx_type j = 0; j < nc+1; j++) + ret.xcidx (j) = N->U->p[j]; + + for (octave_idx_type j = 0; j < nz; j++) + { + ret.xridx (j) = N->U->i[j]; + ret.xdata (j) = reinterpret_cast(N->U->x)[j]; + } + + return ret; + +#else + + octave_unused_parameter (econ); + + return SparseComplexMatrix (); #endif - } - - template <> - Matrix - sparse_qr::sparse_qr_rep::Q (bool econ) - { +} + +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::C +(const ComplexMatrix& b, bool econ) +{ #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - octave_idx_type nc = (econ - ? (ncols > nrows ? nrows : ncols) - : nrows); - Matrix ret (nrows, nc); - cholmod_dense *q; - - // I is nrows x nrows identity matrix - cholmod_dense *I - = cholmod_l_allocate_dense (nrows, nrows, nrows, CHOLMOD_REAL, &m_cc); - - for (octave_idx_type i = 0; i < nrows * nrows; i++) - (reinterpret_cast (I->x))[i] = 0.0; - - for (octave_idx_type i = 0; i < nrows; i++) - (reinterpret_cast (I->x))[i * nrows + i] = 1.0; - - q = SuiteSparseQR_qmult (SPQR_QX, m_H, m_Htau, m_HPinv, I, &m_cc); - spqr_error_handler (&m_cc); - - double *q_x = reinterpret_cast (q->x); - double *ret_vec = const_cast (ret.fortran_vec ()); - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nrows; i++) - ret_vec[j * nrows + i] = q_x[j * nrows + i]; - - cholmod_l_free_dense (&q, &m_cc); - cholmod_l_free_dense (&I, &m_cc); - - return ret; + // FIXME: not tested + octave_idx_type nr = (econ + ? (ncols > nrows ? nrows : ncols) + : nrows); + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + ComplexMatrix ret (nr, b_nc); + + if (nrows != b_nr) + (*current_liboctave_error_handler) ("matrix dimension mismatch"); + + if (b_nc < 0 || b_nr < 0) + (*current_liboctave_error_handler) + ("matrix dimension with negative size"); + + cholmod_dense *QTB; // Q' * B + cholmod_dense B = cod2ccd (b); + + QTB = SuiteSparseQR_qmult (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, + &m_cc); + spqr_error_handler (&m_cc); + + // copy QTB into ret + Complex *QTB_x = reinterpret_cast (QTB->x); + Complex *ret_vec = reinterpret_cast (ret.fortran_vec ()); + for (octave_idx_type j = 0; j < b_nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + ret_vec[j * nr + i] = QTB_x[j * b_nr + i]; + + cholmod_l_free_dense (&QTB, &m_cc); + + return ret; #elif defined (HAVE_CXSPARSE) - if (econ) - (*current_liboctave_error_handler) - ("sparse-qr: economy mode with CXSparse not supported"); - - octave_idx_type nc = N->L->n; - octave_idx_type nr = nrows; - Matrix ret (nr, nr); - double *ret_vec = ret.fortran_vec (); - - if (nr < 0 || nc < 0) - (*current_liboctave_error_handler) ("matrix dimension mismatch"); - - if (nr == 0 || nc == 0) - ret = Matrix (nc, nr, 0.0); - else + if (econ) + (*current_liboctave_error_handler) + ("sparse-qr: economy mode with CXSparse not supported"); + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = N->L->n; + octave_idx_type nr = nrows; + const cs_complex_t *bvec + = reinterpret_cast (b.data ()); + ComplexMatrix ret (b_nr, b_nc); + Complex *vec = ret.fortran_vec (); + + if (nr < 0 || nc < 0 || nr != b_nr) + (*current_liboctave_error_handler) ("matrix dimension mismatch"); + + if (nr == 0 || nc == 0 || b_nc == 0) + ret = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0)); + else + { + OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2); + + for (volatile octave_idx_type j = 0, idx = 0; + j < b_nc; + j++, idx += b_nr) { - OCTAVE_LOCAL_BUFFER (double, bvec, nr + 1); - - for (octave_idx_type i = 0; i < nr; i++) - bvec[i] = 0.; - - OCTAVE_LOCAL_BUFFER (double, buf, S->m2); - - for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx += nr) + octave_quit (); + + volatile octave_idx_type nm = (nr < nc ? nr : nc); + + CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + idx, + reinterpret_cast (buf), + b_nr); + + for (volatile octave_idx_type i = 0; i < nm; i++) { octave_quit (); - bvec[j] = 1.0; - for (octave_idx_type i = nr; i < S->m2; i++) - buf[i] = 0.; - - volatile octave_idx_type nm = (nr < nc ? nr : nc); - - CXSPARSE_DNAME (_ipvec) (S->pinv, bvec, buf, nr); - - for (volatile octave_idx_type i = 0; i < nm; i++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, i, N->B[i], buf); - } - - for (octave_idx_type i = 0; i < nr; i++) - ret_vec[i+idx] = buf[i]; - - bvec[j] = 0.0; + CXSPARSE_ZNAME (_happly) (N->L, i, N->B[i], + reinterpret_cast (buf)); } + + for (octave_idx_type i = 0; i < b_nr; i++) + vec[i+idx] = buf[i]; } - - return ret.transpose (); + } + + return ret; #else - octave_unused_parameter (econ); - - return Matrix (); + octave_unused_parameter (b); + octave_unused_parameter (econ); + + return ComplexMatrix (); #endif - } - - template <> - template <> - Matrix - sparse_qr::sparse_qr_rep::tall_solve, Matrix> - (const MArray& b, octave_idx_type& info) - { - info = -1; - -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD) && defined (HAVE_CXSPARSE)) - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - Matrix x (ncols, b_nc); // X = m_E'*(m_R\(Q'*B)) - - if (nrows < 0 || ncols < 0 || b_nc < 0 || b_nr < 0) - (*current_liboctave_error_handler) - ("matrix dimension with negative size"); - - if (nrows < 0 || ncols < 0 || nrows != b_nr) - (*current_liboctave_error_handler) ("matrix dimension mismatch"); - - cholmod_dense *QTB; // Q' * B - cholmod_dense B = rod2rcd (b); - - // FIXME: Process b column by column as in the CXSPARSE version below. - // This avoids a large dense matrix Q' * B in memory. - QTB = SuiteSparseQR_qmult (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, - &m_cc); - - spqr_error_handler (&m_cc); - - // convert m_R into CXSPARSE matrix R2 - CXSPARSE_DNAME (_sparse) R2; - R2.n = ncols; - R2.m = ncols; - R2.nzmax = m_R->nzmax; - R2.x = reinterpret_cast (m_R->x); - suitesparse_integer *R2_p; - suitesparse_integer *R2_i; - if (sizeof (suitesparse_integer) == sizeof (SuiteSparse_long)) - { - R2.p = reinterpret_cast (m_R->p); - R2.i = reinterpret_cast (m_R->i); - } - else - { - R2_p = new suitesparse_integer[ncols+1]; - SuiteSparse_long *R_p = reinterpret_cast (m_R->p); - for (octave_idx_type i = 0; i < ncols+1; i++) - R2_p[i] = suitesparse_long_to_suitesparse_integer (R_p[i]); - R2.p = R2_p; - octave_idx_type nnz = m_R->nzmax; - R2_i = new suitesparse_integer[nnz]; - SuiteSparse_long *R_i = reinterpret_cast (m_R->i); - for (octave_idx_type i = 0; i < nnz; i++) - R2_i[i] = suitesparse_long_to_suitesparse_integer (R_i[i]); - R2.i = R2_i; - } - R2.nz = -1; - double *x_vec = const_cast (x.fortran_vec ()); - suitesparse_integer *E; - if (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long)) - { - E = new suitesparse_integer [ncols]; - for (octave_idx_type i = 0; i < ncols; i++) - E[i] = suitesparse_long_to_suitesparse_integer (m_E[i]); - } - else - E = reinterpret_cast (m_E); - for (volatile octave_idx_type j = 0; j < b_nc; j++) - { - // fill x(:,j) - // solve (m_R\(Q'*B(:,j)) and store result in QTB(:,j) - CXSPARSE_DNAME (_usolve) - (&R2, &(reinterpret_cast (QTB->x)[j * b_nr])); - // x(:,j) = m_E' * (m_R\(Q'*B(:,j)) - CXSPARSE_DNAME (_ipvec) - (E, &(reinterpret_cast (QTB->x)[j * b_nr]), - &x_vec[j * ncols], ncols); - } - - if (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long)) - { - delete [] R2_p; - delete [] R2_i; - delete [] E; - } - cholmod_l_free_dense (&QTB, &m_cc); - - info = 0; - - return x; +} + +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::Q (bool econ) +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + octave_idx_type nc = (econ + ? (ncols > nrows ? nrows : ncols) + : nrows); + ComplexMatrix ret (nrows, nc); + cholmod_dense *q; + + // I is nrows x nrows identity matrix + cholmod_dense *I + = reinterpret_cast + (cholmod_l_allocate_dense (nrows, nrows, nrows, CHOLMOD_COMPLEX, &m_cc)); + + for (octave_idx_type i = 0; i < nrows * nrows; i++) + (reinterpret_cast (I->x))[i] = 0.0; + + for (octave_idx_type i = 0; i < nrows; i++) + (reinterpret_cast (I->x))[i * nrows + i] = 1.0; + + q = SuiteSparseQR_qmult (SPQR_QX, m_H, m_Htau, m_HPinv, I, + &m_cc); + spqr_error_handler (&m_cc); + + Complex *q_x = reinterpret_cast (q->x); + Complex *ret_vec = const_cast (ret.fortran_vec ()); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nrows; i++) + ret_vec[j * nrows + i] = q_x[j * nrows + i]; + + cholmod_l_free_dense (&q, &m_cc); + cholmod_l_free_dense (&I, &m_cc); + + return ret; #elif defined (HAVE_CXSPARSE) - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - const double *bvec = b.data (); - - Matrix x (nc, b_nc); - double *vec = x.fortran_vec (); - - OCTAVE_LOCAL_BUFFER (double, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; - i++, idx+=nc, bidx+=b_nr) + if (econ) + (*current_liboctave_error_handler) + ("sparse-qr: economy mode with CXSparse not supported"); + + octave_idx_type nc = N->L->n; + octave_idx_type nr = nrows; + ComplexMatrix ret (nr, nr); + Complex *vec = ret.fortran_vec (); + + if (nr < 0 || nc < 0) + (*current_liboctave_error_handler) ("matrix dimension mismatch"); + + if (nr == 0 || nc == 0) + ret = ComplexMatrix (nc, nr, Complex (0.0, 0.0)); + else + { + OCTAVE_LOCAL_BUFFER (cs_complex_t, bvec, nr); + + for (octave_idx_type i = 0; i < nr; i++) + bvec[i] = cs_complex_t (0.0, 0.0); + + OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2); + + for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx+=nr) { octave_quit (); - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_usolve) (N->U, buf); - CXSPARSE_DNAME (_ipvec) (S->q, buf, vec + idx, nc); - } - - info = 0; - - return x; - -#else - - octave_unused_parameter (b); - - return Matrix (); - -#endif - } - - template <> - template <> - Matrix - sparse_qr::sparse_qr_rep::wide_solve, Matrix> - (const MArray& b, octave_idx_type& info) const - { - info = -1; -#if defined (HAVE_CXSPARSE) - - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - const double *bvec = b.data (); - - Matrix x (nc, b_nc); - double *vec = x.fortran_vec (); - - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (double, buf, nbuf); - - for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; - i++, idx+=nc, bidx+=b_nr) - { - octave_quit (); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_pvec) (S->q, bvec + bidx, buf, nr); - CXSPARSE_DNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_pvec) (S->pinv, buf, vec + idx, nc); - } - - info = 0; - - return x; - -#else - octave_unused_parameter (b); - - return Matrix (); - -#endif - } - - template <> - template <> - SparseMatrix - sparse_qr::sparse_qr_rep::tall_solve - (const SparseMatrix& b, octave_idx_type& info) - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - SparseMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) + bvec[j] = cs_complex_t (1.0, 0.0); + + volatile octave_idx_type nm = (nr < nc ? nr : nc); + + CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec, + reinterpret_cast (buf), + nr); + + for (volatile octave_idx_type i = 0; i < nm; i++) { octave_quit (); - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + CXSPARSE_ZNAME (_happly) (N->L, i, N->B[i], + reinterpret_cast (buf)); } - CXSPARSE_DNAME (_usolve) (N->U, buf); - CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc); - - for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + vec[i+idx] = buf[i]; + + bvec[j] = cs_complex_t (0.0, 0.0); + } + } + + return ret.hermitian (); + +#else + + octave_unused_parameter (econ); + + return ComplexMatrix (); + +#endif +} + +template <> +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::tall_solve + (const SparseComplexMatrix& b, octave_idx_type& info) +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + SparseComplexMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + { + Complex c = b.xelem (j, i); + Xx[j] = c.real (); + Xz[j] = c.imag (); + } + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_usolve) (N->U, buf); + CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_usolve) (N->U, buf); + CXSPARSE_DNAME (_ipvec) (S->q, buf, Xz, nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + Complex tmp = Complex (Xx[j], Xz[j]); + + if (tmp != 0.0) { - double tmp = Xx[j]; - - if (tmp != 0.0) + if (ii == x_nz) { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; } - - x.xcidx (i+1) = ii; } - info = 0; - - return x; + x.xcidx (i+1) = ii; + } + + info = 0; + + return x; #else - octave_unused_parameter (b); - - return SparseMatrix (); + octave_unused_parameter (b); + + return SparseComplexMatrix (); #endif - } - - template <> - template <> - SparseMatrix - sparse_qr::sparse_qr_rep::wide_solve - (const SparseMatrix& b, octave_idx_type& info) const - { - info = -1; +} + +template <> +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::wide_solve + (const SparseComplexMatrix& b, octave_idx_type& info) const +{ + info = -1; #if defined (HAVE_CXSPARSE) - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - SparseMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, nbuf); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nr = b.rows (); + octave_idx_type b_nc = b.cols (); + + SparseComplexMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (double, buf, nbuf); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + { + Complex c = b.xelem (j, i); + Xx[j] = c.real (); + Xz[j] = c.imag (); + } + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr); + CXSPARSE_DNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = 0.; + + CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr); + CXSPARSE_DNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xz, nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + Complex tmp = Complex (Xx[j], Xz[j]); + + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; + } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; + } + } + + x.xcidx (i+1) = ii; + } + + info = 0; + + x.maybe_compress (); + + return x; + +#else + + octave_unused_parameter (b); + + return SparseComplexMatrix (); + +#endif +} + +template <> +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::tall_solve, + ComplexMatrix> + (const MArray& b, octave_idx_type& info) +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + ComplexMatrix x (nc, b_nc); + cs_complex_t *vec = reinterpret_cast (x.fortran_vec ()); + + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); + OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_ipvec) (S->pinv, + reinterpret_cast(Xx), + buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) { octave_quit (); - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr); - CXSPARSE_DNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc); - - for (octave_idx_type j = 0; j < nc; j++) + CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_ZNAME (_usolve) (N->U, buf); + CXSPARSE_ZNAME (_ipvec) (S->q, buf, vec + idx, nc); + } + + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return ComplexMatrix (); + +#endif +} + +template <> +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::wide_solve, + ComplexMatrix> + (const MArray& b, octave_idx_type& info) const +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + ComplexMatrix x (nc, b_nc); + cs_complex_t *vec = reinterpret_cast (x.fortran_vec ()); + + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); + OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); + OCTAVE_LOCAL_BUFFER (double, B, nr); + + for (octave_idx_type i = 0; i < nr; i++) + B[i] = N->B[i]; + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_pvec) (S->q, reinterpret_cast (Xx), + buf, nr); + CXSPARSE_ZNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); + } + + CXSPARSE_ZNAME (_pvec) (S->pinv, buf, vec + idx, nc); + } + + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return ComplexMatrix (); + +#endif +} + +template <> +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::tall_solve + (const SparseMatrix& b, octave_idx_type& info) +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + SparseComplexMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_ipvec) (S->pinv, + reinterpret_cast (Xx), + buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_ZNAME (_usolve) (N->U, buf); + CXSPARSE_ZNAME (_ipvec) (S->q, buf, + reinterpret_cast (Xx), + nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + Complex tmp = Xx[j]; + + if (tmp != 0.0) { - double tmp = Xx[j]; - - if (tmp != 0.0) + if (ii == x_nz) { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; } - - x.xcidx (i+1) = ii; } - info = 0; - - x.maybe_compress (); - - return x; + x.xcidx (i+1) = ii; + } + + info = 0; + + x.maybe_compress (); + + return x; #else - octave_unused_parameter (b); - - return SparseMatrix (); + octave_unused_parameter (b); + + return SparseComplexMatrix (); #endif - } - - template <> - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::tall_solve, ComplexMatrix> - (const MArray& b, octave_idx_type& info) - { - info = -1; +} + +template <> +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::wide_solve + (const SparseMatrix& b, octave_idx_type& info) const +{ + info = -1; #if defined (HAVE_CXSPARSE) - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - ComplexMatrix x (nc, b_nc); - Complex *vec = x.fortran_vec (); - - OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + SparseComplexMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); + OCTAVE_LOCAL_BUFFER (double, B, nr); + + for (octave_idx_type i = 0; i < nr; i++) + B[i] = N->B[i]; + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_pvec) (S->q, + reinterpret_cast (Xx), + buf, nr); + CXSPARSE_ZNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) + { + octave_quit (); + + CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); + } + + CXSPARSE_ZNAME (_pvec) (S->pinv, buf, + reinterpret_cast (Xx), + nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + Complex tmp = Xx[j]; + + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; + } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; + } + } + + x.xcidx (i+1) = ii; + } + + info = 0; + + x.maybe_compress (); + + return x; + +#else + + octave_unused_parameter (b); + + return SparseComplexMatrix (); + +#endif +} + +template <> +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::tall_solve, + ComplexMatrix> + (const MArray& b, octave_idx_type& info) +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + const cs_complex_t *bvec = reinterpret_cast + (b.data ()); + + ComplexMatrix x (nc, b_nc); + cs_complex_t *vec = reinterpret_cast + (x.fortran_vec ()); + + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; + i++, idx+=nc, bidx+=b_nr) + { + octave_quit (); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_ZNAME (_usolve) (N->U, buf); + CXSPARSE_ZNAME (_ipvec) (S->q, buf, vec + idx, nc); + } + + info = 0; + + return x; + +#else + + octave_unused_parameter (b); + + return ComplexMatrix (); + +#endif +} + +template <> +template <> +ComplexMatrix +sparse_qr::sparse_qr_rep::wide_solve, + ComplexMatrix> + (const MArray& b, octave_idx_type& info) const +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + const cs_complex_t *bvec = reinterpret_cast + (b.data ()); + + ComplexMatrix x (nc, b_nc); + cs_complex_t *vec = reinterpret_cast (x.fortran_vec ()); + + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); + OCTAVE_LOCAL_BUFFER (double, B, nr); + + for (octave_idx_type i = 0; i < nr; i++) + B[i] = N->B[i]; + + for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; + i++, idx+=nc, bidx+=b_nr) + { + octave_quit (); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_pvec) (S->q, bvec + bidx, buf, nr); + CXSPARSE_ZNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) { octave_quit (); - for (octave_idx_type j = 0; j < b_nr; j++) - { - Complex c = b.xelem (j, i); - Xx[j] = c.real (); - Xz[j] = c.imag (); - } - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_usolve) (N->U, buf); - CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_usolve) (N->U, buf); - CXSPARSE_DNAME (_ipvec) (S->q, buf, Xz, nc); - - for (octave_idx_type j = 0; j < nc; j++) - vec[j+idx] = Complex (Xx[j], Xz[j]); + CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); } - info = 0; - - return x; + CXSPARSE_ZNAME (_pvec) (S->pinv, buf, vec + idx, nc); + } + + info = 0; + + return x; #else - octave_unused_parameter (b); - - return ComplexMatrix (); + octave_unused_parameter (b); + + return ComplexMatrix (); #endif - } - - template <> - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::wide_solve, ComplexMatrix> - (const MArray& b, octave_idx_type& info) const - { - info = -1; +} + +template <> +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::tall_solve + (const SparseComplexMatrix& b, octave_idx_type& info) +{ + info = -1; #if defined (HAVE_CXSPARSE) - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - ComplexMatrix x (nc, b_nc); - Complex *vec = x.fortran_vec (); - - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, nbuf); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + octave_idx_type nr = nrows; + octave_idx_type nc = ncols; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + SparseComplexMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + + OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < S->m2; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_ipvec) (S->pinv, + reinterpret_cast (Xx), + buf, nr); + + for (volatile octave_idx_type j = 0; j < nc; j++) + { + octave_quit (); + + CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); + } + + CXSPARSE_ZNAME (_usolve) (N->U, buf); + CXSPARSE_ZNAME (_ipvec) (S->q, buf, + reinterpret_cast (Xx), + nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + Complex tmp = Xx[j]; + + if (tmp != 0.0) + { + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; + } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; + } + } + + x.xcidx (i+1) = ii; + } + + info = 0; + + x.maybe_compress (); + + return x; + +#else + + octave_unused_parameter (b); + + return SparseComplexMatrix (); + +#endif +} + +template <> +template <> +SparseComplexMatrix +sparse_qr::sparse_qr_rep::wide_solve + (const SparseComplexMatrix& b, octave_idx_type& info) const +{ + info = -1; + +#if defined (HAVE_CXSPARSE) + + // These are swapped because the original matrix was transposed in + // sparse_qr::solve. + + octave_idx_type nr = ncols; + octave_idx_type nc = nrows; + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + SparseComplexMatrix x (nc, b_nc, b.nnz ()); + x.xcidx (0) = 0; + + volatile octave_idx_type x_nz = b.nnz (); + volatile octave_idx_type ii = 0; + volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); + + OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); + OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); + OCTAVE_LOCAL_BUFFER (double, B, nr); + + for (octave_idx_type i = 0; i < nr; i++) + B[i] = N->B[i]; + + for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) + { + octave_quit (); + + for (octave_idx_type j = 0; j < b_nr; j++) + Xx[j] = b.xelem (j, i); + + for (octave_idx_type j = nr; j < nbuf; j++) + buf[j] = cs_complex_t (0.0, 0.0); + + CXSPARSE_ZNAME (_pvec) (S->q, reinterpret_cast(Xx), + buf, nr); + CXSPARSE_ZNAME (_utsolve) (N->U, buf); + + for (volatile octave_idx_type j = nr-1; j >= 0; j--) { octave_quit (); - for (octave_idx_type j = 0; j < b_nr; j++) + CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); + } + + CXSPARSE_ZNAME (_pvec) (S->pinv, buf, + reinterpret_cast(Xx), nc); + + for (octave_idx_type j = 0; j < nc; j++) + { + Complex tmp = Xx[j]; + + if (tmp != 0.0) { - Complex c = b.xelem (j, i); - Xx[j] = c.real (); - Xz[j] = c.imag (); - } - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr); - CXSPARSE_DNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); + if (ii == x_nz) + { + // Resize the sparse matrix + octave_idx_type sz = x_nz * (b_nc - i) / b_nc; + sz = (sz > 10 ? sz : 10) + x_nz; + x.change_capacity (sz); + x_nz = sz; + } + + x.xdata (ii) = tmp; + x.xridx (ii++) = j; } - - CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr); - CXSPARSE_DNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xz, nc); - - for (octave_idx_type j = 0; j < nc; j++) - vec[j+idx] = Complex (Xx[j], Xz[j]); } - info = 0; - - return x; + x.xcidx (i+1) = ii; + } + + info = 0; + + x.maybe_compress (); + + return x; #else - octave_unused_parameter (b); - - return ComplexMatrix (); + octave_unused_parameter (b); + + return SparseComplexMatrix (); #endif +} + +template +sparse_qr::sparse_qr (void) + : m_rep (new sparse_qr_rep (SPARSE_T (), 0)) +{ } + +template +sparse_qr::sparse_qr (const SPARSE_T& a, int order) + : m_rep (new sparse_qr_rep (a, order)) +{ } + +template +bool +sparse_qr::ok (void) const +{ + return m_rep->ok (); +} + +template +SPARSE_T +sparse_qr::V (void) const +{ + return m_rep->V (); +} + +template +ColumnVector +sparse_qr::Pinv (void) const +{ + return m_rep->P (); +} + +template +ColumnVector +sparse_qr::P (void) const +{ + return m_rep->P (); +} + +template +ColumnVector +sparse_qr::E (void) const +{ + return m_rep->E(); +} + + +template +SparseMatrix +sparse_qr::E_MAT (void) const +{ + ColumnVector perm = m_rep->E (); + octave_idx_type nrows = perm.rows (); + SparseMatrix ret (nrows, nrows, nrows); + for (octave_idx_type i = 0; i < nrows; i++) + ret(perm(i) - 1, i) = 1.0; + return ret; +} + + +template +SPARSE_T +sparse_qr::R (bool econ) const +{ + return m_rep->R (econ); +} + +template +typename SPARSE_T::dense_matrix_type +sparse_qr::C (const typename SPARSE_T::dense_matrix_type& b, + bool econ) const +{ + return m_rep->C (b, econ); +} + +template +typename SPARSE_T::dense_matrix_type +sparse_qr::Q (bool econ) const +{ + return m_rep->Q (econ); +} + +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) +//specializations of function min2norm_solve +template <> +template <> +OCTAVE_API Matrix +sparse_qr::min2norm_solve, Matrix> +(const SparseMatrix& a, const MArray& b, + octave_idx_type& info, int order) +{ + info = -1; + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + Matrix x (nc, b_nc); + cholmod_common cc; + + cholmod_l_start (&cc); + cholmod_sparse A = ros2rcs (a); + cholmod_dense B = rod2rcd (b); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); + spqr_error_handler (&cc); + + double *vec = x.fortran_vec (); + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + vec[i] = reinterpret_cast (X->x)[i]; + + info = 0; + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); } - - // Complex-valued matrices. - - template <> - sparse_qr::sparse_qr_rep::sparse_qr_rep - (const SparseComplexMatrix& a, int order) - : nrows (a.rows ()), ncols (a.columns ()) -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - , m_cc (), m_R (nullptr), m_E (nullptr), m_H (nullptr), - m_Htau (nullptr), m_HPinv (nullptr) + cholmod_l_finish (&cc); + + return x; + +} + +template <> +template <> +OCTAVE_API SparseMatrix +sparse_qr::min2norm_solve +(const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info, + int order) +{ + info = -1; + SparseMatrix x; + cholmod_common cc; + + cholmod_l_start (&cc); + cholmod_sparse A = ros2rcs (a); + cholmod_sparse B = ros2rcs (b); + cholmod_sparse *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); + spqr_error_handler (&cc); + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); + delete [] reinterpret_cast (B.p); + delete [] reinterpret_cast (B.i); + } + + x = rcs2ros (X); + cholmod_l_finish (&cc); + info = 0; + + return x; + +} + +template <> +template <> +OCTAVE_API ComplexMatrix +sparse_qr::min2norm_solve, ComplexMatrix> +(const SparseMatrix& a, const MArray& b, + octave_idx_type& info, int order) +{ + info = -1; + + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + + ComplexMatrix x (nc, b_nc); + + cholmod_common cc; + + cholmod_l_start (&cc); + + cholmod_sparse *A = ros2ccs (a, &cc); + cholmod_dense B = cod2ccd (b); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, A, &B, &cc); + spqr_error_handler (&cc); + + Complex *vec = x.fortran_vec (); + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + vec[i] = reinterpret_cast (X->x)[i]; + + cholmod_l_free_sparse (&A, &cc); + cholmod_l_finish (&cc); + + info = 0; + + return x; + +} + +template <> +template <> +OCTAVE_API SparseComplexMatrix +sparse_qr::min2norm_solve + (const SparseMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info, int order) +{ + info = -1; + + cholmod_common cc; + + cholmod_l_start (&cc); + + cholmod_sparse *A = ros2ccs (a, &cc); + cholmod_sparse B = cos2ccs (b); + cholmod_sparse *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, A, &B, &cc); + spqr_error_handler (&cc); + + cholmod_l_free_sparse (&A, &cc); + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) { - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.cols (); - - if (nr < 0 || nc < 0) - (*current_liboctave_error_handler) - ("matrix dimension with negative size"); - - if (order < 0 || order > 9) - (*current_liboctave_error_handler) - ("ordering %d is not supported by SPQR", order); - - cholmod_l_start (&m_cc); - cholmod_sparse A = cos2ccs (a); - - SuiteSparseQR (order, static_cast (SPQR_DEFAULT_TOL), - static_cast (A.nrow), - &A, &m_R, &m_E, &m_H, - &m_HPinv, &m_Htau, &m_cc); - spqr_error_handler (&m_cc); - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - } + delete [] reinterpret_cast (B.p); + delete [] reinterpret_cast (B.i); + } + cholmod_l_finish (&cc); + + SparseComplexMatrix ret = ccs2cos(X); + + info = 0; + + return ret; + +} + +template <> +template <> +OCTAVE_API ComplexMatrix +sparse_qr::min2norm_solve, + ComplexMatrix> + (const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info, int order) +{ + info = -1; + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + ComplexMatrix x (nc, b_nc); + + cholmod_common cc; + + cholmod_l_start (&cc); + + cholmod_sparse A = cos2ccs (a); + cholmod_dense B = cod2ccd (b); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); + spqr_error_handler (&cc); + + Complex *vec = x.fortran_vec (); + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + vec[i] = reinterpret_cast (X->x)[i]; + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); + } + cholmod_l_finish (&cc); + + info = 0; + + return x; + +} + +template <> +template <> +OCTAVE_API ComplexMatrix +sparse_qr::min2norm_solve, + ComplexMatrix> + (const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info, int order) +{ + info = -1; + + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + ComplexMatrix x (nc, b_nc); + + cholmod_common cc; + + cholmod_l_start (&cc); + + cholmod_sparse A = cos2ccs (a); + cholmod_dense *B = rod2ccd (b, &cc); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, B, &cc); + spqr_error_handler (&cc); + + Complex *vec = x.fortran_vec (); + + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + vec[i] = reinterpret_cast (X->x)[i]; + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); } + cholmod_l_free_dense (&B, &cc); + cholmod_l_finish (&cc); + + info = 0; + + return x; + +} + +template <> +template <> +OCTAVE_API SparseComplexMatrix +sparse_qr::min2norm_solve + (const SparseComplexMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info, int order) +{ + info = -1; + + cholmod_common cc; + + cholmod_l_start (&cc); + + cholmod_sparse A = cos2ccs (a); + cholmod_sparse B = cos2ccs (b); + cholmod_sparse *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); + spqr_error_handler (&cc); + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); + delete [] reinterpret_cast (B.p); + delete [] reinterpret_cast (B.i); + } + cholmod_l_finish (&cc); + + info = 0; + + return ccs2cos (X); + +} + +template <> +template <> +OCTAVE_API SparseComplexMatrix +sparse_qr::min2norm_solve + (const SparseComplexMatrix& a, const SparseMatrix& b, + octave_idx_type& info, int order) +{ + info = -1; + + cholmod_common cc; + + cholmod_l_start (&cc); + + cholmod_sparse A = cos2ccs (a); + cholmod_sparse *B = ros2ccs (b, &cc); + cholmod_sparse *X; + + X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, B, &cc); + spqr_error_handler (&cc); + + SparseComplexMatrix ret = ccs2cos(X); + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast (A.p); + delete [] reinterpret_cast (A.i); + } + cholmod_l_free_sparse (&B, &cc); + cholmod_l_finish (&cc); + + info = 0; + + return ret; + +} +#endif + +// FIXME: Why is the "order" of the QR calculation as used in the +// CXSparse function sqr 3 for real matrices and 2 for complex? These +// values seem to be required but there was no explanation in David +// Bateman's original code. + +template +class +cxsparse_defaults +{ +public: + enum { order = -1 }; +}; + +template <> +class +cxsparse_defaults +{ +public: +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + enum { order = SPQR_ORDERING_DEFAULT }; +#elif defined (HAVE_CXSPARSE) + enum { order = 3 }; +#endif +}; + +template <> +class +cxsparse_defaults +{ +public: +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + enum { order = SPQR_ORDERING_DEFAULT }; +#elif defined (HAVE_CXSPARSE) + enum { order = 2 }; +#endif +}; + +template +template +RET_T +sparse_qr::solve (const SPARSE_T& a, const RHS_T& b, + octave_idx_type& info) +{ +#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) + + info = -1; + + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.cols (); + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + int order = cxsparse_defaults::order; + + if (nr < 0 || nc < 0 || b_nc < 0 || b_nr < 0) + (*current_liboctave_error_handler) + ("matrix dimension with negative size"); + + if ( nr != b_nr) + (*current_liboctave_error_handler) + ("matrix dimension mismatch in solution of minimum norm problem"); + + info = 0; + + return min2norm_solve (a, b, info, order); #elif defined (HAVE_CXSPARSE) - , S (nullptr), N (nullptr) + + info = -1; + + octave_idx_type nr = a.rows (); + octave_idx_type nc = a.cols (); + + octave_idx_type b_nc = b.cols (); + octave_idx_type b_nr = b.rows (); + + int order = cxsparse_defaults::order; + + if (nr < 0 || nc < 0 || nr != b_nr) + (*current_liboctave_error_handler) + ("matrix dimension mismatch in solution of minimum norm problem"); + + if (nr == 0 || nc == 0 || b_nc == 0) { - CXSPARSE_ZNAME () A; - - A.nzmax = a.nnz (); - A.m = nrows; - A.n = ncols; - // Cast away const on A, with full knowledge that CSparse won't touch it - // Prevents the methods below making a copy of the data. - A.p = const_cast - (to_suitesparse_intptr (a.cidx ())); - A.i = const_cast - (to_suitesparse_intptr (a.ridx ())); - A.x = const_cast - (reinterpret_cast (a.data ())); - A.nz = -1; - - S = CXSPARSE_ZNAME (_sqr) (order, &A, 1); - N = CXSPARSE_ZNAME (_qr) (&A, S); - - if (! N) - (*current_liboctave_error_handler) - ("sparse_qr: sparse matrix QR factorization filled"); - + info = 0; + + return RET_T (nc, b_nc, 0.0); + } + else if (nr >= nc) + { + sparse_qr q (a, order); + + return q.ok () ? q.tall_solve (b, info) : RET_T (); + } + else + { + sparse_qr q (a.hermitian (), order); + + return q.ok () ? q.wide_solve (b, info) : RET_T (); } #else - { - octave_unused_parameter (order); - - (*current_liboctave_error_handler) - ("sparse_qr: support for CXSparse was unavailable or disabled when liboctave was built"); - } - -#endif - - template <> - sparse_qr::sparse_qr_rep::~sparse_qr_rep (void) - { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - cholmod_l_free_sparse (&m_R, &m_cc); - cholmod_l_free_sparse (&m_H, &m_cc); - cholmod_l_free_dense (&m_Htau, &m_cc); - free (m_E); // FIXME: use cholmod_l_free - free (m_HPinv); - cholmod_l_finish (&m_cc); - -#elif defined (HAVE_CXSPARSE) - - CXSPARSE_ZNAME (_sfree) (S); - CXSPARSE_ZNAME (_nfree) (N); - -#endif - } - - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::V (void) const - { -#if defined (HAVE_CXSPARSE) - // Drop zeros from V and sort - // FIXME: Is the double transpose to sort necessary? - - CXSPARSE_ZNAME (_dropzeros) (N->L); - CXSPARSE_ZNAME () *D = CXSPARSE_ZNAME (_transpose) (N->L, 1); - CXSPARSE_ZNAME (_spfree) (N->L); - N->L = CXSPARSE_ZNAME (_transpose) (D, 1); - CXSPARSE_ZNAME (_spfree) (D); - - octave_idx_type nc = N->L->n; - octave_idx_type nz = N->L->nzmax; - SparseComplexMatrix ret (N->L->m, nc, nz); - - for (octave_idx_type j = 0; j < nc+1; j++) - ret.xcidx (j) = N->L->p[j]; - - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx (j) = N->L->i[j]; - ret.xdata (j) = reinterpret_cast (N->L->x)[j]; - } - - return ret; - -#else - - return SparseComplexMatrix (); - -#endif - } - - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::R (bool econ) const - { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - octave_idx_type nr = from_size_t (m_R->nrow); - octave_idx_type nc = from_size_t (m_R->ncol); - octave_idx_type nz = from_size_t (m_R->nzmax); - - // FIXME: Does this work if econ = true? - SparseComplexMatrix ret ((econ ? (nc > nr ? nr : nc) : nr), nc, nz); - SuiteSparse_long *Rp = reinterpret_cast (m_R->p); - SuiteSparse_long *Ri = reinterpret_cast (m_R->i); - - for (octave_idx_type j = 0; j < nc + 1; j++) - ret.xcidx (j) = from_suitesparse_long (Rp[j]); - - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx (j) = from_suitesparse_long (Ri[j]); - ret.xdata (j) = (reinterpret_cast (m_R->x))[j]; - } - - return ret; - -#elif defined (HAVE_CXSPARSE) - - // Drop zeros from R and sort - // FIXME: Is the double transpose to sort necessary? - - CXSPARSE_ZNAME (_dropzeros) (N->U); - CXSPARSE_ZNAME () *D = CXSPARSE_ZNAME (_transpose) (N->U, 1); - CXSPARSE_ZNAME (_spfree) (N->U); - N->U = CXSPARSE_ZNAME (_transpose) (D, 1); - CXSPARSE_ZNAME (_spfree) (D); - - octave_idx_type nc = N->U->n; - octave_idx_type nz = N->U->nzmax; - - SparseComplexMatrix ret ((econ ? (nc > nrows ? nrows : nc) : nrows), - nc, nz); - - for (octave_idx_type j = 0; j < nc+1; j++) - ret.xcidx (j) = N->U->p[j]; - - for (octave_idx_type j = 0; j < nz; j++) - { - ret.xridx (j) = N->U->i[j]; - ret.xdata (j) = reinterpret_cast(N->U->x)[j]; - } - - return ret; - -#else - - octave_unused_parameter (econ); - - return SparseComplexMatrix (); - -#endif - } - - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::C - (const ComplexMatrix& b, bool econ) - { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - // FIXME: not tested - octave_idx_type nr = (econ - ? (ncols > nrows ? nrows : ncols) - : nrows); - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - ComplexMatrix ret (nr, b_nc); - - if (nrows != b_nr) - (*current_liboctave_error_handler) ("matrix dimension mismatch"); - - if (b_nc < 0 || b_nr < 0) - (*current_liboctave_error_handler) - ("matrix dimension with negative size"); - - cholmod_dense *QTB; // Q' * B - cholmod_dense B = cod2ccd (b); - - QTB = SuiteSparseQR_qmult (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, - &m_cc); - spqr_error_handler (&m_cc); - - // copy QTB into ret - Complex *QTB_x = reinterpret_cast (QTB->x); - Complex *ret_vec = reinterpret_cast (ret.fortran_vec ()); - for (octave_idx_type j = 0; j < b_nc; j++) - for (octave_idx_type i = 0; i < nr; i++) - ret_vec[j * nr + i] = QTB_x[j * b_nr + i]; - - cholmod_l_free_dense (&QTB, &m_cc); - - return ret; - -#elif defined (HAVE_CXSPARSE) - - if (econ) - (*current_liboctave_error_handler) - ("sparse-qr: economy mode with CXSparse not supported"); - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = N->L->n; - octave_idx_type nr = nrows; - const cs_complex_t *bvec - = reinterpret_cast (b.data ()); - ComplexMatrix ret (b_nr, b_nc); - Complex *vec = ret.fortran_vec (); - - if (nr < 0 || nc < 0 || nr != b_nr) - (*current_liboctave_error_handler) ("matrix dimension mismatch"); - - if (nr == 0 || nc == 0 || b_nc == 0) - ret = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0)); - else - { - OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2); - - for (volatile octave_idx_type j = 0, idx = 0; - j < b_nc; - j++, idx += b_nr) - { - octave_quit (); - - volatile octave_idx_type nm = (nr < nc ? nr : nc); - - CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + idx, - reinterpret_cast (buf), - b_nr); - - for (volatile octave_idx_type i = 0; i < nm; i++) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, i, N->B[i], - reinterpret_cast (buf)); - } - - for (octave_idx_type i = 0; i < b_nr; i++) - vec[i+idx] = buf[i]; - } - } - - return ret; - -#else - - octave_unused_parameter (b); - octave_unused_parameter (econ); - - return ComplexMatrix (); - -#endif - } - - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::Q (bool econ) - { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - octave_idx_type nc = (econ - ? (ncols > nrows ? nrows : ncols) - : nrows); - ComplexMatrix ret (nrows, nc); - cholmod_dense *q; - - // I is nrows x nrows identity matrix - cholmod_dense *I - = reinterpret_cast - (cholmod_l_allocate_dense (nrows, nrows, nrows, CHOLMOD_COMPLEX, &m_cc)); - - for (octave_idx_type i = 0; i < nrows * nrows; i++) - (reinterpret_cast (I->x))[i] = 0.0; - - for (octave_idx_type i = 0; i < nrows; i++) - (reinterpret_cast (I->x))[i * nrows + i] = 1.0; - - q = SuiteSparseQR_qmult (SPQR_QX, m_H, m_Htau, m_HPinv, I, - &m_cc); - spqr_error_handler (&m_cc); - - Complex *q_x = reinterpret_cast (q->x); - Complex *ret_vec = const_cast (ret.fortran_vec ()); - - for (octave_idx_type j = 0; j < nc; j++) - for (octave_idx_type i = 0; i < nrows; i++) - ret_vec[j * nrows + i] = q_x[j * nrows + i]; - - cholmod_l_free_dense (&q, &m_cc); - cholmod_l_free_dense (&I, &m_cc); - - return ret; - -#elif defined (HAVE_CXSPARSE) - - if (econ) - (*current_liboctave_error_handler) - ("sparse-qr: economy mode with CXSparse not supported"); - - octave_idx_type nc = N->L->n; - octave_idx_type nr = nrows; - ComplexMatrix ret (nr, nr); - Complex *vec = ret.fortran_vec (); - - if (nr < 0 || nc < 0) - (*current_liboctave_error_handler) ("matrix dimension mismatch"); - - if (nr == 0 || nc == 0) - ret = ComplexMatrix (nc, nr, Complex (0.0, 0.0)); - else - { - OCTAVE_LOCAL_BUFFER (cs_complex_t, bvec, nr); - - for (octave_idx_type i = 0; i < nr; i++) - bvec[i] = cs_complex_t (0.0, 0.0); - - OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2); - - for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx+=nr) - { - octave_quit (); - - bvec[j] = cs_complex_t (1.0, 0.0); - - volatile octave_idx_type nm = (nr < nc ? nr : nc); - - CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec, - reinterpret_cast (buf), - nr); - - for (volatile octave_idx_type i = 0; i < nm; i++) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, i, N->B[i], - reinterpret_cast (buf)); - } - - for (octave_idx_type i = 0; i < nr; i++) - vec[i+idx] = buf[i]; - - bvec[j] = cs_complex_t (0.0, 0.0); - } - } - - return ret.hermitian (); - -#else - - octave_unused_parameter (econ); - - return ComplexMatrix (); - -#endif - } - - template <> - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::tall_solve - (const SparseComplexMatrix& b, octave_idx_type& info) - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - SparseComplexMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - { - Complex c = b.xelem (j, i); - Xx[j] = c.real (); - Xz[j] = c.imag (); - } - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_usolve) (N->U, buf); - CXSPARSE_DNAME (_ipvec) (S->q, buf, Xx, nc); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_usolve) (N->U, buf); - CXSPARSE_DNAME (_ipvec) (S->q, buf, Xz, nc); - - for (octave_idx_type j = 0; j < nc; j++) - { - Complex tmp = Complex (Xx[j], Xz[j]); - - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; - } - } - - x.xcidx (i+1) = ii; - } - - info = 0; - - return x; - -#else - - octave_unused_parameter (b); - - return SparseComplexMatrix (); - -#endif - } - - template <> - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::wide_solve - (const SparseComplexMatrix& b, octave_idx_type& info) const - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nr = b.rows (); - octave_idx_type b_nc = b.cols (); - - SparseComplexMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (double, buf, nbuf); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - { - Complex c = b.xelem (j, i); - Xx[j] = c.real (); - Xz[j] = c.imag (); - } - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr); - CXSPARSE_DNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xx, nc); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = 0.; - - CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr); - CXSPARSE_DNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_DNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_DNAME (_pvec) (S->pinv, buf, Xz, nc); - - for (octave_idx_type j = 0; j < nc; j++) - { - Complex tmp = Complex (Xx[j], Xz[j]); - - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; - } - } - - x.xcidx (i+1) = ii; - } - - info = 0; - - x.maybe_compress (); - - return x; - -#else - - octave_unused_parameter (b); - - return SparseComplexMatrix (); - -#endif - } - - template <> - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::tall_solve, - ComplexMatrix> - (const MArray& b, octave_idx_type& info) - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - ComplexMatrix x (nc, b_nc); - cs_complex_t *vec = reinterpret_cast (x.fortran_vec ()); - - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); - OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_ipvec) (S->pinv, - reinterpret_cast(Xx), - buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_ZNAME (_usolve) (N->U, buf); - CXSPARSE_ZNAME (_ipvec) (S->q, buf, vec + idx, nc); - } - - info = 0; - - return x; - -#else - - octave_unused_parameter (b); - - return ComplexMatrix (); - -#endif - } - - template <> - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::wide_solve, - ComplexMatrix> - (const MArray& b, octave_idx_type& info) const - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - ComplexMatrix x (nc, b_nc); - cs_complex_t *vec = reinterpret_cast (x.fortran_vec ()); - - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); - OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr); - OCTAVE_LOCAL_BUFFER (double, B, nr); - - for (octave_idx_type i = 0; i < nr; i++) - B[i] = N->B[i]; - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_pvec) (S->q, reinterpret_cast (Xx), - buf, nr); - CXSPARSE_ZNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); - } - - CXSPARSE_ZNAME (_pvec) (S->pinv, buf, vec + idx, nc); - } - - info = 0; - - return x; - -#else - - octave_unused_parameter (b); - - return ComplexMatrix (); - -#endif - } - - template <> - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::tall_solve - (const SparseMatrix& b, octave_idx_type& info) - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - SparseComplexMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_ipvec) (S->pinv, - reinterpret_cast (Xx), - buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_ZNAME (_usolve) (N->U, buf); - CXSPARSE_ZNAME (_ipvec) (S->q, buf, - reinterpret_cast (Xx), - nc); - - for (octave_idx_type j = 0; j < nc; j++) - { - Complex tmp = Xx[j]; - - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; - } - } - - x.xcidx (i+1) = ii; - } - - info = 0; - - x.maybe_compress (); - - return x; - -#else - - octave_unused_parameter (b); - - return SparseComplexMatrix (); - -#endif - } - - template <> - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::wide_solve - (const SparseMatrix& b, octave_idx_type& info) const - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - SparseComplexMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); - OCTAVE_LOCAL_BUFFER (double, B, nr); - - for (octave_idx_type i = 0; i < nr; i++) - B[i] = N->B[i]; - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_pvec) (S->q, - reinterpret_cast (Xx), - buf, nr); - CXSPARSE_ZNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); - } - - CXSPARSE_ZNAME (_pvec) (S->pinv, buf, - reinterpret_cast (Xx), - nc); - - for (octave_idx_type j = 0; j < nc; j++) - { - Complex tmp = Xx[j]; - - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; - } - } - - x.xcidx (i+1) = ii; - } - - info = 0; - - x.maybe_compress (); - - return x; - -#else - - octave_unused_parameter (b); - - return SparseComplexMatrix (); - -#endif - } - - template <> - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::tall_solve, - ComplexMatrix> - (const MArray& b, octave_idx_type& info) - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - const cs_complex_t *bvec = reinterpret_cast - (b.data ()); - - ComplexMatrix x (nc, b_nc); - cs_complex_t *vec = reinterpret_cast - (x.fortran_vec ()); - - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; - i++, idx+=nc, bidx+=b_nr) - { - octave_quit (); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_ZNAME (_usolve) (N->U, buf); - CXSPARSE_ZNAME (_ipvec) (S->q, buf, vec + idx, nc); - } - - info = 0; - - return x; - -#else - - octave_unused_parameter (b); - - return ComplexMatrix (); + octave_unused_parameter (a); + octave_unused_parameter (b); + octave_unused_parameter (info); + + return RET_T (); #endif - } - - template <> - template <> - ComplexMatrix - sparse_qr::sparse_qr_rep::wide_solve, - ComplexMatrix> - (const MArray& b, octave_idx_type& info) const - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - const cs_complex_t *bvec = reinterpret_cast - (b.data ()); - - ComplexMatrix x (nc, b_nc); - cs_complex_t *vec = reinterpret_cast (x.fortran_vec ()); - - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); - OCTAVE_LOCAL_BUFFER (double, B, nr); - - for (octave_idx_type i = 0; i < nr; i++) - B[i] = N->B[i]; - - for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc; - i++, idx+=nc, bidx+=b_nr) - { - octave_quit (); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_pvec) (S->q, bvec + bidx, buf, nr); - CXSPARSE_ZNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); - } - - CXSPARSE_ZNAME (_pvec) (S->pinv, buf, vec + idx, nc); - } - - info = 0; - - return x; - -#else - - octave_unused_parameter (b); - - return ComplexMatrix (); - -#endif - } - - template <> - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::tall_solve - (const SparseComplexMatrix& b, octave_idx_type& info) - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - octave_idx_type nr = nrows; - octave_idx_type nc = ncols; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - SparseComplexMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - - OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2); - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < S->m2; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_ipvec) (S->pinv, - reinterpret_cast (Xx), - buf, nr); - - for (volatile octave_idx_type j = 0; j < nc; j++) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, N->B[j], buf); - } - - CXSPARSE_ZNAME (_usolve) (N->U, buf); - CXSPARSE_ZNAME (_ipvec) (S->q, buf, - reinterpret_cast (Xx), - nc); - - for (octave_idx_type j = 0; j < nc; j++) - { - Complex tmp = Xx[j]; - - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; - } - } - - x.xcidx (i+1) = ii; - } - - info = 0; - - x.maybe_compress (); - - return x; - -#else - - octave_unused_parameter (b); - - return SparseComplexMatrix (); - -#endif - } - - template <> - template <> - SparseComplexMatrix - sparse_qr::sparse_qr_rep::wide_solve - (const SparseComplexMatrix& b, octave_idx_type& info) const - { - info = -1; - -#if defined (HAVE_CXSPARSE) - - // These are swapped because the original matrix was transposed in - // sparse_qr::solve. - - octave_idx_type nr = ncols; - octave_idx_type nc = nrows; - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - SparseComplexMatrix x (nc, b_nc, b.nnz ()); - x.xcidx (0) = 0; - - volatile octave_idx_type x_nz = b.nnz (); - volatile octave_idx_type ii = 0; - volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2); - - OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc)); - OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf); - OCTAVE_LOCAL_BUFFER (double, B, nr); - - for (octave_idx_type i = 0; i < nr; i++) - B[i] = N->B[i]; - - for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc) - { - octave_quit (); - - for (octave_idx_type j = 0; j < b_nr; j++) - Xx[j] = b.xelem (j, i); - - for (octave_idx_type j = nr; j < nbuf; j++) - buf[j] = cs_complex_t (0.0, 0.0); - - CXSPARSE_ZNAME (_pvec) (S->q, reinterpret_cast(Xx), - buf, nr); - CXSPARSE_ZNAME (_utsolve) (N->U, buf); - - for (volatile octave_idx_type j = nr-1; j >= 0; j--) - { - octave_quit (); - - CXSPARSE_ZNAME (_happly) (N->L, j, B[j], buf); - } - - CXSPARSE_ZNAME (_pvec) (S->pinv, buf, - reinterpret_cast(Xx), nc); - - for (octave_idx_type j = 0; j < nc; j++) - { - Complex tmp = Xx[j]; - - if (tmp != 0.0) - { - if (ii == x_nz) - { - // Resize the sparse matrix - octave_idx_type sz = x_nz * (b_nc - i) / b_nc; - sz = (sz > 10 ? sz : 10) + x_nz; - x.change_capacity (sz); - x_nz = sz; - } - - x.xdata (ii) = tmp; - x.xridx (ii++) = j; - } - } - - x.xcidx (i+1) = ii; - } - - info = 0; - - x.maybe_compress (); - - return x; - -#else - - octave_unused_parameter (b); - - return SparseComplexMatrix (); - -#endif - } - - template - sparse_qr::sparse_qr (void) - : m_rep (new sparse_qr_rep (SPARSE_T (), 0)) - { } - - template - sparse_qr::sparse_qr (const SPARSE_T& a, int order) - : m_rep (new sparse_qr_rep (a, order)) - { } - - template - bool - sparse_qr::ok (void) const - { - return m_rep->ok (); - } - - template - SPARSE_T - sparse_qr::V (void) const - { - return m_rep->V (); - } - - template - ColumnVector - sparse_qr::Pinv (void) const - { - return m_rep->P (); - } - - template - ColumnVector - sparse_qr::P (void) const - { - return m_rep->P (); - } - - template - ColumnVector - sparse_qr::E (void) const - { - return m_rep->E(); - } - - - template - SparseMatrix - sparse_qr::E_MAT (void) const - { - ColumnVector perm = m_rep->E (); - octave_idx_type nrows = perm.rows (); - SparseMatrix ret (nrows, nrows, nrows); - for (octave_idx_type i = 0; i < nrows; i++) - ret(perm(i) - 1, i) = 1.0; - return ret; - } - - - template - SPARSE_T - sparse_qr::R (bool econ) const - { - return m_rep->R (econ); - } - - template - typename SPARSE_T::dense_matrix_type - sparse_qr::C (const typename SPARSE_T::dense_matrix_type& b, - bool econ) const - { - return m_rep->C (b, econ); - } - - template - typename SPARSE_T::dense_matrix_type - sparse_qr::Q (bool econ) const - { - return m_rep->Q (econ); - } - -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - //specializations of function min2norm_solve - template <> - template <> - OCTAVE_API Matrix - sparse_qr::min2norm_solve, Matrix> - (const SparseMatrix& a, const MArray& b, - octave_idx_type& info, int order) - { - info = -1; - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - Matrix x (nc, b_nc); - cholmod_common cc; - - cholmod_l_start (&cc); - cholmod_sparse A = ros2rcs (a); - cholmod_dense B = rod2rcd (b); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); - spqr_error_handler (&cc); - - double *vec = x.fortran_vec (); - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast (X->x)[i]; - - info = 0; - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - } - cholmod_l_finish (&cc); - - return x; - - } - - template <> - template <> - OCTAVE_API SparseMatrix - sparse_qr::min2norm_solve - (const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info, - int order) - { - info = -1; - SparseMatrix x; - cholmod_common cc; - - cholmod_l_start (&cc); - cholmod_sparse A = ros2rcs (a); - cholmod_sparse B = ros2rcs (b); - cholmod_sparse *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); - spqr_error_handler (&cc); - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - delete [] reinterpret_cast (B.p); - delete [] reinterpret_cast (B.i); - } - - x = rcs2ros (X); - cholmod_l_finish (&cc); - info = 0; - - return x; - - } - - template <> - template <> - OCTAVE_API ComplexMatrix - sparse_qr::min2norm_solve, ComplexMatrix> - (const SparseMatrix& a, const MArray& b, - octave_idx_type& info, int order) - { - info = -1; - - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - - ComplexMatrix x (nc, b_nc); - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse *A = ros2ccs (a, &cc); - cholmod_dense B = cod2ccd (b); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, A, &B, &cc); - spqr_error_handler (&cc); - - Complex *vec = x.fortran_vec (); - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast (X->x)[i]; - - cholmod_l_free_sparse (&A, &cc); - cholmod_l_finish (&cc); - - info = 0; - - return x; - - } - - template <> - template <> - OCTAVE_API SparseComplexMatrix - sparse_qr::min2norm_solve - (const SparseMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info, int order) - { - info = -1; - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse *A = ros2ccs (a, &cc); - cholmod_sparse B = cos2ccs (b); - cholmod_sparse *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, A, &B, &cc); - spqr_error_handler (&cc); - - cholmod_l_free_sparse (&A, &cc); - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (B.p); - delete [] reinterpret_cast (B.i); - } - cholmod_l_finish (&cc); - - SparseComplexMatrix ret = ccs2cos(X); - - info = 0; - - return ret; - - } - - template <> - template <> - OCTAVE_API ComplexMatrix - sparse_qr::min2norm_solve, - ComplexMatrix> - (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info,int order) - { - info = -1; - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - ComplexMatrix x (nc, b_nc); - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_dense B = cod2ccd (b); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); - spqr_error_handler (&cc); - - Complex *vec = x.fortran_vec (); - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast (X->x)[i]; - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - } - cholmod_l_finish (&cc); - - info = 0; - - return x; - - } - - template <> - template <> - OCTAVE_API ComplexMatrix - sparse_qr::min2norm_solve, - ComplexMatrix> - (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info, int order) - { - info = -1; - - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - ComplexMatrix x (nc, b_nc); - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_dense *B = rod2ccd (b, &cc); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, B, &cc); - spqr_error_handler (&cc); - - Complex *vec = x.fortran_vec (); - - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast (X->x)[i]; - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - } - cholmod_l_free_dense (&B, &cc); - cholmod_l_finish (&cc); - - info = 0; - - return x; - - } - - template <> - template <> - OCTAVE_API SparseComplexMatrix - sparse_qr::min2norm_solve - (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info, int order) - { - info = -1; - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_sparse B = cos2ccs (b); - cholmod_sparse *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, &B, &cc); - spqr_error_handler (&cc); - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - delete [] reinterpret_cast (B.p); - delete [] reinterpret_cast (B.i); - } - cholmod_l_finish (&cc); - - info = 0; - - return ccs2cos (X); - - } - - template <> - template <> - OCTAVE_API SparseComplexMatrix - sparse_qr::min2norm_solve - (const SparseComplexMatrix& a, const SparseMatrix& b, - octave_idx_type& info,int order) - { - info = -1; - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_sparse *B = ros2ccs (b, &cc); - cholmod_sparse *X; - - X = SuiteSparseQR_min2norm (order, SPQR_DEFAULT_TOL, &A, B, &cc); - spqr_error_handler (&cc); - - SparseComplexMatrix ret = ccs2cos(X); - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast (A.p); - delete [] reinterpret_cast (A.i); - } - cholmod_l_free_sparse (&B, &cc); - cholmod_l_finish (&cc); - - info = 0; - - return ret; - - } -#endif - - // FIXME: Why is the "order" of the QR calculation as used in the - // CXSparse function sqr 3 for real matrices and 2 for complex? These - // values seem to be required but there was no explanation in David - // Bateman's original code. - - template - class - cxsparse_defaults - { - public: - enum { order = -1 }; - }; - - template <> - class - cxsparse_defaults - { - public: -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - enum { order = SPQR_ORDERING_DEFAULT }; -#elif defined (HAVE_CXSPARSE) - enum { order = 3 }; -#endif - }; - - template <> - class - cxsparse_defaults - { - public: -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - enum { order = SPQR_ORDERING_DEFAULT }; -#elif defined (HAVE_CXSPARSE) - enum { order = 2 }; -#endif - }; - - template - template - RET_T - sparse_qr::solve (const SPARSE_T& a, const RHS_T& b, - octave_idx_type& info) - { -#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - - info = -1; - - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.cols (); - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - int order = cxsparse_defaults::order; - - if (nr < 0 || nc < 0 || b_nc < 0 || b_nr < 0) - (*current_liboctave_error_handler) - ("matrix dimension with negative size"); - - if ( nr != b_nr) - (*current_liboctave_error_handler) - ("matrix dimension mismatch in solution of minimum norm problem"); - - info = 0; - - return min2norm_solve (a, b, info, order); - -#elif defined (HAVE_CXSPARSE) - - info = -1; - - octave_idx_type nr = a.rows (); - octave_idx_type nc = a.cols (); - - octave_idx_type b_nc = b.cols (); - octave_idx_type b_nr = b.rows (); - - int order = cxsparse_defaults::order; - - if (nr < 0 || nc < 0 || nr != b_nr) - (*current_liboctave_error_handler) - ("matrix dimension mismatch in solution of minimum norm problem"); - - if (nr == 0 || nc == 0 || b_nc == 0) - { - info = 0; - - return RET_T (nc, b_nc, 0.0); - } - else if (nr >= nc) - { - sparse_qr q (a, order); - - return q.ok () ? q.tall_solve (b, info) : RET_T (); - } - else - { - sparse_qr q (a.hermitian (), order); - - return q.ok () ? q.wide_solve (b, info) : RET_T (); - } - -#else - - octave_unused_parameter (a); - octave_unused_parameter (b); - octave_unused_parameter (info); - - return RET_T (); - -#endif - } - - //explicit instantiations of static member function solve - template - OCTAVE_API Matrix - sparse_qr::solve, Matrix> - (const SparseMatrix& a, const MArray& b, octave_idx_type& info); - - template - OCTAVE_API SparseMatrix - sparse_qr::solve - (const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info); - - template - OCTAVE_API ComplexMatrix - sparse_qr::solve, ComplexMatrix> - (const SparseMatrix& a, const MArray& b, octave_idx_type& info); - - template - OCTAVE_API SparseComplexMatrix - sparse_qr::solve - (const SparseMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info); - - template - OCTAVE_API ComplexMatrix - sparse_qr::solve, ComplexMatrix> - (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info); - - template - OCTAVE_API SparseComplexMatrix - sparse_qr::solve< - SparseComplexMatrix, SparseComplexMatrix> - (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info); - - template - OCTAVE_API ComplexMatrix - sparse_qr::solve, ComplexMatrix> - (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info); - - template - OCTAVE_API SparseComplexMatrix - sparse_qr::solve - (const SparseComplexMatrix& a, const SparseMatrix& b, - octave_idx_type& info); - - //explicit instantiations of member function E_MAT - template - OCTAVE_API SparseMatrix - sparse_qr::E_MAT (void) const; - - template - OCTAVE_API SparseMatrix - sparse_qr::E_MAT (void) const; - - template - template - RET_T - sparse_qr::tall_solve (const RHS_T& b, octave_idx_type& info) const - { - return m_rep->template tall_solve (b, info); - } - - template - template - RET_T - sparse_qr::wide_solve (const RHS_T& b, octave_idx_type& info) const - { - return m_rep->template wide_solve (b, info); - } - - // Explicitly instantiate all member functions - - template OCTAVE_API sparse_qr::sparse_qr (void); - template OCTAVE_API - sparse_qr::sparse_qr (const SparseMatrix& a, int order); - template OCTAVE_API bool sparse_qr::ok (void) const; - template OCTAVE_API ColumnVector sparse_qr::E (void) const; - template OCTAVE_API SparseMatrix sparse_qr::V (void) const; - template OCTAVE_API ColumnVector sparse_qr::Pinv (void) const; - template OCTAVE_API ColumnVector sparse_qr::P (void) const; - template OCTAVE_API SparseMatrix - sparse_qr::R (bool econ) const; - template OCTAVE_API Matrix - sparse_qr::C (const Matrix& b, bool econ) const; - template OCTAVE_API Matrix sparse_qr::Q (bool econ) const; - - template OCTAVE_API sparse_qr::sparse_qr (void); - template OCTAVE_API - sparse_qr::sparse_qr - (const SparseComplexMatrix& a, int order); - template OCTAVE_API bool sparse_qr::ok (void) const; - template OCTAVE_API ColumnVector - sparse_qr::E (void) const; - template OCTAVE_API SparseComplexMatrix - sparse_qr::V (void) const; - template OCTAVE_API ColumnVector - sparse_qr::Pinv (void) const; - template OCTAVE_API ColumnVector - sparse_qr::P (void) const; - template OCTAVE_API SparseComplexMatrix - sparse_qr::R (bool econ) const; - template OCTAVE_API ComplexMatrix - sparse_qr::C (const ComplexMatrix& b, bool econ) const; - template OCTAVE_API ComplexMatrix - sparse_qr::Q (bool econ) const; - - Matrix - qrsolve (const SparseMatrix& a, const MArray& b, - octave_idx_type& info) - { - return sparse_qr::solve, Matrix> (a, b, - info); - } - - SparseMatrix - qrsolve (const SparseMatrix& a, const SparseMatrix& b, - octave_idx_type& info) - { - return sparse_qr::solve (a, b, - info); - } - - ComplexMatrix - qrsolve (const SparseMatrix& a, const MArray& b, - octave_idx_type& info) - { - return sparse_qr::solve, - ComplexMatrix> (a, b, info); - } - - SparseComplexMatrix - qrsolve (const SparseMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info) - { - return sparse_qr::solve (a, b, info); - } - - ComplexMatrix - qrsolve (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info) - { - return sparse_qr::solve, - ComplexMatrix> (a, b, info); - } - - SparseComplexMatrix - qrsolve (const SparseComplexMatrix& a, const SparseMatrix& b, - octave_idx_type& info) - { - return sparse_qr::solve - (a, b, info); - } - - ComplexMatrix - qrsolve (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info) - { - return sparse_qr::solve, - ComplexMatrix> (a, b, info); - } - - SparseComplexMatrix - qrsolve (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info) - { - return sparse_qr::solve - (a, b, info); - } +} + +//explicit instantiations of static member function solve +template +OCTAVE_API Matrix +sparse_qr::solve, Matrix> +(const SparseMatrix& a, const MArray& b, octave_idx_type& info); + +template +OCTAVE_API SparseMatrix +sparse_qr::solve +(const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info); + +template +OCTAVE_API ComplexMatrix +sparse_qr::solve, ComplexMatrix> +(const SparseMatrix& a, const MArray& b, octave_idx_type& info); + +template +OCTAVE_API SparseComplexMatrix +sparse_qr::solve +(const SparseMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info); + +template +OCTAVE_API ComplexMatrix +sparse_qr::solve, ComplexMatrix> +(const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info); + +template +OCTAVE_API SparseComplexMatrix +sparse_qr::solve< +SparseComplexMatrix, SparseComplexMatrix> +(const SparseComplexMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info); + +template +OCTAVE_API ComplexMatrix +sparse_qr::solve, ComplexMatrix> +(const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info); + +template +OCTAVE_API SparseComplexMatrix +sparse_qr::solve +(const SparseComplexMatrix& a, const SparseMatrix& b, + octave_idx_type& info); + +//explicit instantiations of member function E_MAT +template +OCTAVE_API SparseMatrix +sparse_qr::E_MAT (void) const; + +template +OCTAVE_API SparseMatrix +sparse_qr::E_MAT (void) const; + +template +template +RET_T +sparse_qr::tall_solve (const RHS_T& b, octave_idx_type& info) const +{ + return m_rep->template tall_solve (b, info); +} + +template +template +RET_T +sparse_qr::wide_solve (const RHS_T& b, octave_idx_type& info) const +{ + return m_rep->template wide_solve (b, info); +} + +// Explicitly instantiate all member functions + +template OCTAVE_API sparse_qr::sparse_qr (void); +template OCTAVE_API +sparse_qr::sparse_qr (const SparseMatrix& a, int order); +template OCTAVE_API bool sparse_qr::ok (void) const; +template OCTAVE_API ColumnVector sparse_qr::E (void) const; +template OCTAVE_API SparseMatrix sparse_qr::V (void) const; +template OCTAVE_API ColumnVector sparse_qr::Pinv (void) const; +template OCTAVE_API ColumnVector sparse_qr::P (void) const; +template OCTAVE_API SparseMatrix +sparse_qr::R (bool econ) const; +template OCTAVE_API Matrix +sparse_qr::C (const Matrix& b, bool econ) const; +template OCTAVE_API Matrix sparse_qr::Q (bool econ) const; + +template OCTAVE_API sparse_qr::sparse_qr (void); +template OCTAVE_API +sparse_qr::sparse_qr +(const SparseComplexMatrix& a, int order); +template OCTAVE_API bool sparse_qr::ok (void) const; +template OCTAVE_API ColumnVector +sparse_qr::E (void) const; +template OCTAVE_API SparseComplexMatrix +sparse_qr::V (void) const; +template OCTAVE_API ColumnVector +sparse_qr::Pinv (void) const; +template OCTAVE_API ColumnVector +sparse_qr::P (void) const; +template OCTAVE_API SparseComplexMatrix +sparse_qr::R (bool econ) const; +template OCTAVE_API ComplexMatrix +sparse_qr::C (const ComplexMatrix& b, bool econ) const; +template OCTAVE_API ComplexMatrix +sparse_qr::Q (bool econ) const; + +Matrix +qrsolve (const SparseMatrix& a, const MArray& b, + octave_idx_type& info) +{ + return sparse_qr::solve, Matrix> (a, b, + info); +} + +SparseMatrix +qrsolve (const SparseMatrix& a, const SparseMatrix& b, + octave_idx_type& info) +{ + return sparse_qr::solve (a, b, + info); +} + +ComplexMatrix +qrsolve (const SparseMatrix& a, const MArray& b, + octave_idx_type& info) +{ + return sparse_qr::solve, + ComplexMatrix> (a, b, info); +} + +SparseComplexMatrix +qrsolve (const SparseMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info) +{ + return sparse_qr::solve (a, b, info); +} + +ComplexMatrix +qrsolve (const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info) +{ + return sparse_qr::solve, + ComplexMatrix> (a, b, info); +} + +SparseComplexMatrix +qrsolve (const SparseComplexMatrix& a, const SparseMatrix& b, + octave_idx_type& info) +{ + return sparse_qr::solve + (a, b, info); +} + +ComplexMatrix +qrsolve (const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info) +{ + return sparse_qr::solve, + ComplexMatrix> (a, b, info); +} + +SparseComplexMatrix +qrsolve (const SparseComplexMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info) +{ + return sparse_qr::solve + (a, b, info); +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/sparse-qr.h --- a/liboctave/numeric/sparse-qr.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/sparse-qr.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,121 +38,121 @@ OCTAVE_BEGIN_NAMESPACE(math) - // If the sparse matrix classes become templated on the element type - // (i.e., sparse_matrix), then it might be best to make the - // template parameter of this class also be the element type instead - // of the matrix type. +// If the sparse matrix classes become templated on the element type +// (i.e., sparse_matrix), then it might be best to make the +// template parameter of this class also be the element type instead +// of the matrix type. - template - class - sparse_qr - { - public: +template +class +sparse_qr +{ +public: - OCTAVE_API sparse_qr (void); + OCTAVE_API sparse_qr (void); #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD)) - // order = 7 selects SPQR default ordering - OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 7); + // order = 7 selects SPQR default ordering + OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 7); #else - OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 0); + OCTAVE_API sparse_qr (const SPARSE_T& a, int order = 0); #endif - sparse_qr (const sparse_qr& a) = default; + sparse_qr (const sparse_qr& a) = default; - ~sparse_qr (void) = default; + ~sparse_qr (void) = default; - sparse_qr& operator = (const sparse_qr& a) = default; + sparse_qr& operator = (const sparse_qr& a) = default; - OCTAVE_API bool ok (void) const; + OCTAVE_API bool ok (void) const; - OCTAVE_API ColumnVector E (void) const; + OCTAVE_API ColumnVector E (void) const; - // constructs permutation matrix from permutation vector rep -> E() - OCTAVE_API SparseMatrix E_MAT () const; + // constructs permutation matrix from permutation vector rep -> E() + OCTAVE_API SparseMatrix E_MAT () const; - OCTAVE_API SPARSE_T V (void) const; + OCTAVE_API SPARSE_T V (void) const; - OCTAVE_API ColumnVector Pinv (void) const; + OCTAVE_API ColumnVector Pinv (void) const; - OCTAVE_API ColumnVector P (void) const; + OCTAVE_API ColumnVector P (void) const; - OCTAVE_API SPARSE_T R (bool econ = false) const; + OCTAVE_API SPARSE_T R (bool econ = false) const; - OCTAVE_API typename SPARSE_T::dense_matrix_type - C (const typename SPARSE_T::dense_matrix_type& b, bool econ = false) const; + OCTAVE_API typename SPARSE_T::dense_matrix_type + C (const typename SPARSE_T::dense_matrix_type& b, bool econ = false) const; - OCTAVE_API typename SPARSE_T::dense_matrix_type - Q (bool econ = false) const; + OCTAVE_API typename SPARSE_T::dense_matrix_type + Q (bool econ = false) const; - template - static OCTAVE_API RET_T - solve (const SPARSE_T& a, const RHS_T& b, - octave_idx_type& info); + template + static OCTAVE_API RET_T + solve (const SPARSE_T& a, const RHS_T& b, + octave_idx_type& info); - private: +private: - template - static OCTAVE_API RET_T - min2norm_solve (const SPARSE_T& a, const RHS_T& b, - octave_idx_type& info, int order); + template + static OCTAVE_API RET_T + min2norm_solve (const SPARSE_T& a, const RHS_T& b, + octave_idx_type& info, int order); - template - OCTAVE_API RET_T - tall_solve (const RHS_T& b, octave_idx_type& info) const; + template + OCTAVE_API RET_T + tall_solve (const RHS_T& b, octave_idx_type& info) const; - template - OCTAVE_API RET_T - wide_solve (const RHS_T& b, octave_idx_type& info) const; + template + OCTAVE_API RET_T + wide_solve (const RHS_T& b, octave_idx_type& info) const; - //-------- - class sparse_qr_rep; + //-------- + class sparse_qr_rep; - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; - // extern instantiations with set visibility/export/import attribute +// extern instantiations with set visibility/export/import attribute - extern template class OCTAVE_EXTERN_TEMPLATE_API sparse_qr; +extern template class OCTAVE_EXTERN_TEMPLATE_API sparse_qr; - extern template class OCTAVE_EXTERN_TEMPLATE_API sparse_qr; +extern template class OCTAVE_EXTERN_TEMPLATE_API sparse_qr; - // Provide qrsolve for backward compatibility. +// Provide qrsolve for backward compatibility. - extern OCTAVE_API Matrix - qrsolve (const SparseMatrix& a, const MArray& b, - octave_idx_type& info); +extern OCTAVE_API Matrix +qrsolve (const SparseMatrix& a, const MArray& b, + octave_idx_type& info); - extern OCTAVE_API SparseMatrix - qrsolve (const SparseMatrix& a, const SparseMatrix& b, - octave_idx_type& info); +extern OCTAVE_API SparseMatrix +qrsolve (const SparseMatrix& a, const SparseMatrix& b, + octave_idx_type& info); - extern OCTAVE_API ComplexMatrix - qrsolve (const SparseMatrix& a, const MArray& b, - octave_idx_type& info); +extern OCTAVE_API ComplexMatrix +qrsolve (const SparseMatrix& a, const MArray& b, + octave_idx_type& info); - extern OCTAVE_API SparseComplexMatrix - qrsolve (const SparseMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info); +extern OCTAVE_API SparseComplexMatrix +qrsolve (const SparseMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info); - extern OCTAVE_API ComplexMatrix - qrsolve (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info); +extern OCTAVE_API ComplexMatrix +qrsolve (const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info); - extern OCTAVE_API SparseComplexMatrix - qrsolve (const SparseComplexMatrix& a, const SparseMatrix& b, - octave_idx_type& info); +extern OCTAVE_API SparseComplexMatrix +qrsolve (const SparseComplexMatrix& a, const SparseMatrix& b, + octave_idx_type& info); - extern OCTAVE_API ComplexMatrix - qrsolve (const SparseComplexMatrix& a, const MArray& b, - octave_idx_type& info); +extern OCTAVE_API ComplexMatrix +qrsolve (const SparseComplexMatrix& a, const MArray& b, + octave_idx_type& info); - extern OCTAVE_API SparseComplexMatrix - qrsolve (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info); +extern OCTAVE_API SparseComplexMatrix +qrsolve (const SparseComplexMatrix& a, const SparseComplexMatrix& b, + octave_idx_type& info); - typedef sparse_qr SparseQR; - typedef sparse_qr SparseComplexQR; +typedef sparse_qr SparseQR; +typedef sparse_qr SparseComplexQR; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/svd.cc --- a/liboctave/numeric/svd.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/svd.cc Thu Dec 01 20:05:44 2022 -0800 @@ -305,29 +305,29 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - T - svd::left_singular_matrix (void) const - { - if (m_type == svd::Type::sigma_only) - (*current_liboctave_error_handler) - ("svd: U not computed because type == svd::sigma_only"); +template +T +svd::left_singular_matrix (void) const +{ + if (m_type == svd::Type::sigma_only) + (*current_liboctave_error_handler) + ("svd: U not computed because type == svd::sigma_only"); - return m_left_sm; - } + return m_left_sm; +} - template - T - svd::right_singular_matrix (void) const - { - if (m_type == svd::Type::sigma_only) - (*current_liboctave_error_handler) - ("svd: V not computed because type == svd::sigma_only"); +template +T +svd::right_singular_matrix (void) const +{ + if (m_type == svd::Type::sigma_only) + (*current_liboctave_error_handler) + ("svd: V not computed because type == svd::sigma_only"); - return m_right_sm; - } + return m_right_sm; +} - // GESVD specializations +// GESVD specializations #define GESVD_REAL_STEP(f, F) \ F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobu, 1), \ @@ -348,83 +348,83 @@ F77_CHAR_ARG_LEN (1) \ F77_CHAR_ARG_LEN (1))) - // DGESVD - template<> - OCTAVE_API void - svd::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, - double *tmp_data, F77_INT m1, double *s_vec, - double *u, double *vt, F77_INT nrow_vt1, - std::vector& work, F77_INT& lwork, - F77_INT& info) - { - GESVD_REAL_STEP (dgesvd, DGESVD); +// DGESVD +template<> +OCTAVE_API void +svd::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, + double *tmp_data, F77_INT m1, double *s_vec, + double *u, double *vt, F77_INT nrow_vt1, + std::vector& work, F77_INT& lwork, + F77_INT& info) +{ + GESVD_REAL_STEP (dgesvd, DGESVD); - lwork = static_cast (work[0]); - work.reserve (lwork); + lwork = static_cast (work[0]); + work.reserve (lwork); - GESVD_REAL_STEP (dgesvd, DGESVD); - } + GESVD_REAL_STEP (dgesvd, DGESVD); +} - // SGESVD - template<> - OCTAVE_API void - svd::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, - float *tmp_data, F77_INT m1, float *s_vec, - float *u, float *vt, F77_INT nrow_vt1, - std::vector& work, F77_INT& lwork, - F77_INT& info) - { - GESVD_REAL_STEP (sgesvd, SGESVD); +// SGESVD +template<> +OCTAVE_API void +svd::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, + float *tmp_data, F77_INT m1, float *s_vec, + float *u, float *vt, F77_INT nrow_vt1, + std::vector& work, F77_INT& lwork, + F77_INT& info) +{ + GESVD_REAL_STEP (sgesvd, SGESVD); - lwork = static_cast (work[0]); - work.reserve (lwork); + lwork = static_cast (work[0]); + work.reserve (lwork); - GESVD_REAL_STEP (sgesvd, SGESVD); - } + GESVD_REAL_STEP (sgesvd, SGESVD); +} - // ZGESVD - template<> - OCTAVE_API void - svd::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, - Complex *tmp_data, F77_INT m1, double *s_vec, - Complex *u, Complex *vt, F77_INT nrow_vt1, - std::vector& work, F77_INT& lwork, - F77_INT& info) - { - std::vector rwork (5 * std::max (m, n)); +// ZGESVD +template<> +OCTAVE_API void +svd::gesvd (char& jobu, char& jobv, F77_INT m, F77_INT n, + Complex *tmp_data, F77_INT m1, double *s_vec, + Complex *u, Complex *vt, F77_INT nrow_vt1, + std::vector& work, F77_INT& lwork, + F77_INT& info) +{ + std::vector rwork (5 * std::max (m, n)); - GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); + GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); - lwork = static_cast (work[0].real ()); - work.reserve (lwork); + lwork = static_cast (work[0].real ()); + work.reserve (lwork); - GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); - } + GESVD_COMPLEX_STEP (zgesvd, ZGESVD, F77_DBLE_CMPLX_ARG); +} - // CGESVD - template<> - OCTAVE_API void - svd::gesvd (char& jobu, char& jobv, F77_INT m, - F77_INT n, FloatComplex *tmp_data, - F77_INT m1, float *s_vec, FloatComplex *u, - FloatComplex *vt, F77_INT nrow_vt1, - std::vector& work, - F77_INT& lwork, F77_INT& info) - { - std::vector rwork (5 * std::max (m, n)); +// CGESVD +template<> +OCTAVE_API void +svd::gesvd (char& jobu, char& jobv, F77_INT m, + F77_INT n, FloatComplex *tmp_data, + F77_INT m1, float *s_vec, FloatComplex *u, + FloatComplex *vt, F77_INT nrow_vt1, + std::vector& work, + F77_INT& lwork, F77_INT& info) +{ + std::vector rwork (5 * std::max (m, n)); - GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); + GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); - lwork = static_cast (work[0].real ()); - work.reserve (lwork); + lwork = static_cast (work[0].real ()); + work.reserve (lwork); - GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); - } + GESVD_COMPLEX_STEP (cgesvd, CGESVD, F77_CMPLX_ARG); +} #undef GESVD_REAL_STEP #undef GESVD_COMPLEX_STEP - // GESDD specializations +// GESDD specializations #define GESDD_REAL_STEP(f, F) \ F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&jobz, 1), \ @@ -441,100 +441,100 @@ rwork.data (), iwork, info \ F77_CHAR_ARG_LEN (1))) - // DGESDD - template<> - OCTAVE_API void - svd::gesdd (char& jobz, F77_INT m, F77_INT n, double *tmp_data, - F77_INT m1, double *s_vec, double *u, double *vt, - F77_INT nrow_vt1, std::vector& work, - F77_INT& lwork, F77_INT *iwork, F77_INT& info) - { - GESDD_REAL_STEP (dgesdd, DGESDD); +// DGESDD +template<> +OCTAVE_API void +svd::gesdd (char& jobz, F77_INT m, F77_INT n, double *tmp_data, + F77_INT m1, double *s_vec, double *u, double *vt, + F77_INT nrow_vt1, std::vector& work, + F77_INT& lwork, F77_INT *iwork, F77_INT& info) +{ + GESDD_REAL_STEP (dgesdd, DGESDD); - lwork = static_cast (work[0]); - work.reserve (lwork); + lwork = static_cast (work[0]); + work.reserve (lwork); - GESDD_REAL_STEP (dgesdd, DGESDD); - } + GESDD_REAL_STEP (dgesdd, DGESDD); +} - // SGESDD - template<> - OCTAVE_API void - svd::gesdd (char& jobz, F77_INT m, F77_INT n, float *tmp_data, - F77_INT m1, float *s_vec, float *u, float *vt, - F77_INT nrow_vt1, std::vector& work, - F77_INT& lwork, F77_INT *iwork, F77_INT& info) - { - GESDD_REAL_STEP (sgesdd, SGESDD); +// SGESDD +template<> +OCTAVE_API void +svd::gesdd (char& jobz, F77_INT m, F77_INT n, float *tmp_data, + F77_INT m1, float *s_vec, float *u, float *vt, + F77_INT nrow_vt1, std::vector& work, + F77_INT& lwork, F77_INT *iwork, F77_INT& info) +{ + GESDD_REAL_STEP (sgesdd, SGESDD); - lwork = static_cast (work[0]); - work.reserve (lwork); + lwork = static_cast (work[0]); + work.reserve (lwork); - GESDD_REAL_STEP (sgesdd, SGESDD); - } + GESDD_REAL_STEP (sgesdd, SGESDD); +} - // ZGESDD - template<> - OCTAVE_API void - svd::gesdd (char& jobz, F77_INT m, F77_INT n, - Complex *tmp_data, F77_INT m1, double *s_vec, - Complex *u, Complex *vt, F77_INT nrow_vt1, - std::vector& work, F77_INT& lwork, - F77_INT *iwork, F77_INT& info) - { +// ZGESDD +template<> +OCTAVE_API void +svd::gesdd (char& jobz, F77_INT m, F77_INT n, + Complex *tmp_data, F77_INT m1, double *s_vec, + Complex *u, Complex *vt, F77_INT nrow_vt1, + std::vector& work, F77_INT& lwork, + F77_INT *iwork, F77_INT& info) +{ - F77_INT min_mn = std::min (m, n); - F77_INT max_mn = std::max (m, n); + F77_INT min_mn = std::min (m, n); + F77_INT max_mn = std::max (m, n); - F77_INT lrwork; - if (jobz == 'N') - lrwork = 7*min_mn; - else - lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); + F77_INT lrwork; + if (jobz == 'N') + lrwork = 7*min_mn; + else + lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); - std::vector rwork (lrwork); + std::vector rwork (lrwork); - GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); + GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); - lwork = static_cast (work[0].real ()); - work.reserve (lwork); + lwork = static_cast (work[0].real ()); + work.reserve (lwork); - GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); - } + GESDD_COMPLEX_STEP (zgesdd, ZGESDD, F77_DBLE_CMPLX_ARG); +} - // CGESDD - template<> - OCTAVE_API void - svd::gesdd (char& jobz, F77_INT m, F77_INT n, - FloatComplex *tmp_data, F77_INT m1, - float *s_vec, FloatComplex *u, - FloatComplex *vt, F77_INT nrow_vt1, - std::vector& work, - F77_INT& lwork, F77_INT *iwork, - F77_INT& info) - { - F77_INT min_mn = std::min (m, n); - F77_INT max_mn = std::max (m, n); +// CGESDD +template<> +OCTAVE_API void +svd::gesdd (char& jobz, F77_INT m, F77_INT n, + FloatComplex *tmp_data, F77_INT m1, + float *s_vec, FloatComplex *u, + FloatComplex *vt, F77_INT nrow_vt1, + std::vector& work, + F77_INT& lwork, F77_INT *iwork, + F77_INT& info) +{ + F77_INT min_mn = std::min (m, n); + F77_INT max_mn = std::max (m, n); - F77_INT lrwork; - if (jobz == 'N') - lrwork = 7*min_mn; - else - lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); - std::vector rwork (lrwork); + F77_INT lrwork; + if (jobz == 'N') + lrwork = 7*min_mn; + else + lrwork = min_mn * std::max (5*min_mn+5, 2*max_mn+2*min_mn+1); + std::vector rwork (lrwork); - GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); + GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); - lwork = static_cast (work[0].real ()); - work.reserve (lwork); + lwork = static_cast (work[0].real ()); + work.reserve (lwork); - GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); - } + GESDD_COMPLEX_STEP (cgesdd, CGESDD, F77_CMPLX_ARG); +} #undef GESDD_REAL_STEP #undef GESDD_COMPLEX_STEP - // GEJSV specializations +// GEJSV specializations #define GEJSV_REAL_STEP(f, F) \ F77_XFCN (f, F, (F77_CONST_CHAR_ARG2 (&joba, 1), \ @@ -571,301 +571,301 @@ F77_CHAR_ARG_LEN (1) \ F77_CHAR_ARG_LEN (1))) - // DGEJSV - template<> - void - svd::gejsv (char& joba, char& jobu, char& jobv, - char& jobr, char& jobt, char& jobp, - F77_INT m, F77_INT n, - P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, - P *v, F77_INT nrow_v1, std::vector

& work, - F77_INT& lwork, std::vector& iwork, - F77_INT& info) - { - lwork = gejsv_lwork::optimal (joba, jobu, jobv, m, n); - work.reserve (lwork); +// DGEJSV +template<> +void +svd::gejsv (char& joba, char& jobu, char& jobv, + char& jobr, char& jobt, char& jobp, + F77_INT m, F77_INT n, + P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, + P *v, F77_INT nrow_v1, std::vector

& work, + F77_INT& lwork, std::vector& iwork, + F77_INT& info) +{ + lwork = gejsv_lwork::optimal (joba, jobu, jobv, m, n); + work.reserve (lwork); - GEJSV_REAL_STEP (dgejsv, DGEJSV); - } + GEJSV_REAL_STEP (dgejsv, DGEJSV); +} - // SGEJSV - template<> - void - svd::gejsv (char& joba, char& jobu, char& jobv, - char& jobr, char& jobt, char& jobp, - F77_INT m, F77_INT n, - P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, - P *v, F77_INT nrow_v1, std::vector

& work, - F77_INT& lwork, std::vector& iwork, - F77_INT& info) - { - lwork = gejsv_lwork::optimal (joba, jobu, jobv, m, n); - work.reserve (lwork); +// SGEJSV +template<> +void +svd::gejsv (char& joba, char& jobu, char& jobv, + char& jobr, char& jobt, char& jobp, + F77_INT m, F77_INT n, + P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, + P *v, F77_INT nrow_v1, std::vector

& work, + F77_INT& lwork, std::vector& iwork, + F77_INT& info) +{ + lwork = gejsv_lwork::optimal (joba, jobu, jobv, m, n); + work.reserve (lwork); - GEJSV_REAL_STEP (sgejsv, SGEJSV); - } + GEJSV_REAL_STEP (sgejsv, SGEJSV); +} - // ZGEJSV - template<> - void - svd::gejsv (char& joba, char& jobu, char& jobv, - char& jobr, char& jobt, char& jobp, - F77_INT m, F77_INT n, - P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, - P *v, F77_INT nrow_v1, std::vector

& work, - F77_INT& lwork, std::vector& iwork, - F77_INT& info) - { - F77_INT lrwork = -1; // work space size query - std::vector rwork (1); - work.reserve (2); +// ZGEJSV +template<> +void +svd::gejsv (char& joba, char& jobu, char& jobv, + char& jobr, char& jobt, char& jobp, + F77_INT m, F77_INT n, + P *tmp_data, F77_INT m1, DM_P *s_vec, P *u, + P *v, F77_INT nrow_v1, std::vector

& work, + F77_INT& lwork, std::vector& iwork, + F77_INT& info) +{ + F77_INT lrwork = -1; // work space size query + std::vector rwork (1); + work.reserve (2); - GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); + GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); - lwork = static_cast (work[0].real ()); - work.reserve (lwork); + lwork = static_cast (work[0].real ()); + work.reserve (lwork); - lrwork = static_cast (rwork[0]); - rwork.reserve (lrwork); + lrwork = static_cast (rwork[0]); + rwork.reserve (lrwork); - F77_INT liwork = static_cast (iwork[0]); - iwork.reserve (liwork); + F77_INT liwork = static_cast (iwork[0]); + iwork.reserve (liwork); - GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); - } + GEJSV_COMPLEX_STEP (zgejsv, ZGEJSV, F77_DBLE_CMPLX_ARG); +} - // CGEJSV - template<> - void - svd::gejsv (char& joba, char& jobu, char& jobv, - char& jobr, char& jobt, char& jobp, - F77_INT m, F77_INT n, P *tmp_data, - F77_INT m1, DM_P *s_vec, P *u, P *v, - F77_INT nrow_v1, std::vector

& work, - F77_INT& lwork, - std::vector& iwork, F77_INT& info) - { - F77_INT lrwork = -1; // work space size query - std::vector rwork (1); - work.reserve (2); +// CGEJSV +template<> +void +svd::gejsv (char& joba, char& jobu, char& jobv, + char& jobr, char& jobt, char& jobp, + F77_INT m, F77_INT n, P *tmp_data, + F77_INT m1, DM_P *s_vec, P *u, P *v, + F77_INT nrow_v1, std::vector

& work, + F77_INT& lwork, + std::vector& iwork, F77_INT& info) +{ + F77_INT lrwork = -1; // work space size query + std::vector rwork (1); + work.reserve (2); - GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); + GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); - lwork = static_cast (work[0].real ()); - work.reserve (lwork); + lwork = static_cast (work[0].real ()); + work.reserve (lwork); - lrwork = static_cast (rwork[0]); - rwork.reserve (lrwork); + lrwork = static_cast (rwork[0]); + rwork.reserve (lrwork); - F77_INT liwork = static_cast (iwork[0]); - iwork.reserve (liwork); + F77_INT liwork = static_cast (iwork[0]); + iwork.reserve (liwork); - GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); - } + GEJSV_COMPLEX_STEP (cgejsv, CGEJSV, F77_CMPLX_ARG); +} #undef GEJSV_REAL_STEP #undef GEJSV_COMPLEX_STEP - template - svd::svd (const T& a, svd::Type type, svd::Driver driver) - : m_type (type), m_driver (driver), m_left_sm (), m_sigma (), - m_right_sm () - { - F77_INT info; - - F77_INT m = to_f77_int (a.rows ()); - F77_INT n = to_f77_int (a.cols ()); - - if (m == 0 || n == 0) - { - switch (m_type) - { - case svd::Type::std: - m_left_sm = T (m, m, 0); - for (F77_INT i = 0; i < m; i++) - m_left_sm.xelem (i, i) = 1; - m_sigma = DM_T (m, n); - m_right_sm = T (n, n, 0); - for (F77_INT i = 0; i < n; i++) - m_right_sm.xelem (i, i) = 1; - break; +template +svd::svd (const T& a, svd::Type type, svd::Driver driver) + : m_type (type), m_driver (driver), m_left_sm (), m_sigma (), + m_right_sm () +{ + F77_INT info; - case svd::Type::economy: - m_left_sm = T (m, 0, 0); - m_sigma = DM_T (0, 0); - m_right_sm = T (n, 0, 0); - break; - - case svd::Type::sigma_only: - default: - m_sigma = DM_T (0, 1); - break; - } - return; - } + F77_INT m = to_f77_int (a.rows ()); + F77_INT n = to_f77_int (a.cols ()); - T atmp = a; - P *tmp_data = atmp.fortran_vec (); - - F77_INT min_mn = (m < n ? m : n); - - char jobu = 'A'; - char jobv = 'A'; - - F77_INT ncol_u = m; - F77_INT nrow_vt = n; - F77_INT nrow_s = m; - F77_INT ncol_s = n; - + if (m == 0 || n == 0) + { switch (m_type) { + case svd::Type::std: + m_left_sm = T (m, m, 0); + for (F77_INT i = 0; i < m; i++) + m_left_sm.xelem (i, i) = 1; + m_sigma = DM_T (m, n); + m_right_sm = T (n, n, 0); + for (F77_INT i = 0; i < n; i++) + m_right_sm.xelem (i, i) = 1; + break; + case svd::Type::economy: - jobu = jobv = 'S'; - ncol_u = nrow_vt = nrow_s = ncol_s = min_mn; + m_left_sm = T (m, 0, 0); + m_sigma = DM_T (0, 0); + m_right_sm = T (n, 0, 0); break; case svd::Type::sigma_only: - - // Note: for this case, both jobu and jobv should be 'N', but there - // seems to be a bug in dgesvd from Lapack V2.0. To demonstrate the - // bug, set both jobu and jobv to 'N' and find the singular values of - // [eye(3), eye(3)]. The result is [-sqrt(2), -sqrt(2), -sqrt(2)]. - // - // For Lapack 3.0, this problem seems to be fixed. - - jobu = jobv = 'N'; - ncol_u = nrow_vt = 1; - break; - default: + m_sigma = DM_T (0, 1); break; } + return; + } - if (! (jobu == 'N' || jobu == 'O')) - m_left_sm.resize (m, ncol_u); + T atmp = a; + P *tmp_data = atmp.fortran_vec (); + + F77_INT min_mn = (m < n ? m : n); + + char jobu = 'A'; + char jobv = 'A'; + + F77_INT ncol_u = m; + F77_INT nrow_vt = n; + F77_INT nrow_s = m; + F77_INT ncol_s = n; + + switch (m_type) + { + case svd::Type::economy: + jobu = jobv = 'S'; + ncol_u = nrow_vt = nrow_s = ncol_s = min_mn; + break; + + case svd::Type::sigma_only: - P *u = m_left_sm.fortran_vec (); + // Note: for this case, both jobu and jobv should be 'N', but there + // seems to be a bug in dgesvd from Lapack V2.0. To demonstrate the + // bug, set both jobu and jobv to 'N' and find the singular values of + // [eye(3), eye(3)]. The result is [-sqrt(2), -sqrt(2), -sqrt(2)]. + // + // For Lapack 3.0, this problem seems to be fixed. + + jobu = jobv = 'N'; + ncol_u = nrow_vt = 1; + break; + + default: + break; + } + + if (! (jobu == 'N' || jobu == 'O')) + m_left_sm.resize (m, ncol_u); + + P *u = m_left_sm.fortran_vec (); + + m_sigma.resize (nrow_s, ncol_s); + DM_P *s_vec = m_sigma.fortran_vec (); - m_sigma.resize (nrow_s, ncol_s); - DM_P *s_vec = m_sigma.fortran_vec (); + if (! (jobv == 'N' || jobv == 'O')) + { + if (m_driver == svd::Driver::GEJSV) + m_right_sm.resize (n, nrow_vt); + else + m_right_sm.resize (nrow_vt, n); + } + + P *vt = m_right_sm.fortran_vec (); + + // Query _GESVD for the correct dimension of WORK. + + F77_INT lwork = -1; + + std::vector

work (1); - if (! (jobv == 'N' || jobv == 'O')) + const F77_INT f77_int_one = static_cast (1); + F77_INT m1 = std::max (m, f77_int_one); + F77_INT nrow_vt1 = std::max (nrow_vt, f77_int_one); + + if (m_driver == svd::Driver::GESVD) + gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, + work, lwork, info); + else if (m_driver == svd::Driver::GESDD) + { + assert (jobu == jobv); + char jobz = jobu; + + std::vector iwork (8 * std::min (m, n)); + + gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, + work, lwork, iwork.data (), info); + } + else if (m_driver == svd::Driver::GEJSV) + { + bool transposed = false; + if (n > m) { - if (m_driver == svd::Driver::GEJSV) - m_right_sm.resize (n, nrow_vt); - else - m_right_sm.resize (nrow_vt, n); + // GEJSV only accepts m >= n, thus we need to transpose here + transposed = true; + + std::swap (m, n); + m1 = std::max (m, f77_int_one); + nrow_vt1 = std::max (n, f77_int_one); // we have m > n + if (m_type == svd::Type::sigma_only) + nrow_vt1 = 1; + std::swap (jobu, jobv); + + atmp = atmp.hermitian (); + tmp_data = atmp.fortran_vec (); + + // Swap pointers of U and V. + u = m_right_sm.fortran_vec (); + vt = m_left_sm.fortran_vec (); } - P *vt = m_right_sm.fortran_vec (); - - // Query _GESVD for the correct dimension of WORK. - - F77_INT lwork = -1; - - std::vector

work (1); - - const F77_INT f77_int_one = static_cast (1); - F77_INT m1 = std::max (m, f77_int_one); - F77_INT nrow_vt1 = std::max (nrow_vt, f77_int_one); - - if (m_driver == svd::Driver::GESVD) - gesvd (jobu, jobv, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, - work, lwork, info); - else if (m_driver == svd::Driver::GESDD) - { - assert (jobu == jobv); - char jobz = jobu; - - std::vector iwork (8 * std::min (m, n)); + // translate jobu and jobv from gesvd to gejsv. + std::unordered_map job_svd2jsv; + job_svd2jsv['A'] = "FJ"; + job_svd2jsv['S'] = "UV"; + job_svd2jsv['O'] = "WW"; + job_svd2jsv['N'] = "NN"; + jobu = job_svd2jsv[jobu][0]; + jobv = job_svd2jsv[jobv][1]; - gesdd (jobz, m, n, tmp_data, m1, s_vec, u, vt, nrow_vt1, - work, lwork, iwork.data (), info); - } - else if (m_driver == svd::Driver::GEJSV) - { - bool transposed = false; - if (n > m) - { - // GEJSV only accepts m >= n, thus we need to transpose here - transposed = true; + char joba = 'F'; // 'F': most conservative + char jobr = 'R'; // 'R' is recommended. + char jobt = 'N'; // or 'T', but that requires U and V appear together + char jobp = 'N'; // use 'P' if denormal is poorly implemented. - std::swap (m, n); - m1 = std::max (m, f77_int_one); - nrow_vt1 = std::max (n, f77_int_one); // we have m > n - if (m_type == svd::Type::sigma_only) - nrow_vt1 = 1; - std::swap (jobu, jobv); + std::vector iwork (std::max (m + 3*n, 1)); - atmp = atmp.hermitian (); - tmp_data = atmp.fortran_vec (); - - // Swap pointers of U and V. - u = m_right_sm.fortran_vec (); - vt = m_left_sm.fortran_vec (); - } + gejsv (joba, jobu, jobv, jobr, jobt, jobp, m, n, tmp_data, m1, + s_vec, u, vt, nrow_vt1, work, lwork, iwork, info); - // translate jobu and jobv from gesvd to gejsv. - std::unordered_map job_svd2jsv; - job_svd2jsv['A'] = "FJ"; - job_svd2jsv['S'] = "UV"; - job_svd2jsv['O'] = "WW"; - job_svd2jsv['N'] = "NN"; - jobu = job_svd2jsv[jobu][0]; - jobv = job_svd2jsv[jobv][1]; - - char joba = 'F'; // 'F': most conservative - char jobr = 'R'; // 'R' is recommended. - char jobt = 'N'; // or 'T', but that requires U and V appear together - char jobp = 'N'; // use 'P' if denormal is poorly implemented. - - std::vector iwork (std::max (m + 3*n, 1)); - - gejsv (joba, jobu, jobv, jobr, jobt, jobp, m, n, tmp_data, m1, - s_vec, u, vt, nrow_vt1, work, lwork, iwork, info); - - if (iwork[2] == 1) - (*current_liboctave_warning_with_id_handler) - ("Octave:convergence", "svd: (driver: GEJSV) " - "Denormal occurred, possible loss of accuracy."); + if (iwork[2] == 1) + (*current_liboctave_warning_with_id_handler) + ("Octave:convergence", "svd: (driver: GEJSV) " + "Denormal occurred, possible loss of accuracy."); - if (info < 0) - (*current_liboctave_error_handler) - ("svd: (driver: GEJSV) Illegal argument at #%d", - static_cast (-info)); - else if (info > 0) - (*current_liboctave_warning_with_id_handler) - ("Octave:convergence", "svd: (driver: GEJSV) " - "Fail to converge within max sweeps, " - "possible inaccurate result."); + if (info < 0) + (*current_liboctave_error_handler) + ("svd: (driver: GEJSV) Illegal argument at #%d", + static_cast (-info)); + else if (info > 0) + (*current_liboctave_warning_with_id_handler) + ("Octave:convergence", "svd: (driver: GEJSV) " + "Fail to converge within max sweeps, " + "possible inaccurate result."); - if (transposed) // put things that need to transpose back here - std::swap (m, n); - } - else - (*current_liboctave_error_handler) ("svd: unknown driver"); + if (transposed) // put things that need to transpose back here + std::swap (m, n); + } + else + (*current_liboctave_error_handler) ("svd: unknown driver"); - // LAPACK can return -0 which is a small problem (bug #55710). - for (octave_idx_type i = 0; i < m_sigma.diag_length (); i++) - { - if (! m_sigma.dgxelem (i)) - m_sigma.dgxelem (i) = DM_P (0); - } - - // GESVD and GESDD return VT instead of V, GEJSV return V. - if (! (jobv == 'N' || jobv == 'O') && (m_driver != svd::Driver::GEJSV)) - m_right_sm = m_right_sm.hermitian (); + // LAPACK can return -0 which is a small problem (bug #55710). + for (octave_idx_type i = 0; i < m_sigma.diag_length (); i++) + { + if (! m_sigma.dgxelem (i)) + m_sigma.dgxelem (i) = DM_P (0); } - // Instantiations we need. + // GESVD and GESDD return VT instead of V, GEJSV return V. + if (! (jobv == 'N' || jobv == 'O') && (m_driver != svd::Driver::GEJSV)) + m_right_sm = m_right_sm.hermitian (); +} - template class svd; +// Instantiations we need. - template class svd; +template class svd; + +template class svd; - template class svd; +template class svd; - template class svd; +template class svd; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/numeric/svd.h --- a/liboctave/numeric/svd.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/numeric/svd.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,95 +34,95 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - class - OCTAVE_API - svd - { - public: - - typedef typename T::real_diag_matrix_type DM_T; +template +class +OCTAVE_API +svd +{ +public: - enum class Type - { - std, - economy, - sigma_only - }; + typedef typename T::real_diag_matrix_type DM_T; - enum class Driver - { - GESVD, - GESDD, - GEJSV - }; + enum class Type + { + std, + economy, + sigma_only + }; - svd (void) - : m_type (), m_driver (), m_left_sm (), m_sigma (), m_right_sm () - { } + enum class Driver + { + GESVD, + GESDD, + GEJSV + }; - svd (const T& a, svd::Type type = svd::Type::std, - svd::Driver driver = svd::Driver::GESVD); + svd (void) + : m_type (), m_driver (), m_left_sm (), m_sigma (), m_right_sm () + { } - svd (const svd& a) - : m_type (a.m_type), m_driver (a.m_driver), m_left_sm (a.m_left_sm), - m_sigma (a.m_sigma), m_right_sm (a.m_right_sm) - { } + svd (const T& a, svd::Type type = svd::Type::std, + svd::Driver driver = svd::Driver::GESVD); - svd& operator = (const svd& a) + svd (const svd& a) + : m_type (a.m_type), m_driver (a.m_driver), m_left_sm (a.m_left_sm), + m_sigma (a.m_sigma), m_right_sm (a.m_right_sm) + { } + + svd& operator = (const svd& a) + { + if (this != &a) { - if (this != &a) - { - m_type = a.m_type; - m_left_sm = a.m_left_sm; - m_sigma = a.m_sigma; - m_right_sm = a.m_right_sm; - m_driver = a.m_driver; - } - - return *this; + m_type = a.m_type; + m_left_sm = a.m_left_sm; + m_sigma = a.m_sigma; + m_right_sm = a.m_right_sm; + m_driver = a.m_driver; } - ~svd (void) = default; - - T left_singular_matrix (void) const; + return *this; + } - DM_T singular_values (void) const { return m_sigma; } + ~svd (void) = default; - T right_singular_matrix (void) const; + T left_singular_matrix (void) const; - private: + DM_T singular_values (void) const { return m_sigma; } - typedef typename T::element_type P; - typedef typename DM_T::element_type DM_P; + T right_singular_matrix (void) const; + +private: - svd::Type m_type; - svd::Driver m_driver; + typedef typename T::element_type P; + typedef typename DM_T::element_type DM_P; - T m_left_sm; - DM_T m_sigma; - T m_right_sm; + svd::Type m_type; + svd::Driver m_driver; - void gesvd (char& jobu, char& jobv, octave_f77_int_type m, - octave_f77_int_type n, P *tmp_data, octave_f77_int_type m1, - DM_P *s_vec, P *u, P *vt, octave_f77_int_type nrow_vt1, - std::vector

& work, octave_f77_int_type& lwork, - octave_f77_int_type& info); + T m_left_sm; + DM_T m_sigma; + T m_right_sm; + + void gesvd (char& jobu, char& jobv, octave_f77_int_type m, + octave_f77_int_type n, P *tmp_data, octave_f77_int_type m1, + DM_P *s_vec, P *u, P *vt, octave_f77_int_type nrow_vt1, + std::vector

& work, octave_f77_int_type& lwork, + octave_f77_int_type& info); - void gesdd (char& jobz, octave_f77_int_type m, octave_f77_int_type n, - P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, - P *vt, octave_f77_int_type nrow_vt1, std::vector

& work, - octave_f77_int_type& lwork, octave_f77_int_type *iwork, - octave_f77_int_type& info); + void gesdd (char& jobz, octave_f77_int_type m, octave_f77_int_type n, + P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, + P *vt, octave_f77_int_type nrow_vt1, std::vector

& work, + octave_f77_int_type& lwork, octave_f77_int_type *iwork, + octave_f77_int_type& info); - void gejsv (char& joba, char& jobu, char& jobv, char& jobr, char& jobt, - char& jobp, octave_f77_int_type m, octave_f77_int_type n, - P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, - P *v, octave_f77_int_type nrow_v1, std::vector

& work, - octave_f77_int_type& lwork, - std::vector& iwork, - octave_f77_int_type& info); - }; + void gejsv (char& joba, char& jobu, char& jobv, char& jobr, char& jobt, + char& jobp, octave_f77_int_type m, octave_f77_int_type n, + P *tmp_data, octave_f77_int_type m1, DM_P *s_vec, P *u, + P *v, octave_f77_int_type nrow_v1, std::vector

& work, + octave_f77_int_type& lwork, + std::vector& iwork, + octave_f77_int_type& info); +}; OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/child-list.cc --- a/liboctave/system/child-list.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/child-list.cc Thu Dec 01 20:05:44 2022 -0800 @@ -32,70 +32,70 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void child_list::remove (pid_t pid) - { - m_list.remove_if ([pid] (const child& oc) { return oc.m_pid == pid; }); - } +void child_list::remove (pid_t pid) +{ + m_list.remove_if ([pid] (const child& oc) { return oc.m_pid == pid; }); +} - void child_list::child_list::insert (pid_t pid, child::child_event_handler f) - { - m_list.append (child (pid, f)); - } +void child_list::child_list::insert (pid_t pid, child::child_event_handler f) +{ + m_list.append (child (pid, f)); +} - void child_list::reap (void) - { - // Mark the record for PID invalid. +void child_list::reap (void) +{ + // Mark the record for PID invalid. - for (auto& oc : m_list) - { - // The call to the child::child_event_handler might - // invalidate the iterator (for example, by calling - // child_list::remove), so we increment the iterator - // here. + for (auto& oc : m_list) + { + // The call to the child::child_event_handler might + // invalidate the iterator (for example, by calling + // child_list::remove), so we increment the iterator + // here. - if (oc.m_have_status) - { - oc.m_have_status = 0; + if (oc.m_have_status) + { + oc.m_have_status = 0; - child::child_event_handler f = oc.m_handler; + child::child_event_handler f = oc.m_handler; - if (f && f (oc.m_pid, oc.m_status)) - oc.m_pid = -1; - } - } + if (f && f (oc.m_pid, oc.m_status)) + oc.m_pid = -1; + } + } - // Remove PIDs that have completed above. - remove (-1); - } + // Remove PIDs that have completed above. + remove (-1); +} - // Wait on our children and record any changes in their status. +// Wait on our children and record any changes in their status. - bool child_list::wait (void) - { - bool retval = false; +bool child_list::wait (void) +{ + bool retval = false; - for (auto& oc : m_list) - { - pid_t pid = oc.m_pid; + for (auto& oc : m_list) + { + pid_t pid = oc.m_pid; - if (pid > 0) - { - int status; + if (pid > 0) + { + int status; - if (sys::waitpid (pid, &status, sys::wnohang ()) > 0) - { - oc.m_have_status = 1; + if (sys::waitpid (pid, &status, sys::wnohang ()) > 0) + { + oc.m_have_status = 1; - oc.m_status = status; + oc.m_status = status; - retval = true; + retval = true; - break; - } - } - } + break; + } + } + } - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/child-list.h --- a/liboctave/system/child-list.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/child-list.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,60 +36,60 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class OCTAVE_API child - { - public: +class OCTAVE_API child +{ +public: - // Do whatever to handle event for child with PID (might not - // actually be dead, could just be stopped). Return true if - // the list element corresponding to PID should be removed from - // list. This function should not call any functions that modify - // the child_list. + // Do whatever to handle event for child with PID (might not + // actually be dead, could just be stopped). Return true if + // the list element corresponding to PID should be removed from + // list. This function should not call any functions that modify + // the child_list. - typedef bool (*child_event_handler) (pid_t, int); + typedef bool (*child_event_handler) (pid_t, int); - child (pid_t pid = -1, child_event_handler f = nullptr) - : m_pid (pid), m_handler (f), m_have_status (0), m_status (0) - { } + child (pid_t pid = -1, child_event_handler f = nullptr) + : m_pid (pid), m_handler (f), m_have_status (0), m_status (0) + { } - child (const child&) = default; + child (const child&) = default; - child& operator = (const child&) = default; + child& operator = (const child&) = default; - ~child (void) = default; + ~child (void) = default; - // The process ID of this child. - pid_t m_pid; + // The process ID of this child. + pid_t m_pid; - // The function we call if an event happens for this child. - child_event_handler m_handler; + // The function we call if an event happens for this child. + child_event_handler m_handler; - // Nonzero if this child has stopped or terminated. - sig_atomic_t m_have_status; + // Nonzero if this child has stopped or terminated. + sig_atomic_t m_have_status; - // The m_status of this child; 0 if running, otherwise a m_status value - // from waitpid. - int m_status; - }; + // The m_status of this child; 0 if running, otherwise a m_status value + // from waitpid. + int m_status; +}; - class OCTAVE_API child_list - { - public: +class OCTAVE_API child_list +{ +public: - child_list (void) { } + child_list (void) { } - void insert (pid_t pid, child::child_event_handler f); + void insert (pid_t pid, child::child_event_handler f); - void remove (pid_t pid); + void remove (pid_t pid); - void reap (void); + void reap (void); - bool wait (void); + bool wait (void); - private: +private: - base_list m_list; - }; + base_list m_list; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/dir-ops.cc --- a/liboctave/system/dir-ops.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/dir-ops.cc Thu Dec 01 20:05:44 2022 -0800 @@ -46,69 +46,69 @@ OCTAVE_BEGIN_NAMESPACE(sys) - bool - dir_entry::open (const std::string& n) +bool +dir_entry::open (const std::string& n) +{ + if (! n.empty ()) + m_name = n; + + if (! m_name.empty ()) { - if (! n.empty ()) - m_name = n; + close (); - if (! m_name.empty ()) - { - close (); + std::string fullname = sys::file_ops::tilde_expand (m_name); + + m_dir = octave_opendir_wrapper (fullname.c_str ()); - std::string fullname = sys::file_ops::tilde_expand (m_name); + if (! m_dir) + m_errmsg = std::strerror (errno); + } + else + m_errmsg = "dir_entry::open: empty filename"; - m_dir = octave_opendir_wrapper (fullname.c_str ()); + return m_dir != nullptr; +} - if (! m_dir) - m_errmsg = std::strerror (errno); - } - else - m_errmsg = "dir_entry::open: empty filename"; +string_vector +dir_entry::read (void) +{ + string_vector retval; - return m_dir != nullptr; + if (ok ()) + { + std::list dirlist; + + char *fname; + + while ((fname = octave_readdir_wrapper (m_dir))) + dirlist.push_back (fname); + + retval = string_vector (dirlist); } - string_vector - dir_entry::read (void) - { - string_vector retval; - - if (ok ()) - { - std::list dirlist; + return retval; +} - char *fname; - - while ((fname = octave_readdir_wrapper (m_dir))) - dirlist.push_back (fname); +bool +dir_entry::close (void) +{ + bool retval = true; - retval = string_vector (dirlist); - } + if (m_dir) + { + retval = (octave_closedir_wrapper (m_dir) == 0); - return retval; + m_dir = nullptr; } - bool - dir_entry::close (void) - { - bool retval = true; - - if (m_dir) - { - retval = (octave_closedir_wrapper (m_dir) == 0); + return retval; +} - m_dir = nullptr; - } - - return retval; - } - - unsigned int - dir_entry::max_name_length (void) - { - return octave_name_max_wrapper (); - } +unsigned int +dir_entry::max_name_length (void) +{ + return octave_name_max_wrapper (); +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/dir-ops.h --- a/liboctave/system/dir-ops.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/dir-ops.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,75 +36,75 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class - OCTAVE_API - dir_entry - { +class +OCTAVE_API +dir_entry +{ + + // NOTE: This class cannot be used safely cross-platform (Windows) with + // non-ASCII characters in paths. + // Consider replacing the implementation using std::filesystem (C++ 17). + // In the meantime, consider using sys::get_dirlist instead. + +public: - // NOTE: This class cannot be used safely cross-platform (Windows) with - // non-ASCII characters in paths. - // Consider replacing the implementation using std::filesystem (C++ 17). - // In the meantime, consider using sys::get_dirlist instead. + dir_entry (const std::string& n = "") + : m_name (n), m_dir (nullptr), m_fail (false), m_errmsg () + { + if (! m_name.empty ()) + open (); + } - public: + dir_entry (const dir_entry& d) + : m_name (d.m_name), m_dir (d.m_dir), m_fail (d.m_fail), + m_errmsg (d.m_errmsg) + { } - dir_entry (const std::string& n = "") - : m_name (n), m_dir (nullptr), m_fail (false), m_errmsg () + dir_entry& operator = (const dir_entry& d) + { + if (this != &d) { - if (! m_name.empty ()) - open (); + m_name = d.m_name; + m_dir = d.m_dir; + m_fail = d.m_fail; + m_errmsg = d.m_errmsg; } - dir_entry (const dir_entry& d) - : m_name (d.m_name), m_dir (d.m_dir), m_fail (d.m_fail), - m_errmsg (d.m_errmsg) - { } + return *this; + } + + ~dir_entry (void) { close (); } + + bool open (const std::string& = ""); - dir_entry& operator = (const dir_entry& d) - { - if (this != &d) - { - m_name = d.m_name; - m_dir = d.m_dir; - m_fail = d.m_fail; - m_errmsg = d.m_errmsg; - } + string_vector read (void); + + bool close (void); - return *this; - } + bool ok (void) const { return m_dir && ! m_fail; } - ~dir_entry (void) { close (); } + operator bool () const { return ok (); } - bool open (const std::string& = ""); - - string_vector read (void); + std::string error (void) const { return ok () ? "" : m_errmsg; } - bool close (void); - - bool ok (void) const { return m_dir && ! m_fail; } - - operator bool () const { return ok (); } + static unsigned int max_name_length (void); - std::string error (void) const { return ok () ? "" : m_errmsg; } +private: - static unsigned int max_name_length (void); - - private: + // Name of the directory. + std::string m_name; - // Name of the directory. - std::string m_name; + // A pointer to the contents of the directory. We use void here to + // avoid possible conflicts with the way some systems declare the + // type DIR. + void *m_dir; - // A pointer to the contents of the directory. We use void here to - // avoid possible conflicts with the way some systems declare the - // type DIR. - void *m_dir; + // TRUE means the open for this directory failed. + bool m_fail; - // TRUE means the open for this directory failed. - bool m_fail; - - // If a failure occurs, this contains the system error text. - std::string m_errmsg; - }; + // If a failure occurs, this contains the system error text. + std::string m_errmsg; +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/file-ops.cc --- a/liboctave/system/file-ops.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/file-ops.cc Thu Dec 01 20:05:44 2022 -0800 @@ -59,814 +59,814 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // The following tilde-expansion code was stolen and adapted from - // readline. +// The following tilde-expansion code was stolen and adapted from +// readline. - // The default value of tilde_additional_prefixes. This is set to - // whitespace preceding a tilde so that simple programs which do not - // perform any word separation get desired behavior. - static const char *default_prefixes[] = { " ~", "\t~", ":~", nullptr }; +// The default value of tilde_additional_prefixes. This is set to +// whitespace preceding a tilde so that simple programs which do not +// perform any word separation get desired behavior. +static const char *default_prefixes[] = { " ~", "\t~", ":~", nullptr }; - // The default value of tilde_additional_suffixes. This is set to - // whitespace or newline so that simple programs which do not perform - // any word separation get desired behavior. - static const char *default_suffixes[] = { " ", "\n", ":", nullptr }; +// The default value of tilde_additional_suffixes. This is set to +// whitespace or newline so that simple programs which do not perform +// any word separation get desired behavior. +static const char *default_suffixes[] = { " ", "\n", ":", nullptr }; - static std::size_t - tilde_find_prefix (const std::string& s, std::size_t& len) - { - len = 0; +static std::size_t +tilde_find_prefix (const std::string& s, std::size_t& len) +{ + len = 0; - std::size_t s_len = s.length (); + std::size_t s_len = s.length (); - if (s_len == 0 || s[0] == '~') - return 0; + if (s_len == 0 || s[0] == '~') + return 0; - string_vector prefixes = sys::file_ops::tilde_additional_prefixes; + string_vector prefixes = sys::file_ops::tilde_additional_prefixes; - if (! prefixes.empty ()) - { - for (std::size_t i = 0; i < s_len; i++) - { - for (int j = 0; j < prefixes.numel (); j++) - { - std::size_t pfx_len = prefixes[j].length (); + if (! prefixes.empty ()) + { + for (std::size_t i = 0; i < s_len; i++) + { + for (int j = 0; j < prefixes.numel (); j++) + { + std::size_t pfx_len = prefixes[j].length (); - if (prefixes[j] == s.substr (i, pfx_len)) - { - len = pfx_len - 1; - return i + len; - } - } - } - } + if (prefixes[j] == s.substr (i, pfx_len)) + { + len = pfx_len - 1; + return i + len; + } + } + } + } - return s_len; - } + return s_len; +} - // Find the end of a tilde expansion in S, and return the index - // of the character which ends the tilde definition. +// Find the end of a tilde expansion in S, and return the index +// of the character which ends the tilde definition. - static std::size_t - tilde_find_suffix (const std::string& s) - { - std::size_t s_len = s.length (); +static std::size_t +tilde_find_suffix (const std::string& s) +{ + std::size_t s_len = s.length (); - string_vector suffixes = sys::file_ops::tilde_additional_suffixes; + string_vector suffixes = sys::file_ops::tilde_additional_suffixes; - std::size_t i = 0; + std::size_t i = 0; - for ( ; i < s_len; i++) - { - if (sys::file_ops::is_dir_sep (s[i])) - break; + for ( ; i < s_len; i++) + { + if (sys::file_ops::is_dir_sep (s[i])) + break; - if (! suffixes.empty ()) - { - for (int j = 0; j < suffixes.numel (); j++) - { - std::size_t sfx_len = suffixes[j].length (); + if (! suffixes.empty ()) + { + for (int j = 0; j < suffixes.numel (); j++) + { + std::size_t sfx_len = suffixes[j].length (); - if (suffixes[j] == s.substr (i, sfx_len)) - return i; - } - } - } + if (suffixes[j] == s.substr (i, sfx_len)) + return i; + } + } + } - return i; - } + return i; +} - // Take FNAME and return the tilde prefix we want expanded. +// Take FNAME and return the tilde prefix we want expanded. - static std::string - isolate_tilde_prefix (const std::string& fname) - { - std::size_t f_len = fname.length (); +static std::string +isolate_tilde_prefix (const std::string& fname) +{ + std::size_t f_len = fname.length (); - std::size_t len = 1; + std::size_t len = 1; - while (len < f_len && ! sys::file_ops::is_dir_sep (fname[len])) - len++; + while (len < f_len && ! sys::file_ops::is_dir_sep (fname[len])) + len++; - return fname.substr (1, len); - } + return fname.substr (1, len); +} - // Do the work of tilde expansion on FILENAME. FILENAME starts with a - // tilde. +// Do the work of tilde expansion on FILENAME. FILENAME starts with a +// tilde. - static std::string - tilde_expand_word (const std::string& filename) - { - std::size_t f_len = filename.length (); +static std::string +tilde_expand_word (const std::string& filename) +{ + std::size_t f_len = filename.length (); - if (f_len == 0 || filename[0] != '~') - return std::string (filename); + if (f_len == 0 || filename[0] != '~') + return std::string (filename); - // A leading '~/' or a bare '~' is *always* translated to the value - // of $HOME or the home directory of the current user, regardless of - // any preexpansion hook. + // A leading '~/' or a bare '~' is *always* translated to the value + // of $HOME or the home directory of the current user, regardless of + // any preexpansion hook. - if (f_len == 1 || sys::file_ops::is_dir_sep (filename[1])) - return sys::env::get_home_directory () + filename.substr (1); + if (f_len == 1 || sys::file_ops::is_dir_sep (filename[1])) + return sys::env::get_home_directory () + filename.substr (1); - std::string username = isolate_tilde_prefix (filename); + std::string username = isolate_tilde_prefix (filename); - std::size_t user_len = username.length (); + std::size_t user_len = username.length (); - std::string dirname; + std::string dirname; - if (sys::file_ops::tilde_expansion_preexpansion_hook) - { - std::string expansion - = sys::file_ops::tilde_expansion_preexpansion_hook (username); + if (sys::file_ops::tilde_expansion_preexpansion_hook) + { + std::string expansion + = sys::file_ops::tilde_expansion_preexpansion_hook (username); - if (! expansion.empty ()) - return expansion + filename.substr (user_len+1); - } + if (! expansion.empty ()) + return expansion + filename.substr (user_len+1); + } - // No preexpansion hook, or the preexpansion hook failed. Look in the - // password database. + // No preexpansion hook, or the preexpansion hook failed. Look in the + // password database. - sys::password pw = sys::password::getpwnam (username); + sys::password pw = sys::password::getpwnam (username); - if (! pw) - { - // If the calling program has a special syntax for expanding tildes, - // and we couldn't find a standard expansion, then let them try. + if (! pw) + { + // If the calling program has a special syntax for expanding tildes, + // and we couldn't find a standard expansion, then let them try. - if (sys::file_ops::tilde_expansion_failure_hook) - { - std::string expansion - = sys::file_ops::tilde_expansion_failure_hook (username); + if (sys::file_ops::tilde_expansion_failure_hook) + { + std::string expansion + = sys::file_ops::tilde_expansion_failure_hook (username); - if (! expansion.empty ()) - dirname = expansion + filename.substr (user_len+1); - } + if (! expansion.empty ()) + dirname = expansion + filename.substr (user_len+1); + } - // If we don't have a failure hook, or if the failure hook did not - // expand the tilde, return a copy of what we were passed. + // If we don't have a failure hook, or if the failure hook did not + // expand the tilde, return a copy of what we were passed. - if (dirname.empty ()) - dirname = filename; - } - else - dirname = pw.dir () + filename.substr (user_len+1); + if (dirname.empty ()) + dirname = filename; + } + else + dirname = pw.dir () + filename.substr (user_len+1); - return dirname; - } + return dirname; +} OCTAVE_BEGIN_NAMESPACE(sys) OCTAVE_BEGIN_NAMESPACE(file_ops) - char dev_sep_char (void) - { +char dev_sep_char (void) +{ #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - return ':'; + return ':'; #else - return 0; + return 0; #endif - } +} - char dir_sep_char (void) - { +char dir_sep_char (void) +{ #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - return '\\'; + return '\\'; #else - return '/'; + return '/'; #endif - } +} - std::string dir_sep_str (void) - { +std::string dir_sep_str (void) +{ #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - return R"(\)"; + return R"(\)"; #else - return "/"; + return "/"; #endif - } +} - std::string dir_sep_chars (void) - { +std::string dir_sep_chars (void) +{ #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) - return R"(/\)"; + return R"(/\)"; #else - return dir_sep_str (); + return dir_sep_str (); #endif - } +} - tilde_expansion_hook tilde_expansion_preexpansion_hook = nullptr; +tilde_expansion_hook tilde_expansion_preexpansion_hook = nullptr; - tilde_expansion_hook tilde_expansion_failure_hook = nullptr; +tilde_expansion_hook tilde_expansion_failure_hook = nullptr; - string_vector tilde_additional_prefixes = default_prefixes; +string_vector tilde_additional_prefixes = default_prefixes; - string_vector tilde_additional_suffixes = default_suffixes; +string_vector tilde_additional_suffixes = default_suffixes; - bool is_dev_sep (char c) - { +bool is_dev_sep (char c) +{ #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - return c == dev_sep_char (); + return c == dev_sep_char (); #else - octave_unused_parameter (c); + octave_unused_parameter (c); - return false; + return false; #endif - } +} - bool is_dir_sep (char c) - { - std::string tmp = dir_sep_chars (); - return tmp.find (c) != std::string::npos; - } +bool is_dir_sep (char c) +{ + std::string tmp = dir_sep_chars (); + return tmp.find (c) != std::string::npos; +} - std::string tilde_expand (const std::string& name) - { - if (name.find ('~') == std::string::npos) - return std::string (name); - else - { - std::string result; +std::string tilde_expand (const std::string& name) +{ + if (name.find ('~') == std::string::npos) + return std::string (name); + else + { + std::string result; - std::size_t name_len = name.length (); + std::size_t name_len = name.length (); - // Scan through S expanding tildes as we come to them. + // Scan through S expanding tildes as we come to them. - std::size_t pos = 0; + std::size_t pos = 0; - while (1) - { - if (pos > name_len) - break; + while (1) + { + if (pos > name_len) + break; - std::size_t len; + std::size_t len; - // Make START point to the tilde which starts the expansion. + // Make START point to the tilde which starts the expansion. - std::size_t start = tilde_find_prefix (name.substr (pos), len); + std::size_t start = tilde_find_prefix (name.substr (pos), len); - result.append (name.substr (pos, start)); + result.append (name.substr (pos, start)); - // Advance STRING to the starting tilde. + // Advance STRING to the starting tilde. - pos += start; + pos += start; - // Make FINI be the index of one after the last character of the - // username. + // Make FINI be the index of one after the last character of the + // username. - std::size_t fini = tilde_find_suffix (name.substr (pos)); + std::size_t fini = tilde_find_suffix (name.substr (pos)); - // If both START and FINI are zero, we are all done. + // If both START and FINI are zero, we are all done. - if (! (start || fini)) - break; + if (! (start || fini)) + break; - // Expand the entire tilde word, and copy it into RESULT. + // Expand the entire tilde word, and copy it into RESULT. - std::string tilde_word = name.substr (pos, fini); + std::string tilde_word = name.substr (pos, fini); - pos += fini; + pos += fini; - std::string expansion = tilde_expand_word (tilde_word); + std::string expansion = tilde_expand_word (tilde_word); - result.append (expansion); - } + result.append (expansion); + } - return result; - } - } + return result; + } +} - string_vector tilde_expand (const string_vector& names) - { - int n = names.numel (); +string_vector tilde_expand (const string_vector& names) +{ + int n = names.numel (); - string_vector retval (n); + string_vector retval (n); - for (int i = 0; i < n; i++) - retval[i] = tilde_expand (names[i]); + for (int i = 0; i < n; i++) + retval[i] = tilde_expand (names[i]); - return retval; - } + return retval; +} - std::string concat (const std::string& dir, const std::string& file) - { - return dir.empty () - ? file - : (is_dir_sep (dir.back ()) - ? dir + file - : dir + dir_sep_char () + file); - } +std::string concat (const std::string& dir, const std::string& file) +{ + return dir.empty () + ? file + : (is_dir_sep (dir.back ()) + ? dir + file + : dir + dir_sep_char () + file); +} - std::string dirname (const std::string& path) - { - std::size_t ipos = path.find_last_of (dir_sep_chars ()); +std::string dirname (const std::string& path) +{ + std::size_t ipos = path.find_last_of (dir_sep_chars ()); - return (ipos != std::string::npos) ? path.substr (0, ipos) : ""; - } + return (ipos != std::string::npos) ? path.substr (0, ipos) : ""; +} - std::string tail (const std::string& path) - { - std::size_t ipos = path.find_last_of (dir_sep_chars ()); +std::string tail (const std::string& path) +{ + std::size_t ipos = path.find_last_of (dir_sep_chars ()); - if (ipos != std::string::npos) - ipos++; - else - ipos = 0; + if (ipos != std::string::npos) + ipos++; + else + ipos = 0; - return path.substr (ipos); - } + return path.substr (ipos); +} - std::string native_separator_path (const std::string& path) - { - std::string retval; +std::string native_separator_path (const std::string& path) +{ + std::string retval; - if (dir_sep_char () == '/') - retval = path; - else - { - std::size_t n = path.length (); - for (std::size_t i = 0; i < n; i++) - { - if (path[i] == '/') - retval += dir_sep_char(); - else - retval += path[i]; - } - } + if (dir_sep_char () == '/') + retval = path; + else + { + std::size_t n = path.length (); + for (std::size_t i = 0; i < n; i++) + { + if (path[i] == '/') + retval += dir_sep_char(); + else + retval += path[i]; + } + } - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(file_ops) - int mkdir (const std::string& nm, mode_t md) +int mkdir (const std::string& nm, mode_t md) +{ + std::string msg; + return mkdir (nm, md, msg); +} + +int mkdir (const std::string& name, mode_t mode, std::string& msg) +{ + msg = ""; + + int status = octave_mkdir_wrapper (name.c_str (), mode); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} + +int recursive_mkdir (const std::string& name, mode_t mode) +{ + std::string msg; + return recursive_mkdir (name, mode, msg); +} + +int recursive_mkdir (const std::string& name, mode_t mode, std::string& msg) +{ + int status; + + // account for root in absolute directories +#if defined (OCTAVE_USE_WINDOWS_API) + // root of current drive + std::size_t skip_root = 0; + if (name.size () > 1) { - std::string msg; - return mkdir (nm, md, msg); + if (name[1] == ':') + // drive root (e.g., C:\) + skip_root = 2; + else if (file_ops::is_dir_sep (name[0]) + && file_ops::is_dir_sep (name[1])) + { + // UNC path root (e.g., \\SERVER\share\) + skip_root = name.find_first_of (file_ops::dir_sep_chars (), 2); + skip_root = name.find_first_of (file_ops::dir_sep_chars (), + skip_root + 1); + } } - int mkdir (const std::string& name, mode_t mode, std::string& msg) - { - msg = ""; + std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), + skip_root + 1); +#else + std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), 1); +#endif - int status = octave_mkdir_wrapper (name.c_str (), mode); - - if (status < 0) - msg = std::strerror (errno); - - return status; + // iterate over all componenents of NAME and make directories + while (delim != std::string::npos) + { + std::string base = name.substr (0, delim); + sys::file_stat fs (base); + if (! fs.is_dir ()) + { + status = mkdir (base, mode, msg); + if (status < 0) + return status; + } + delim = name.find_first_of (file_ops::dir_sep_chars (), delim + 1); } - int recursive_mkdir (const std::string& name, mode_t mode) + // finally, create requested directory + return mkdir (name, mode, msg); +} + +int mkfifo (const std::string& nm, mode_t md) +{ + std::string msg; + return mkfifo (nm, md, msg); +} + +int mkfifo (const std::string& name, mode_t mode, std::string& msg) +{ + msg = ""; + + int status = octave_mkfifo_wrapper (name.c_str (), mode); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} + +int link (const std::string& old_name, const std::string& new_name) +{ + std::string msg; + return link (old_name, new_name, msg); +} + +int link (const std::string& old_name, const std::string& new_name, + std::string& msg) +{ + msg = ""; + + int status = -1; + + status = octave_link_wrapper (old_name.c_str (), new_name.c_str ()); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} + +int symlink (const std::string& old_name, const std::string& new_name) +{ + std::string msg; + return symlink (old_name, new_name, msg); +} + +int symlink (const std::string& old_name, const std::string& new_name, + std::string& msg) +{ + msg = ""; + + int status = -1; + + status = octave_symlink_wrapper (old_name.c_str (), new_name.c_str ()); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} + +int readlink (const std::string& path, std::string& result) +{ + std::string msg; + return readlink (path, result, msg); +} + +int readlink (const std::string& path, std::string& result, std::string& msg) +{ + int status = -1; + + msg = ""; + + char *buf = octave_areadlink_wrapper (path.c_str ()); + + if (! buf) + msg = std::strerror (errno); + else { - std::string msg; - return recursive_mkdir (name, mode, msg); + result = buf; + ::free (buf); + status = 0; } - int recursive_mkdir (const std::string& name, mode_t mode, std::string& msg) - { - int status; + return status; +} + +int rename (const std::string& from, const std::string& to) +{ + std::string msg; + return rename (from, to, msg); +} + +int rename (const std::string& from, const std::string& to, + std::string& msg) +{ + int status = -1; + + msg = ""; + +#if defined (OCTAVE_USE_WINDOWS_API) + std::wstring wfrom = u8_to_wstring (from); + std::wstring wto = u8_to_wstring (to); + status = _wrename (wfrom.c_str (), wto.c_str ()); +#else + status = std::rename (from.c_str (), to.c_str ()); +#endif + + if (status < 0) + msg = std::strerror (errno); + + return status; +} - // account for root in absolute directories -#if defined (OCTAVE_USE_WINDOWS_API) - // root of current drive - std::size_t skip_root = 0; - if (name.size () > 1) +int rmdir (const std::string& name) +{ + std::string msg; + return rmdir (name, msg); +} + +int rmdir (const std::string& name, std::string& msg) +{ + msg = ""; + + int status = -1; + + status = octave_rmdir_wrapper (name.c_str ()); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} + +// And a version that works recursively. + +int recursive_rmdir (const std::string& name) +{ + std::string msg; + return recursive_rmdir (name, msg); +} + +int recursive_rmdir (const std::string& name, std::string& msg) +{ + msg = ""; + + int status = 0; + + string_vector dirlist; + + if (get_dirlist (name, dirlist, msg)) + { + for (octave_idx_type i = 0; i < dirlist.numel (); i++) { - if (name[1] == ':') - // drive root (e.g., C:\) - skip_root = 2; - else if (file_ops::is_dir_sep (name[0]) - && file_ops::is_dir_sep (name[1])) + octave_quit (); + + std::string nm = dirlist[i]; + + // Skip current directory and parent. + if (nm == "." || nm == "..") + continue; + + std::string fullnm = name + file_ops::dir_sep_str () + nm; + + // Get info about the file. Don't follow links. + file_stat fs (fullnm, false); + + if (fs) { - // UNC path root (e.g., \\SERVER\share\) - skip_root = name.find_first_of (file_ops::dir_sep_chars (), 2); - skip_root = name.find_first_of (file_ops::dir_sep_chars (), - skip_root + 1); + if (fs.is_dir ()) + { + status = recursive_rmdir (fullnm, msg); + + if (status < 0) + break; + } + else + { + status = unlink (fullnm, msg); + + if (status < 0) + break; + } + } + else + { + msg = fs.error (); + break; } } - std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), - skip_root + 1); -#else - std::size_t delim = name.find_first_of (file_ops::dir_sep_chars (), 1); -#endif + if (status >= 0) + status = rmdir (name, msg); + } + else + status = -1; + + return status; +} - // iterate over all componenents of NAME and make directories - while (delim != std::string::npos) - { - std::string base = name.substr (0, delim); - sys::file_stat fs (base); - if (! fs.is_dir ()) - { - status = mkdir (base, mode, msg); - if (status < 0) - return status; - } - delim = name.find_first_of (file_ops::dir_sep_chars (), delim + 1); - } +int umask (mode_t mode) +{ + return octave_umask_wrapper (mode); +} - // finally, create requested directory - return mkdir (name, mode, msg); - } - - int mkfifo (const std::string& nm, mode_t md) - { - std::string msg; - return mkfifo (nm, md, msg); - } +int unlink (const std::string& name) +{ + std::string msg; + return unlink (name, msg); +} - int mkfifo (const std::string& name, mode_t mode, std::string& msg) - { - msg = ""; - - int status = octave_mkfifo_wrapper (name.c_str (), mode); +int unlink (const std::string& name, std::string& msg) +{ + msg = ""; - if (status < 0) - msg = std::strerror (errno); + int status = -1; - return status; - } + status = octave_unlink_wrapper (name.c_str ()); + + if (status < 0) + msg = std::strerror (errno); - int link (const std::string& old_name, const std::string& new_name) - { - std::string msg; - return link (old_name, new_name, msg); - } + return status; +} - int link (const std::string& old_name, const std::string& new_name, - std::string& msg) - { - msg = ""; +std::string tempnam (const std::string& dir, const std::string& pfx) +{ + std::string msg; + return tempnam (dir, pfx, msg); +} - int status = -1; +std::string tempnam (const std::string& dir, const std::string& pfx, + std::string& msg) +{ + msg = ""; - status = octave_link_wrapper (old_name.c_str (), new_name.c_str ()); - - if (status < 0) - msg = std::strerror (errno); + std::string retval; - return status; - } - - int symlink (const std::string& old_name, const std::string& new_name) - { - std::string msg; - return symlink (old_name, new_name, msg); - } - - int symlink (const std::string& old_name, const std::string& new_name, - std::string& msg) - { - msg = ""; + // get dir path to use for template + std::string templatename; + if (dir.empty ()) + templatename = env::get_temp_directory (); + else if (! file_stat (dir, false).is_dir ()) + templatename = env::get_temp_directory (); + else + templatename = dir; - int status = -1; - - status = octave_symlink_wrapper (old_name.c_str (), new_name.c_str ()); - - if (status < 0) - msg = std::strerror (errno); + // add dir sep char if it is not there + if (*templatename.rbegin () != file_ops::dir_sep_char ()) + templatename += file_ops::dir_sep_char (); - return status; - } + if (pfx.empty ()) + templatename += "file"; + else + templatename += pfx; - int readlink (const std::string& path, std::string& result) - { - std::string msg; - return readlink (path, result, msg); - } + // add the required XXXXXX for the template + templatename += "XXXXXX"; + + // create and copy template to char array for call to gen_tempname + char tname [templatename.length () + 1]; - int readlink (const std::string& path, std::string& result, std::string& msg) - { - int status = -1; + strcpy (tname, templatename.c_str ()); - msg = ""; + if (octave_gen_tempname_wrapper (tname) == -1) + msg = std::strerror (errno); + else + retval = tname; - char *buf = octave_areadlink_wrapper (path.c_str ()); + return retval; +} - if (! buf) - msg = std::strerror (errno); - else - { - result = buf; - ::free (buf); - status = 0; - } - - return status; - } +std::string canonicalize_file_name (const std::string& name) +{ + std::string msg; + return canonicalize_file_name (name, msg); +} - int rename (const std::string& from, const std::string& to) - { - std::string msg; - return rename (from, to, msg); - } +std::string canonicalize_file_name (const std::string& name, std::string& msg) +{ + msg = ""; - int rename (const std::string& from, const std::string& to, - std::string& msg) - { - int status = -1; + std::string retval; - msg = ""; + // FIXME: Consider replacing this with std::filesystem::canonical on all + // platforms once we allow using C++17. #if defined (OCTAVE_USE_WINDOWS_API) - std::wstring wfrom = u8_to_wstring (from); - std::wstring wto = u8_to_wstring (to); - status = _wrename (wfrom.c_str (), wto.c_str ()); -#else - status = std::rename (from.c_str (), to.c_str ()); -#endif - - if (status < 0) - msg = std::strerror (errno); - - return status; - } - - int rmdir (const std::string& name) - { - std::string msg; - return rmdir (name, msg); - } - - int rmdir (const std::string& name, std::string& msg) - { - msg = ""; - - int status = -1; - - status = octave_rmdir_wrapper (name.c_str ()); - - if (status < 0) - msg = std::strerror (errno); - - return status; - } - - // And a version that works recursively. - - int recursive_rmdir (const std::string& name) - { - std::string msg; - return recursive_rmdir (name, msg); - } - - int recursive_rmdir (const std::string& name, std::string& msg) - { - msg = ""; - - int status = 0; - - string_vector dirlist; - - if (get_dirlist (name, dirlist, msg)) - { - for (octave_idx_type i = 0; i < dirlist.numel (); i++) - { - octave_quit (); - - std::string nm = dirlist[i]; - - // Skip current directory and parent. - if (nm == "." || nm == "..") - continue; - - std::string fullnm = name + file_ops::dir_sep_str () + nm; - - // Get info about the file. Don't follow links. - file_stat fs (fullnm, false); - - if (fs) - { - if (fs.is_dir ()) - { - status = recursive_rmdir (fullnm, msg); - - if (status < 0) - break; - } - else - { - status = unlink (fullnm, msg); + // open file handle + std::wstring wname = u8_to_wstring (name); + HANDLE h_file = CreateFileW (wname.c_str (), GENERIC_READ, + FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (status < 0) - break; - } - } - else - { - msg = fs.error (); - break; - } - } - - if (status >= 0) - status = rmdir (name, msg); - } - else - status = -1; - - return status; - } - - int umask (mode_t mode) - { - return octave_umask_wrapper (mode); - } - - int unlink (const std::string& name) - { - std::string msg; - return unlink (name, msg); - } - - int unlink (const std::string& name, std::string& msg) - { - msg = ""; - - int status = -1; - - status = octave_unlink_wrapper (name.c_str ()); - - if (status < 0) - msg = std::strerror (errno); - - return status; - } + // Might have been a symbolic link that points to a network share. + // It looks like opening a network share itself (not a file or folder + // *on* a share) might return an invalid handle. As a workaround, try to + // open a handle to the symbolic link itself (and do not resolve it). + if (h_file == INVALID_HANDLE_VALUE) + h_file = CreateFileW (wname.c_str (), GENERIC_READ, + FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS + | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - std::string tempnam (const std::string& dir, const std::string& pfx) - { - std::string msg; - return tempnam (dir, pfx, msg); - } - - std::string tempnam (const std::string& dir, const std::string& pfx, - std::string& msg) + if (h_file == INVALID_HANDLE_VALUE) { - msg = ""; - - std::string retval; - - // get dir path to use for template - std::string templatename; - if (dir.empty ()) - templatename = env::get_temp_directory (); - else if (! file_stat (dir, false).is_dir ()) - templatename = env::get_temp_directory (); - else - templatename = dir; - - // add dir sep char if it is not there - if (*templatename.rbegin () != file_ops::dir_sep_char ()) - templatename += file_ops::dir_sep_char (); - - if (pfx.empty ()) - templatename += "file"; - else - templatename += pfx; - - // add the required XXXXXX for the template - templatename += "XXXXXX"; - - // create and copy template to char array for call to gen_tempname - char tname [templatename.length () + 1]; - - strcpy (tname, templatename.c_str ()); - - if (octave_gen_tempname_wrapper (tname) == -1) - msg = std::strerror (errno); - else - retval = tname; - + msg = "Unable to open file \"" + name + "\""; return retval; } - std::string canonicalize_file_name (const std::string& name) - { - std::string msg; - return canonicalize_file_name (name, msg); - } - - std::string canonicalize_file_name (const std::string& name, std::string& msg) - { - msg = ""; - - std::string retval; - - // FIXME: Consider replacing this with std::filesystem::canonical on all - // platforms once we allow using C++17. - -#if defined (OCTAVE_USE_WINDOWS_API) - // open file handle - std::wstring wname = u8_to_wstring (name); - HANDLE h_file = CreateFileW (wname.c_str (), GENERIC_READ, - FILE_SHARE_READ, nullptr, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS, nullptr); + unwind_action close_file_handle (CloseHandle, h_file); - // Might have been a symbolic link that points to a network share. - // It looks like opening a network share itself (not a file or folder - // *on* a share) might return an invalid handle. As a workaround, try to - // open a handle to the symbolic link itself (and do not resolve it). - if (h_file == INVALID_HANDLE_VALUE) - h_file = CreateFileW (wname.c_str (), GENERIC_READ, - FILE_SHARE_READ, nullptr, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS - | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - - if (h_file == INVALID_HANDLE_VALUE) - { - msg = "Unable to open file \"" + name + "\""; - return retval; - } - - unwind_action close_file_handle (CloseHandle, h_file); - - const std::size_t buf_size = 32767; - wchar_t buffer[buf_size] = L""; - - // query canonical name - DWORD len = GetFinalPathNameByHandleW (h_file, buffer, buf_size, - FILE_NAME_NORMALIZED); - if (len >= buf_size) - { - msg = "Error querying normalized name for \"" + name + "\""; - return retval; - } - - retval = u8_from_wstring (std::wstring (buffer, len)); - - // remove prefix - // "Normal" paths are prefixed by "\\?\". - // UNC paths are prefixed by "\\?\UNC\". - if (retval.compare (0, 8, R"(\\?\UNC\)") == 0) - { - retval = retval.erase (2, 6); + const std::size_t buf_size = 32767; + wchar_t buffer[buf_size] = L""; - // If the initial path looked like a mapped network drive, replace - // portion of path that corresponds to mapped root with drive root. - if (name.size () < 3 || name[1] != ':') - return retval; - - // UNC path corresponding to original drive letter (mappped drive) - std::wstring orig_map = wname.substr (0, 3); - orig_map[2] = L'\\'; - HANDLE h_map = CreateFileW (orig_map.c_str (), GENERIC_READ, - FILE_SHARE_READ, nullptr, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS - | FILE_FLAG_OPEN_REPARSE_POINT, - nullptr); - - if (h_map == INVALID_HANDLE_VALUE) - // cannot determine common root - return retval; - - unwind_action close_map_handle (CloseHandle, h_map); - len = GetFinalPathNameByHandleW (h_map, buffer, buf_size, - FILE_NAME_NORMALIZED); - - std::string orig_root - = u8_from_wstring (std::wstring (buffer, len)); - - if (orig_root.compare (0, 8, R"(\\?\UNC\)")) - // root was not a mapped share - return retval; - - orig_root = orig_root.erase (2, 6); - // trim trailing file separators from UNC path corresponding to root - std::string file_seps = file_ops::dir_sep_chars (); - while (file_seps.find (orig_root.back ()) != std::string::npos) - orig_root.pop_back (); - - if (retval.compare (0, orig_root.size (), orig_root)) - // start of UNC path doesn't match mapped drive root - return retval; - - // file is on mapped share - size_t sep_pos = orig_root.size (); - if (sep_pos != retval.size ()) - retval = retval.substr (sep_pos-2); - else - retval.resize (2); // no file component - retval[0] = std::toupper (name[0]); - retval[1] = ':'; - } - else if (retval.compare (0, 4, R"(\\?\)") == 0) - retval = retval.erase (0, 4); -#else - char *tmp = octave_canonicalize_file_name_wrapper (name.c_str ()); - - if (tmp) - { - retval = tmp; - free (tmp); - } - - if (retval.empty ()) - msg = std::strerror (errno); -#endif - + // query canonical name + DWORD len = GetFinalPathNameByHandleW (h_file, buffer, buf_size, + FILE_NAME_NORMALIZED); + if (len >= buf_size) + { + msg = "Error querying normalized name for \"" + name + "\""; return retval; } + retval = u8_from_wstring (std::wstring (buffer, len)); + + // remove prefix + // "Normal" paths are prefixed by "\\?\". + // UNC paths are prefixed by "\\?\UNC\". + if (retval.compare (0, 8, R"(\\?\UNC\)") == 0) + { + retval = retval.erase (2, 6); + + // If the initial path looked like a mapped network drive, replace + // portion of path that corresponds to mapped root with drive root. + if (name.size () < 3 || name[1] != ':') + return retval; + + // UNC path corresponding to original drive letter (mappped drive) + std::wstring orig_map = wname.substr (0, 3); + orig_map[2] = L'\\'; + HANDLE h_map = CreateFileW (orig_map.c_str (), GENERIC_READ, + FILE_SHARE_READ, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS + | FILE_FLAG_OPEN_REPARSE_POINT, + nullptr); + + if (h_map == INVALID_HANDLE_VALUE) + // cannot determine common root + return retval; + + unwind_action close_map_handle (CloseHandle, h_map); + len = GetFinalPathNameByHandleW (h_map, buffer, buf_size, + FILE_NAME_NORMALIZED); + + std::string orig_root + = u8_from_wstring (std::wstring (buffer, len)); + + if (orig_root.compare (0, 8, R"(\\?\UNC\)")) + // root was not a mapped share + return retval; + + orig_root = orig_root.erase (2, 6); + // trim trailing file separators from UNC path corresponding to root + std::string file_seps = file_ops::dir_sep_chars (); + while (file_seps.find (orig_root.back ()) != std::string::npos) + orig_root.pop_back (); + + if (retval.compare (0, orig_root.size (), orig_root)) + // start of UNC path doesn't match mapped drive root + return retval; + + // file is on mapped share + size_t sep_pos = orig_root.size (); + if (sep_pos != retval.size ()) + retval = retval.substr (sep_pos-2); + else + retval.resize (2); // no file component + retval[0] = std::toupper (name[0]); + retval[1] = ':'; + } + else if (retval.compare (0, 4, R"(\\?\)") == 0) + retval = retval.erase (0, 4); +#else + char *tmp = octave_canonicalize_file_name_wrapper (name.c_str ()); + + if (tmp) + { + retval = tmp; + free (tmp); + } + + if (retval.empty ()) + msg = std::strerror (errno); +#endif + + return retval; +} + OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/file-ops.h --- a/liboctave/system/file-ops.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/file-ops.h Thu Dec 01 20:05:44 2022 -0800 @@ -40,156 +40,156 @@ OCTAVE_BEGIN_NAMESPACE(file_ops) - typedef std::string (*tilde_expansion_hook) (const std::string&); +typedef std::string (*tilde_expansion_hook) (const std::string&); - // If non-null, this contains the address of a function that the - // application wants called before trying the standard tilde - // expansions. The function is called with the text sans tilde, and - // returns a malloc()'ed string which is the expansion, or a NULL - // pointer if the expansion fails. +// If non-null, this contains the address of a function that the +// application wants called before trying the standard tilde +// expansions. The function is called with the text sans tilde, and +// returns a malloc()'ed string which is the expansion, or a NULL +// pointer if the expansion fails. - extern OCTAVE_API tilde_expansion_hook tilde_expansion_preexpansion_hook; +extern OCTAVE_API tilde_expansion_hook tilde_expansion_preexpansion_hook; - // If non-null, this contains the address of a function to call if the - // standard meaning for expanding a tilde fails. The function is - // called with the text (sans tilde, as in "foo"), and returns a - // malloc()'ed string which is the expansion, or a NULL pointer if - // there is no expansion. +// If non-null, this contains the address of a function to call if the +// standard meaning for expanding a tilde fails. The function is +// called with the text (sans tilde, as in "foo"), and returns a +// malloc()'ed string which is the expansion, or a NULL pointer if +// there is no expansion. - extern OCTAVE_API tilde_expansion_hook tilde_expansion_failure_hook; +extern OCTAVE_API tilde_expansion_hook tilde_expansion_failure_hook; - // When non-null, this is a NULL terminated array of strings which are - // duplicates for a tilde prefix. Bash uses this to expand '=~' and - // ':~'. +// When non-null, this is a NULL terminated array of strings which are +// duplicates for a tilde prefix. Bash uses this to expand '=~' and +// ':~'. - extern OCTAVE_API string_vector tilde_additional_prefixes; +extern OCTAVE_API string_vector tilde_additional_prefixes; - // When non-null, this is a NULL terminated array of strings which - // match the end of a username, instead of just "/". Bash sets this - // to ':' and '=~'. +// When non-null, this is a NULL terminated array of strings which +// match the end of a username, instead of just "/". Bash sets this +// to ':' and '=~'. - extern OCTAVE_API string_vector tilde_additional_suffixes; +extern OCTAVE_API string_vector tilde_additional_suffixes; - // Find the start of a tilde expansion in S, and return the index - // of the tilde which starts the expansion. Place the length of the - // text which identified this tilde starter in LEN, excluding the - // tilde itself. +// Find the start of a tilde expansion in S, and return the index +// of the tilde which starts the expansion. Place the length of the +// text which identified this tilde starter in LEN, excluding the +// tilde itself. - extern OCTAVE_API char dev_sep_char (void); +extern OCTAVE_API char dev_sep_char (void); - extern OCTAVE_API bool is_dev_sep (char c); +extern OCTAVE_API bool is_dev_sep (char c); - extern OCTAVE_API char dir_sep_char (void); +extern OCTAVE_API char dir_sep_char (void); - extern OCTAVE_API std::string dir_sep_str (void); +extern OCTAVE_API std::string dir_sep_str (void); - extern OCTAVE_API std::string dir_sep_chars (void); +extern OCTAVE_API std::string dir_sep_chars (void); - extern OCTAVE_API bool is_dir_sep (char c); +extern OCTAVE_API bool is_dir_sep (char c); - // If NAME has a leading ~ or ~user, Unix-style, expand it to the - // user's home directory. If no ~, or no , just return NAME. +// If NAME has a leading ~ or ~user, Unix-style, expand it to the +// user's home directory. If no ~, or no , just return NAME. - extern OCTAVE_API std::string tilde_expand (const std::string&); +extern OCTAVE_API std::string tilde_expand (const std::string&); - // A vector version of the above. +// A vector version of the above. - extern OCTAVE_API string_vector tilde_expand (const string_vector&); +extern OCTAVE_API string_vector tilde_expand (const string_vector&); - extern OCTAVE_API std::string concat (const std::string&, const std::string&); +extern OCTAVE_API std::string concat (const std::string&, const std::string&); - // Return the directory part of a filename or an empty string if - // there is no directory component. Does not check to see - // whether the file exists or is a directory. +// Return the directory part of a filename or an empty string if +// there is no directory component. Does not check to see +// whether the file exists or is a directory. - extern OCTAVE_API std::string dirname (const std::string& path); +extern OCTAVE_API std::string dirname (const std::string& path); - // Return the tail member of a filename. +// Return the tail member of a filename. - extern OCTAVE_API std::string tail (const std::string& path); +extern OCTAVE_API std::string tail (const std::string& path); - // Convert path from UNIX type separators to whatever is the - // system separators. +// Convert path from UNIX type separators to whatever is the +// system separators. - extern OCTAVE_API std::string - native_separator_path (const std::string& path); +extern OCTAVE_API std::string +native_separator_path (const std::string& path); OCTAVE_END_NAMESPACE(file_ops) - extern OCTAVE_API int - mkdir (const std::string&, mode_t); +extern OCTAVE_API int +mkdir (const std::string&, mode_t); - extern OCTAVE_API int - mkdir (const std::string&, mode_t, std::string&); +extern OCTAVE_API int +mkdir (const std::string&, mode_t, std::string&); - extern OCTAVE_API int - recursive_mkdir (const std::string& name, mode_t mode); +extern OCTAVE_API int +recursive_mkdir (const std::string& name, mode_t mode); - extern OCTAVE_API int - recursive_mkdir (const std::string& name, mode_t mode, std::string& msg); +extern OCTAVE_API int +recursive_mkdir (const std::string& name, mode_t mode, std::string& msg); - extern OCTAVE_API int - mkfifo (const std::string&, mode_t); +extern OCTAVE_API int +mkfifo (const std::string&, mode_t); - extern OCTAVE_API int - mkfifo (const std::string&, mode_t, std::string&); +extern OCTAVE_API int +mkfifo (const std::string&, mode_t, std::string&); - extern OCTAVE_API int - link (const std::string&, const std::string&); +extern OCTAVE_API int +link (const std::string&, const std::string&); - extern OCTAVE_API int - link (const std::string&, const std::string&, std::string&); +extern OCTAVE_API int +link (const std::string&, const std::string&, std::string&); - extern OCTAVE_API int - symlink (const std::string&, const std::string&); +extern OCTAVE_API int +symlink (const std::string&, const std::string&); - extern OCTAVE_API int - symlink (const std::string&, const std::string&, std::string&); +extern OCTAVE_API int +symlink (const std::string&, const std::string&, std::string&); - extern OCTAVE_API int - readlink (const std::string&, std::string&); +extern OCTAVE_API int +readlink (const std::string&, std::string&); - extern OCTAVE_API int - readlink (const std::string&, std::string&, std::string&); +extern OCTAVE_API int +readlink (const std::string&, std::string&, std::string&); - extern OCTAVE_API int - rename (const std::string&, const std::string&); +extern OCTAVE_API int +rename (const std::string&, const std::string&); - extern OCTAVE_API int - rename (const std::string&, const std::string&, std::string&); +extern OCTAVE_API int +rename (const std::string&, const std::string&, std::string&); - extern OCTAVE_API int - rmdir (const std::string&); +extern OCTAVE_API int +rmdir (const std::string&); - extern OCTAVE_API int - rmdir (const std::string&, std::string&); +extern OCTAVE_API int +rmdir (const std::string&, std::string&); - extern OCTAVE_API int - recursive_rmdir (const std::string&); +extern OCTAVE_API int +recursive_rmdir (const std::string&); - extern OCTAVE_API int - recursive_rmdir (const std::string&, std::string&); +extern OCTAVE_API int +recursive_rmdir (const std::string&, std::string&); - extern OCTAVE_API int - umask (mode_t); +extern OCTAVE_API int +umask (mode_t); - extern OCTAVE_API int - unlink (const std::string&); +extern OCTAVE_API int +unlink (const std::string&); - extern OCTAVE_API int - unlink (const std::string&, std::string&); +extern OCTAVE_API int +unlink (const std::string&, std::string&); - extern OCTAVE_API std::string - tempnam (const std::string&, const std::string&); +extern OCTAVE_API std::string +tempnam (const std::string&, const std::string&); - extern OCTAVE_API std::string - tempnam (const std::string&, const std::string&, std::string&); +extern OCTAVE_API std::string +tempnam (const std::string&, const std::string&, std::string&); - extern OCTAVE_API std::string - canonicalize_file_name (const std::string&); +extern OCTAVE_API std::string +canonicalize_file_name (const std::string&); - extern OCTAVE_API std::string - canonicalize_file_name (const std::string&, std::string&); +extern OCTAVE_API std::string +canonicalize_file_name (const std::string&, std::string&); OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/file-stat.cc --- a/liboctave/system/file-stat.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/file-stat.cc Thu Dec 01 20:05:44 2022 -0800 @@ -45,236 +45,236 @@ OCTAVE_BEGIN_NAMESPACE(sys) - // FIXME: the is_* and mode_as_string functions are only valid - // for initialized objects. If called for an object that is not - // initialized, they should throw an exception. +// FIXME: the is_* and mode_as_string functions are only valid +// for initialized objects. If called for an object that is not +// initialized, they should throw an exception. + +bool +base_file_stat::is_blk (void) const +{ + return exists () && is_blk (m_mode); +} + +bool +base_file_stat::is_chr (void) const +{ + return exists () && is_chr (m_mode); +} - bool - base_file_stat::is_blk (void) const - { - return exists () && is_blk (m_mode); - } +bool +base_file_stat::is_dir (void) const +{ + return exists () && is_dir (m_mode); +} - bool - base_file_stat::is_chr (void) const - { - return exists () && is_chr (m_mode); - } +bool +base_file_stat::is_fifo (void) const +{ + return exists () && is_fifo (m_mode); +} + +bool +base_file_stat::is_lnk (void) const +{ + return exists () && is_lnk (m_mode); +} - bool - base_file_stat::is_dir (void) const - { - return exists () && is_dir (m_mode); - } +bool +base_file_stat::is_reg (void) const +{ + return exists () && is_reg (m_mode); +} + +bool +base_file_stat::is_sock (void) const +{ + return exists () && is_sock (m_mode); +} + +bool +base_file_stat::is_blk (mode_t mode) +{ + return octave_is_blk_wrapper (mode); +} - bool - base_file_stat::is_fifo (void) const - { - return exists () && is_fifo (m_mode); - } +bool +base_file_stat::is_chr (mode_t mode) +{ + return octave_is_chr_wrapper (mode); +} - bool - base_file_stat::is_lnk (void) const - { - return exists () && is_lnk (m_mode); - } +bool +base_file_stat::is_dir (mode_t mode) +{ + return octave_is_dir_wrapper (mode); +} + +bool +base_file_stat::is_fifo (mode_t mode) +{ + return octave_is_fifo_wrapper (mode); +} - bool - base_file_stat::is_reg (void) const - { - return exists () && is_reg (m_mode); - } +bool +base_file_stat::is_lnk (mode_t mode) +{ + return octave_is_lnk_wrapper (mode); +} + +bool +base_file_stat::is_reg (mode_t mode) +{ + return octave_is_reg_wrapper (mode); +} + +bool +base_file_stat::is_sock (mode_t mode) +{ + return octave_is_sock_wrapper (mode); +} - bool - base_file_stat::is_sock (void) const - { - return exists () && is_sock (m_mode); - } +bool +base_file_stat::have_struct_stat_st_rdev (void) +{ + return ::octave_have_struct_stat_st_rdev (); +} - bool - base_file_stat::is_blk (mode_t mode) - { - return octave_is_blk_wrapper (mode); - } +bool +base_file_stat::have_struct_stat_st_blksize (void) +{ + return octave_have_struct_stat_st_blksize (); +} + +bool +base_file_stat::have_struct_stat_st_blocks (void) +{ + return octave_have_struct_stat_st_blocks (); +} - bool - base_file_stat::is_chr (mode_t mode) - { - return octave_is_chr_wrapper (mode); - } +std::string +base_file_stat::mode_as_string (void) const +{ + char buf[12]; + + octave_strmode_wrapper (m_mode, buf); + + return std::string (buf); +} + +// Has FILE been modified since TIME? Returns 1 for yes, 0 for no, +// and -1 for any error. + +int +base_file_stat::is_newer (const std::string& file, + const sys::time& time) +{ + file_stat fs (file); - bool - base_file_stat::is_dir (mode_t mode) - { - return octave_is_dir_wrapper (mode); - } + return fs ? fs.is_newer (time) : -1; +} + +// Private stuff: - bool - base_file_stat::is_fifo (mode_t mode) - { - return octave_is_fifo_wrapper (mode); - } +file_stat::file_stat (const std::string& n, bool fl) + : base_file_stat (), m_file_name (n), m_follow_links (fl) +{ + if (! m_file_name.empty ()) + update_internal (); +} - bool - base_file_stat::is_lnk (mode_t mode) +file_stat::~file_stat () { } + +void +file_stat::update_internal (bool force) +{ + if (! m_initialized || force) { - return octave_is_lnk_wrapper (mode); - } - - bool - base_file_stat::is_reg (mode_t mode) - { - return octave_is_reg_wrapper (mode); - } - - bool - base_file_stat::is_sock (mode_t mode) - { - return octave_is_sock_wrapper (mode); - } - - bool - base_file_stat::have_struct_stat_st_rdev (void) - { - return ::octave_have_struct_stat_st_rdev (); - } - - bool - base_file_stat::have_struct_stat_st_blksize (void) - { - return octave_have_struct_stat_st_blksize (); - } - - bool - base_file_stat::have_struct_stat_st_blocks (void) - { - return octave_have_struct_stat_st_blocks (); - } - - std::string - base_file_stat::mode_as_string (void) const - { - char buf[12]; + m_initialized = false; + m_fail = false; - octave_strmode_wrapper (m_mode, buf); - - return std::string (buf); - } - - // Has FILE been modified since TIME? Returns 1 for yes, 0 for no, - // and -1 for any error. - - int - base_file_stat::is_newer (const std::string& file, - const sys::time& time) - { - file_stat fs (file); - - return fs ? fs.is_newer (time) : -1; - } - - // Private stuff: - - file_stat::file_stat (const std::string& n, bool fl) - : base_file_stat (), m_file_name (n), m_follow_links (fl) - { - if (! m_file_name.empty ()) - update_internal (); - } - - file_stat::~file_stat () { } - - void - file_stat::update_internal (bool force) - { - if (! m_initialized || force) - { - m_initialized = false; - m_fail = false; - - std::string full_file_name = sys::file_ops::tilde_expand (m_file_name); + std::string full_file_name = sys::file_ops::tilde_expand (m_file_name); #if defined (OCTAVE_USE_WINDOWS_API) - full_file_name = sys::env::make_absolute (full_file_name); + full_file_name = sys::env::make_absolute (full_file_name); - // Remove trailing slashes - while (full_file_name.length () > 1 - && sys::file_ops::is_dir_sep (full_file_name.back ())) - full_file_name.pop_back (); + // Remove trailing slashes + while (full_file_name.length () > 1 + && sys::file_ops::is_dir_sep (full_file_name.back ())) + full_file_name.pop_back (); - // If path is a root (like "C:" or "\\SERVER\share"), add a - // trailing backslash. - // FIXME: This pattern does not match all possible UNC roots: - // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc - static const regexp pat (R"(^\\\\[\w.-]+\\[\w\$-]+$)"); - if ((full_file_name.length () == 2 && full_file_name[1] == ':') - || (full_file_name.length () > 4 && full_file_name[0] == '\\' - && full_file_name[1] == '\\' && pat.is_match (full_file_name))) - full_file_name.push_back ('\\'); + // If path is a root (like "C:" or "\\SERVER\share"), add a + // trailing backslash. + // FIXME: This pattern does not match all possible UNC roots: + // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/62e862f4-2a51-452e-8eeb-dc4ff5ee33cc + static const regexp pat (R"(^\\\\[\w.-]+\\[\w\$-]+$)"); + if ((full_file_name.length () == 2 && full_file_name[1] == ':') + || (full_file_name.length () > 4 && full_file_name[0] == '\\' + && full_file_name[1] == '\\' && pat.is_match (full_file_name))) + full_file_name.push_back ('\\'); #endif - const char *cname = full_file_name.c_str (); + const char *cname = full_file_name.c_str (); - time_t sys_atime, sys_mtime, sys_ctime; + time_t sys_atime, sys_mtime, sys_ctime; - int status - = (m_follow_links - ? octave_stat_wrapper (cname, &m_mode, &m_ino, &m_dev, - &m_nlink, &m_uid, &m_gid, &m_size, - &sys_atime, &sys_mtime, &sys_ctime, - &m_rdev, &m_blksize, &m_blocks) - : octave_lstat_wrapper (cname, &m_mode, &m_ino, &m_dev, - &m_nlink, &m_uid, &m_gid, &m_size, - &sys_atime, &sys_mtime, &sys_ctime, - &m_rdev, &m_blksize, &m_blocks)); + int status + = (m_follow_links + ? octave_stat_wrapper (cname, &m_mode, &m_ino, &m_dev, + &m_nlink, &m_uid, &m_gid, &m_size, + &sys_atime, &sys_mtime, &sys_ctime, + &m_rdev, &m_blksize, &m_blocks) + : octave_lstat_wrapper (cname, &m_mode, &m_ino, &m_dev, + &m_nlink, &m_uid, &m_gid, &m_size, + &sys_atime, &sys_mtime, &sys_ctime, + &m_rdev, &m_blksize, &m_blocks)); - if (status < 0) - { - m_fail = true; - m_errmsg = std::strerror (errno); - } - else - { - m_atime = sys::time (static_cast (sys_atime)); - m_mtime = sys::time (static_cast (sys_mtime)); - m_ctime = sys::time (static_cast (sys_ctime)); - } + if (status < 0) + { + m_fail = true; + m_errmsg = std::strerror (errno); + } + else + { + m_atime = sys::time (static_cast (sys_atime)); + m_mtime = sys::time (static_cast (sys_mtime)); + m_ctime = sys::time (static_cast (sys_ctime)); + } - m_initialized = true; - } + m_initialized = true; } +} - void - file_fstat::update_internal (bool force) +void +file_fstat::update_internal (bool force) +{ + if (! m_initialized || force) { - if (! m_initialized || force) - { - m_initialized = false; - m_fail = false; + m_initialized = false; + m_fail = false; - time_t sys_atime, sys_mtime, sys_ctime; + time_t sys_atime, sys_mtime, sys_ctime; - int status - = octave_fstat_wrapper (m_fid, &m_mode, &m_ino, &m_dev, - &m_nlink, &m_uid, &m_gid, &m_size, - &sys_atime, &sys_mtime, &sys_ctime, - &m_rdev, &m_blksize, &m_blocks); + int status + = octave_fstat_wrapper (m_fid, &m_mode, &m_ino, &m_dev, + &m_nlink, &m_uid, &m_gid, &m_size, + &sys_atime, &sys_mtime, &sys_ctime, + &m_rdev, &m_blksize, &m_blocks); - if (status < 0) - { - m_fail = true; - m_errmsg = std::strerror (errno); - } - else - { - m_atime = sys::time (static_cast (sys_atime)); - m_mtime = sys::time (static_cast (sys_mtime)); - m_ctime = sys::time (static_cast (sys_ctime)); - } + if (status < 0) + { + m_fail = true; + m_errmsg = std::strerror (errno); + } + else + { + m_atime = sys::time (static_cast (sys_atime)); + m_mtime = sys::time (static_cast (sys_mtime)); + m_ctime = sys::time (static_cast (sys_ctime)); + } - m_initialized = true; - } + m_initialized = true; } +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/file-stat.h --- a/liboctave/system/file-stat.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/file-stat.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,290 +38,290 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class - OCTAVE_API - base_file_stat - { - public: +class +OCTAVE_API +base_file_stat +{ +public: + + base_file_stat (void) + : m_initialized (false), m_fail (false), m_errmsg (), m_mode (), + m_ino (), m_dev (), m_nlink (), m_uid (), m_gid (), + m_size (), m_atime (), m_mtime (), m_ctime (), m_rdev (), + m_blksize (), m_blocks () { } - base_file_stat (void) - : m_initialized (false), m_fail (false), m_errmsg (), m_mode (), - m_ino (), m_dev (), m_nlink (), m_uid (), m_gid (), - m_size (), m_atime (), m_mtime (), m_ctime (), m_rdev (), - m_blksize (), m_blocks () { } + base_file_stat (const base_file_stat& fs) + : m_initialized (fs.m_initialized), m_fail (fs.m_fail), + m_errmsg (fs.m_errmsg), m_mode (fs.m_mode), m_ino (fs.m_ino), + m_dev (fs.m_dev), m_nlink (fs.m_nlink), m_uid (fs.m_uid), + m_gid (fs.m_gid), m_size (fs.m_size), m_atime (fs.m_atime), + m_mtime (fs.m_mtime), m_ctime (fs.m_ctime), m_rdev (fs.m_rdev), + m_blksize (fs.m_blksize), m_blocks (fs.m_blocks) { } - base_file_stat (const base_file_stat& fs) - : m_initialized (fs.m_initialized), m_fail (fs.m_fail), - m_errmsg (fs.m_errmsg), m_mode (fs.m_mode), m_ino (fs.m_ino), - m_dev (fs.m_dev), m_nlink (fs.m_nlink), m_uid (fs.m_uid), - m_gid (fs.m_gid), m_size (fs.m_size), m_atime (fs.m_atime), - m_mtime (fs.m_mtime), m_ctime (fs.m_ctime), m_rdev (fs.m_rdev), - m_blksize (fs.m_blksize), m_blocks (fs.m_blocks) { } - - base_file_stat& operator = (const base_file_stat& fs) + base_file_stat& operator = (const base_file_stat& fs) + { + if (this != &fs) { - if (this != &fs) - { - m_initialized = fs.m_initialized; - m_fail = fs.m_fail; - m_errmsg = fs.m_errmsg; - m_mode = fs.m_mode; - m_ino = fs.m_ino; - m_dev = fs.m_dev; - m_nlink = fs.m_nlink; - m_uid = fs.m_uid; - m_gid = fs.m_gid; - m_size = fs.m_size; - m_atime = fs.m_atime; - m_mtime = fs.m_mtime; - m_ctime = fs.m_ctime; - m_rdev = fs.m_rdev; - m_blksize = fs.m_blksize; - m_blocks = fs.m_blocks; - } - - return *this; - } - - // The minimum difference in file time stamp values. - // FIXME: This value should come from the filesystem itself. - // How can we get that info? - sys::time time_resolution (void) const - { - static sys::time resolution (1.0); - return resolution; + m_initialized = fs.m_initialized; + m_fail = fs.m_fail; + m_errmsg = fs.m_errmsg; + m_mode = fs.m_mode; + m_ino = fs.m_ino; + m_dev = fs.m_dev; + m_nlink = fs.m_nlink; + m_uid = fs.m_uid; + m_gid = fs.m_gid; + m_size = fs.m_size; + m_atime = fs.m_atime; + m_mtime = fs.m_mtime; + m_ctime = fs.m_ctime; + m_rdev = fs.m_rdev; + m_blksize = fs.m_blksize; + m_blocks = fs.m_blocks; } - // File status and info. The is_XXX functions will return false for - // file_stat objects that are not properly initialized. The others - // should all return 0 (or the equivalent, for the given object) - // which is likely not meaningful. + return *this; + } - bool is_blk (void) const; - bool is_chr (void) const; - bool is_dir (void) const; - bool is_fifo (void) const; - bool is_lnk (void) const; - bool is_reg (void) const; - bool is_sock (void) const; + // The minimum difference in file time stamp values. + // FIXME: This value should come from the filesystem itself. + // How can we get that info? + sys::time time_resolution (void) const + { + static sys::time resolution (1.0); + return resolution; + } + + // File status and info. The is_XXX functions will return false for + // file_stat objects that are not properly initialized. The others + // should all return 0 (or the equivalent, for the given object) + // which is likely not meaningful. - static bool is_blk (mode_t mode); - static bool is_chr (mode_t mode); - static bool is_dir (mode_t mode); - static bool is_fifo (mode_t mode); - static bool is_lnk (mode_t mode); - static bool is_reg (mode_t mode); - static bool is_sock (mode_t mode); + bool is_blk (void) const; + bool is_chr (void) const; + bool is_dir (void) const; + bool is_fifo (void) const; + bool is_lnk (void) const; + bool is_reg (void) const; + bool is_sock (void) const; - static bool have_struct_stat_st_rdev (void); - static bool have_struct_stat_st_blksize (void); - static bool have_struct_stat_st_blocks (void); - - ino_t ino (void) const { return m_ino; } - dev_t dev (void) const { return m_dev; } + static bool is_blk (mode_t mode); + static bool is_chr (mode_t mode); + static bool is_dir (mode_t mode); + static bool is_fifo (mode_t mode); + static bool is_lnk (mode_t mode); + static bool is_reg (mode_t mode); + static bool is_sock (mode_t mode); - nlink_t nlink (void) const { return m_nlink; } - - uid_t uid (void) const { return m_uid; } - gid_t gid (void) const { return m_gid; } - - off_t size (void) const { return m_size; } + static bool have_struct_stat_st_rdev (void); + static bool have_struct_stat_st_blksize (void); + static bool have_struct_stat_st_blocks (void); - sys::time atime (void) const { return m_atime; } - sys::time mtime (void) const { return m_mtime; } - sys::time ctime (void) const { return m_ctime; } + ino_t ino (void) const { return m_ino; } + dev_t dev (void) const { return m_dev; } - dev_t rdev (void) const { return m_rdev; } + nlink_t nlink (void) const { return m_nlink; } + + uid_t uid (void) const { return m_uid; } + gid_t gid (void) const { return m_gid; } - long blksize (void) const { return m_blksize; } - long blocks (void) const { return m_blocks; } - - mode_t mode (void) const { return m_mode; } + off_t size (void) const { return m_size; } - std::string mode_as_string (void) const; + sys::time atime (void) const { return m_atime; } + sys::time mtime (void) const { return m_mtime; } + sys::time ctime (void) const { return m_ctime; } - bool ok (void) const { return m_initialized && ! m_fail; } + dev_t rdev (void) const { return m_rdev; } - operator bool () const { return ok (); } + long blksize (void) const { return m_blksize; } + long blocks (void) const { return m_blocks; } - bool exists (void) const { return ok (); } + mode_t mode (void) const { return m_mode; } + + std::string mode_as_string (void) const; - std::string error (void) const { return ok () ? "" : m_errmsg; } + bool ok (void) const { return m_initialized && ! m_fail; } - // Has the file referenced by this object been modified since TIME? - bool is_newer (const sys::time& time) const { return m_mtime > time; } + operator bool () const { return ok (); } - // It's nice to be able to hide the file_stat object if we don't - // really care about it. - static int is_newer (const std::string&, const sys::time&); + bool exists (void) const { return ok (); } + + std::string error (void) const { return ok () ? "" : m_errmsg; } - protected: + // Has the file referenced by this object been modified since TIME? + bool is_newer (const sys::time& time) const { return m_mtime > time; } - virtual ~base_file_stat (void) = default; - - // TRUE means we have already called stat. - bool m_initialized; + // It's nice to be able to hide the file_stat object if we don't + // really care about it. + static int is_newer (const std::string&, const sys::time&); - // TRUE means the stat for this file failed. - bool m_fail; +protected: - // If a failure occurs, this contains the system error text. - std::string m_errmsg; + virtual ~base_file_stat (void) = default; - // file type and permissions - mode_t m_mode; + // TRUE means we have already called stat. + bool m_initialized; - // serial number - ino_t m_ino; + // TRUE means the stat for this file failed. + bool m_fail; - // device number - dev_t m_dev; + // If a failure occurs, this contains the system error text. + std::string m_errmsg; - // number of links - nlink_t m_nlink; + // file type and permissions + mode_t m_mode; - // user ID of owner - uid_t m_uid; + // serial number + ino_t m_ino; - // group ID of owner - gid_t m_gid; + // device number + dev_t m_dev; - // size in bytes, for regular files - off_t m_size; + // number of links + nlink_t m_nlink; - // time of last access - sys::time m_atime; + // user ID of owner + uid_t m_uid; + + // group ID of owner + gid_t m_gid; - // time of last modification - sys::time m_mtime; + // size in bytes, for regular files + off_t m_size; - // time of last file status change - sys::time m_ctime; + // time of last access + sys::time m_atime; - // device number for special files - dev_t m_rdev; + // time of last modification + sys::time m_mtime; - // best I/O block size - long m_blksize; + // time of last file status change + sys::time m_ctime; - // number of 512-byte blocks allocated - long m_blocks; - }; + // device number for special files + dev_t m_rdev; - class - OCTAVE_API - file_stat : public base_file_stat - { - public: + // best I/O block size + long m_blksize; + + // number of 512-byte blocks allocated + long m_blocks; +}; - // This constructor must remain defined in the cpp file rather than in - // the header file (bug #50234). - file_stat (const std::string& n = "", bool fl = true); +class +OCTAVE_API +file_stat : public base_file_stat +{ +public: - file_stat (const file_stat& fs) - : base_file_stat (fs), m_file_name (fs.m_file_name), - m_follow_links (fs.m_follow_links) { } + // This constructor must remain defined in the cpp file rather than in + // the header file (bug #50234). + file_stat (const std::string& n = "", bool fl = true); - file_stat& operator = (const file_stat& fs) + file_stat (const file_stat& fs) + : base_file_stat (fs), m_file_name (fs.m_file_name), + m_follow_links (fs.m_follow_links) { } + + file_stat& operator = (const file_stat& fs) + { + if (this != &fs) { - if (this != &fs) - { - base_file_stat::operator = (fs); + base_file_stat::operator = (fs); - m_file_name = fs.m_file_name; - m_follow_links = fs.m_follow_links; - } - - return *this; + m_file_name = fs.m_file_name; + m_follow_links = fs.m_follow_links; } - // This destructor must remain as an empty destructor defined in the - // cpp file rather than in the header file (bug #50234). - ~file_stat (void); + return *this; + } + + // This destructor must remain as an empty destructor defined in the + // cpp file rather than in the header file (bug #50234). + ~file_stat (void); + + void get_stats (bool force = false) + { + if (! m_initialized || force) + update_internal (force); + } - void get_stats (bool force = false) + void get_stats (const std::string& n, bool force = false) + { + if (n != m_file_name || ! m_initialized || force) { - if (! m_initialized || force) - update_internal (force); + m_initialized = false; + + m_file_name = n; + + update_internal (force); } + } + +private: - void get_stats (const std::string& n, bool force = false) + // Name of the file. + std::string m_file_name; + + // TRUE means follow symbolic links to the ultimate file (stat). + // FALSE means get information about the link itself (lstat). + bool m_follow_links; + + void update_internal (bool force = false); +}; + +class +OCTAVE_API +file_fstat : public base_file_stat +{ +public: + + file_fstat (int n) : base_file_stat (), m_fid (n) + { + update_internal (); + } + + file_fstat (const file_fstat& fs) + : base_file_stat (fs), m_fid (fs.m_fid) { } + + file_fstat& operator = (const file_fstat& fs) + { + if (this != &fs) { - if (n != m_file_name || ! m_initialized || force) - { - m_initialized = false; + base_file_stat::operator = (fs); - m_file_name = n; - - update_internal (force); - } + m_fid = fs.m_fid; } - private: - - // Name of the file. - std::string m_file_name; + return *this; + } - // TRUE means follow symbolic links to the ultimate file (stat). - // FALSE means get information about the link itself (lstat). - bool m_follow_links; - - void update_internal (bool force = false); - }; + ~file_fstat (void) = default; - class - OCTAVE_API - file_fstat : public base_file_stat - { - public: - - file_fstat (int n) : base_file_stat (), m_fid (n) - { - update_internal (); - } - - file_fstat (const file_fstat& fs) - : base_file_stat (fs), m_fid (fs.m_fid) { } - - file_fstat& operator = (const file_fstat& fs) - { - if (this != &fs) - { - base_file_stat::operator = (fs); + void get_stats (bool force = false) + { + if (! m_initialized || force) + update_internal (force); + } - m_fid = fs.m_fid; - } - - return *this; - } - - ~file_fstat (void) = default; - - void get_stats (bool force = false) - { - if (! m_initialized || force) - update_internal (force); - } - - void get_stats (int n, bool force = false) + void get_stats (int n, bool force = false) + { + if (n != m_fid || ! m_initialized || force) { - if (n != m_fid || ! m_initialized || force) - { - m_initialized = false; + m_initialized = false; - m_fid = n; + m_fid = n; - update_internal (force); - } + update_internal (force); } + } - private: +private: - // Open file descriptor. - int m_fid; + // Open file descriptor. + int m_fid; - void update_internal (bool force = false); - }; + void update_internal (bool force = false); +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/lo-sysdep.cc --- a/liboctave/system/lo-sysdep.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/lo-sysdep.cc Thu Dec 01 20:05:44 2022 -0800 @@ -55,136 +55,284 @@ OCTAVE_BEGIN_NAMESPACE(sys) - int - system (const std::string& cmd_str) - { +int +system (const std::string& cmd_str) +{ #if defined (OCTAVE_USE_WINDOWS_API) - const std::wstring wcmd_str = u8_to_wstring (cmd_str); + const std::wstring wcmd_str = u8_to_wstring (cmd_str); - return _wsystem (wcmd_str.c_str ()); + return _wsystem (wcmd_str.c_str ()); #else - return ::system (cmd_str.c_str ()); + return ::system (cmd_str.c_str ()); #endif - } +} - std::string - getcwd (void) - { - std::string retval; +std::string +getcwd (void) +{ + std::string retval; #if defined (OCTAVE_USE_WINDOWS_API) - wchar_t *tmp = _wgetcwd (nullptr, 0); + wchar_t *tmp = _wgetcwd (nullptr, 0); - if (! tmp) - (*current_liboctave_error_handler) ("unable to find current directory"); + if (! tmp) + (*current_liboctave_error_handler) ("unable to find current directory"); - std::wstring tmp_wstr (tmp); - free (tmp); + std::wstring tmp_wstr (tmp); + free (tmp); - std::string tmp_str = u8_from_wstring (tmp_wstr); + std::string tmp_str = u8_from_wstring (tmp_wstr); - retval = tmp_str; + retval = tmp_str; #else - // Using octave_getcwd_wrapper ensures that we have a getcwd that - // will allocate a buffer as large as necessary if buf and size are - // both 0. + // Using octave_getcwd_wrapper ensures that we have a getcwd that + // will allocate a buffer as large as necessary if buf and size are + // both 0. - char *tmp = octave_getcwd_wrapper (nullptr, 0); + char *tmp = octave_getcwd_wrapper (nullptr, 0); + + if (! tmp) + (*current_liboctave_error_handler) ("unable to find current directory"); - if (! tmp) - (*current_liboctave_error_handler) ("unable to find current directory"); + retval = tmp; + free (tmp); +#endif + + return retval; +} - retval = tmp; - free (tmp); +int +chdir (const std::string& path_arg) +{ + std::string path = sys::file_ops::tilde_expand (path_arg); + +#if defined (OCTAVE_USE_WINDOWS_API) + if (path.length () == 2 && path[1] == ':') + path += '\\'; #endif - return retval; + return octave_chdir_wrapper (path.c_str ()); +} + +bool +get_dirlist (const std::string& dirname, string_vector& dirlist, + std::string& msg) +{ + dirlist = ""; + msg = ""; +#if defined (OCTAVE_USE_WINDOWS_API) + _WIN32_FIND_DATAW ffd; + + std::string path_name (dirname); + if (path_name.empty ()) + return true; + + if (path_name.back () == '\\' || path_name.back () == '/') + path_name.push_back ('*'); + else + path_name.append (R"(\*)"); + + // Find first file in directory. + std::wstring wpath_name = u8_to_wstring (path_name); + HANDLE hFind = FindFirstFileW (wpath_name.c_str (), &ffd); + if (INVALID_HANDLE_VALUE == hFind) + { + DWORD errCode = GetLastError (); + char *errorText = nullptr; + FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, errCode, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast (&errorText), 0, nullptr); + if (errorText != nullptr) + { + msg = std::string (errorText); + LocalFree (errorText); + } + return false; } - int - chdir (const std::string& path_arg) - { - std::string path = sys::file_ops::tilde_expand (path_arg); + std::list dirlist_str; + do + dirlist_str.push_back (u8_from_wstring (ffd.cFileName)); + while (FindNextFileW (hFind, &ffd) != 0); + + FindClose(hFind); + + dirlist = string_vector (dirlist_str); -#if defined (OCTAVE_USE_WINDOWS_API) - if (path.length () == 2 && path[1] == ':') - path += '\\'; -#endif +#else + + dir_entry dir (dirname); - return octave_chdir_wrapper (path.c_str ()); + if (! dir) + { + msg = dir.error (); + return false; } - bool - get_dirlist (const std::string& dirname, string_vector& dirlist, - std::string& msg) - { - dirlist = ""; - msg = ""; + dirlist = dir.read (); + + dir.close (); +#endif + + return true; +} + #if defined (OCTAVE_USE_WINDOWS_API) - _WIN32_FIND_DATAW ffd; - std::string path_name (dirname); - if (path_name.empty ()) - return true; +static bool check_fseek_ftell_workaround_needed (bool set_nonbuffered_mode) +{ + // To check whether the workaround is needed: + // + // * Create a tmp file with LF line endings only. + // + // * Open that file for reading in text mode. + // + // * Read a line. + // + // * Use ftello to record the position of the beginning of the + // second line. + // + // * Read and save the contents of the second line. + // + // * Use fseeko to return to the saved position. + // + // * Read the second line again and compare to the previously + // saved text. + // + // * If the lines are different, we need to set non-buffered + // input mode for files opened in text mode. - if (path_name.back () == '\\' || path_name.back () == '/') - path_name.push_back ('*'); - else - path_name.append (R"(\*)"); + std::string tmpname = sys::tempnam ("", "oct-"); - // Find first file in directory. - std::wstring wpath_name = u8_to_wstring (path_name); - HANDLE hFind = FindFirstFileW (wpath_name.c_str (), &ffd); - if (INVALID_HANDLE_VALUE == hFind) + if (tmpname.empty ()) + { + (*current_liboctave_warning_handler) + ("fseek/ftell bug check failed (tmp name creation)!"); + return false; + } + + std::FILE *fptr = std::fopen (tmpname.c_str (), "wb"); + + if (! fptr) + { + (*current_liboctave_warning_handler) + ("fseek/ftell bug check failed (opening tmp file for writing)!"); + return false; + } + + fprintf (fptr, "%s", "foo\nbar\nbaz\n"); + + std::fclose (fptr); + + fptr = std::fopen (tmpname.c_str (), "rt"); + + if (! fptr) + { + (*current_liboctave_warning_handler) + ("fseek/ftell bug check failed (opening tmp file for reading)!"); + return false; + } + + unwind_action act ([=] () + { + std::fclose (fptr); + sys::unlink (tmpname); + }); + + if (set_nonbuffered_mode) + ::setvbuf (fptr, nullptr, _IONBF, 0); + + while (true) + { + int c = fgetc (fptr); + + if (c == EOF) { - DWORD errCode = GetLastError (); - char *errorText = nullptr; - FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, errCode, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast (&errorText), 0, nullptr); - if (errorText != nullptr) - { - msg = std::string (errorText); - LocalFree (errorText); - } + (*current_liboctave_warning_handler) + ("fseek/ftell bug check failed (skipping first line)!"); return false; } - std::list dirlist_str; - do - dirlist_str.push_back (u8_from_wstring (ffd.cFileName)); - while (FindNextFileW (hFind, &ffd) != 0); + if (c == '\n') + break; + } - FindClose(hFind); + off_t pos = octave_ftello_wrapper (fptr); - dirlist = string_vector (dirlist_str); - -#else + char buf1[8]; + int i = 0; + while (true) + { + int c = fgetc (fptr); - dir_entry dir (dirname); - - if (! dir) + if (c == EOF) { - msg = dir.error (); + (*current_liboctave_warning_handler) + ("fseek/ftell bug check failed (reading second line)!"); return false; } - dirlist = dir.read (); + if (c == '\n') + break; + + buf1[i++] = static_cast (c); + } + buf1[i] = '\0'; + + octave_fseeko_wrapper (fptr, pos, SEEK_SET); + + char buf2[8]; + i = 0; + while (true) + { + int c = fgetc (fptr); - dir.close (); + if (c == EOF) + { + (*current_liboctave_warning_handler) + ("fseek/ftell bug check failed (reading after repositioning)!"); + return false; + } + + if (c == '\n') + break; + + buf2[i++] = static_cast (c); + } + buf2[i] = '\0'; + + return strcmp (buf1, buf2); +} + #endif - return true; - } - +std::FILE * +fopen (const std::string& filename, const std::string& mode) +{ #if defined (OCTAVE_USE_WINDOWS_API) - static bool check_fseek_ftell_workaround_needed (bool set_nonbuffered_mode) + std::wstring wfilename = u8_to_wstring (filename); + std::wstring wmode = u8_to_wstring (mode); + + std::FILE *fptr = _wfopen (wfilename.c_str (), wmode.c_str ()); + + static bool fseek_ftell_bug_workaround_needed = false; + static bool fseek_ftell_bug_checked = false; + + if (! fseek_ftell_bug_checked && mode.find ('t') != std::string::npos) { + // FIXME: Is the following workaround needed for all files + // opened in text mode, or only for files opened for reading? + + // Try to avoid fseek/ftell bug on Windows systems by setting + // non-buffered input mode for files opened in text mode, but + // only if it appears that the workaround is needed. See + // Octave bug #58055. + // To check whether the workaround is needed: // // * Create a tmp file with LF line endings only. @@ -193,559 +341,411 @@ // // * Read a line. // - // * Use ftello to record the position of the beginning of the - // second line. + // * Use ftello to record the position of the beginning of + // the second line. // // * Read and save the contents of the second line. // // * Use fseeko to return to the saved position. // - // * Read the second line again and compare to the previously - // saved text. + // * Read the second line again and compare to the + // previously saved text. // // * If the lines are different, we need to set non-buffered // input mode for files opened in text mode. - - std::string tmpname = sys::tempnam ("", "oct-"); - - if (tmpname.empty ()) - { - (*current_liboctave_warning_handler) - ("fseek/ftell bug check failed (tmp name creation)!"); - return false; - } - - std::FILE *fptr = std::fopen (tmpname.c_str (), "wb"); + // + // * To verify that the workaround solves the problem, + // repeat the above test with non-buffered input mode. If + // that fails, warn that there may be trouble with + // ftell/fseek when reading files opened in text mode. - if (! fptr) - { - (*current_liboctave_warning_handler) - ("fseek/ftell bug check failed (opening tmp file for writing)!"); - return false; - } - - fprintf (fptr, "%s", "foo\nbar\nbaz\n"); - - std::fclose (fptr); - - fptr = std::fopen (tmpname.c_str (), "rt"); - - if (! fptr) + if (check_fseek_ftell_workaround_needed (false)) { - (*current_liboctave_warning_handler) - ("fseek/ftell bug check failed (opening tmp file for reading)!"); - return false; - } - - unwind_action act ([=] () - { - std::fclose (fptr); - sys::unlink (tmpname); - }); - - if (set_nonbuffered_mode) - ::setvbuf (fptr, nullptr, _IONBF, 0); - - while (true) - { - int c = fgetc (fptr); - - if (c == EOF) - { - (*current_liboctave_warning_handler) - ("fseek/ftell bug check failed (skipping first line)!"); - return false; - } - - if (c == '\n') - break; + if (check_fseek_ftell_workaround_needed (true)) + (*current_liboctave_warning_handler) + ("fseek/ftell may fail for files opened in text mode"); + else + fseek_ftell_bug_workaround_needed = true; } - off_t pos = octave_ftello_wrapper (fptr); - - char buf1[8]; - int i = 0; - while (true) - { - int c = fgetc (fptr); - - if (c == EOF) - { - (*current_liboctave_warning_handler) - ("fseek/ftell bug check failed (reading second line)!"); - return false; - } - - if (c == '\n') - break; - - buf1[i++] = static_cast (c); - } - buf1[i] = '\0'; - - octave_fseeko_wrapper (fptr, pos, SEEK_SET); - - char buf2[8]; - i = 0; - while (true) - { - int c = fgetc (fptr); - - if (c == EOF) - { - (*current_liboctave_warning_handler) - ("fseek/ftell bug check failed (reading after repositioning)!"); - return false; - } - - if (c == '\n') - break; - - buf2[i++] = static_cast (c); - } - buf2[i] = '\0'; - - return strcmp (buf1, buf2); + fseek_ftell_bug_checked = true; } -#endif + if (fseek_ftell_bug_workaround_needed + && mode.find ('t') != std::string::npos) + ::setvbuf (fptr, nullptr, _IONBF, 0); + + return fptr; - std::FILE * - fopen (const std::string& filename, const std::string& mode) - { +#else + return std::fopen (filename.c_str (), mode.c_str ()); +#endif +} + +std::FILE * +fopen_tmp (const std::string& name, const std::string& mode) +{ #if defined (OCTAVE_USE_WINDOWS_API) - std::wstring wfilename = u8_to_wstring (filename); - std::wstring wmode = u8_to_wstring (mode); - - std::FILE *fptr = _wfopen (wfilename.c_str (), wmode.c_str ()); - - static bool fseek_ftell_bug_workaround_needed = false; - static bool fseek_ftell_bug_checked = false; - - if (! fseek_ftell_bug_checked && mode.find ('t') != std::string::npos) - { - // FIXME: Is the following workaround needed for all files - // opened in text mode, or only for files opened for reading? - - // Try to avoid fseek/ftell bug on Windows systems by setting - // non-buffered input mode for files opened in text mode, but - // only if it appears that the workaround is needed. See - // Octave bug #58055. + // Append "D" to the mode string to indicate that this is a temporary + // file that should be deleted when the last open handle is closed. + std::string tmp_mode = mode + "D"; - // To check whether the workaround is needed: - // - // * Create a tmp file with LF line endings only. - // - // * Open that file for reading in text mode. - // - // * Read a line. - // - // * Use ftello to record the position of the beginning of - // the second line. - // - // * Read and save the contents of the second line. - // - // * Use fseeko to return to the saved position. - // - // * Read the second line again and compare to the - // previously saved text. - // - // * If the lines are different, we need to set non-buffered - // input mode for files opened in text mode. - // - // * To verify that the workaround solves the problem, - // repeat the above test with non-buffered input mode. If - // that fails, warn that there may be trouble with - // ftell/fseek when reading files opened in text mode. - - if (check_fseek_ftell_workaround_needed (false)) - { - if (check_fseek_ftell_workaround_needed (true)) - (*current_liboctave_warning_handler) - ("fseek/ftell may fail for files opened in text mode"); - else - fseek_ftell_bug_workaround_needed = true; - } - - fseek_ftell_bug_checked = true; - } - - if (fseek_ftell_bug_workaround_needed - && mode.find ('t') != std::string::npos) - ::setvbuf (fptr, nullptr, _IONBF, 0); - - return fptr; - -#else - return std::fopen (filename.c_str (), mode.c_str ()); -#endif - } - - std::FILE * - fopen_tmp (const std::string& name, const std::string& mode) - { -#if defined (OCTAVE_USE_WINDOWS_API) - - // Append "D" to the mode string to indicate that this is a temporary - // file that should be deleted when the last open handle is closed. - std::string tmp_mode = mode + "D"; - - return std::fopen (name.c_str (), tmp_mode.c_str ()); + return std::fopen (name.c_str (), tmp_mode.c_str ()); #else - std::FILE *fptr = std::fopen (name.c_str (), mode.c_str ()); + std::FILE *fptr = std::fopen (name.c_str (), mode.c_str ()); - // From gnulib: This relies on the Unix semantics that a file is not - // really removed until it is closed. - octave_unlink_wrapper (name.c_str ()); + // From gnulib: This relies on the Unix semantics that a file is not + // really removed until it is closed. + octave_unlink_wrapper (name.c_str ()); - return fptr; + return fptr; #endif - } +} - std::fstream - fstream (const std::string& filename, const std::ios::openmode mode) - { +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); + std::wstring wfilename = u8_to_wstring (filename); - return std::fstream (wfilename.c_str (), mode); + return std::fstream (wfilename.c_str (), mode); #else - return std::fstream (filename.c_str (), mode); + return std::fstream (filename.c_str (), mode); #endif - } +} - std::ifstream - ifstream (const std::string& filename, const std::ios::openmode mode) - { +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); + std::wstring wfilename = u8_to_wstring (filename); - return std::ifstream (wfilename.c_str (), mode); + return std::ifstream (wfilename.c_str (), mode); #else - return std::ifstream (filename.c_str (), mode); + return std::ifstream (filename.c_str (), mode); #endif - } +} - std::ofstream - ofstream (const std::string& filename, const std::ios::openmode mode) - { +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); + std::wstring wfilename = u8_to_wstring (filename); - return std::ofstream (wfilename.c_str (), mode); + return std::ofstream (wfilename.c_str (), mode); #else - return std::ofstream (filename.c_str (), mode); + return std::ofstream (filename.c_str (), mode); #endif - } +} - void - putenv_wrapper (const std::string& name, const std::string& value) - { - std::string new_env = name + "=" + value; +void +putenv_wrapper (const std::string& name, const std::string& value) +{ + std::string new_env = name + "=" + value; - // FIXME: The malloc leaks memory, but so would a call to setenv. - // Short of extreme measures to track memory, altering the environment - // always leaks memory, but the saving grace is that the leaks are small. + // FIXME: The malloc leaks memory, but so would a call to setenv. + // Short of extreme measures to track memory, altering the environment + // always leaks memory, but the saving grace is that the leaks are small. - // As far as I can see there's no way to distinguish between the - // various errors; putenv doesn't have errno values. + // As far as I can see there's no way to distinguish between the + // various errors; putenv doesn't have errno values. #if defined (OCTAVE_USE_WINDOWS_API) - std::wstring new_wenv = u8_to_wstring (new_env); + std::wstring new_wenv = u8_to_wstring (new_env); - int len = (new_wenv.length () + 1) * sizeof (wchar_t); + int len = (new_wenv.length () + 1) * sizeof (wchar_t); - wchar_t *new_item = static_cast (std::malloc (len)); + wchar_t *new_item = static_cast (std::malloc (len)); - wcscpy (new_item, new_wenv.c_str()); + wcscpy (new_item, new_wenv.c_str()); - if (_wputenv (new_item) < 0) - (*current_liboctave_error_handler) - ("putenv (%s) failed", new_env.c_str()); + if (_wputenv (new_item) < 0) + (*current_liboctave_error_handler) + ("putenv (%s) failed", new_env.c_str()); #else - int len = new_env.length () + 1; + int len = new_env.length () + 1; + + char *new_item = static_cast (std::malloc (len)); - char *new_item = static_cast (std::malloc (len)); + std::strcpy (new_item, new_env.c_str()); + + if (octave_putenv_wrapper (new_item) < 0) + (*current_liboctave_error_handler) ("putenv (%s) failed", new_item); +#endif +} - std::strcpy (new_item, new_env.c_str()); +std::string +getenv_wrapper (const std::string& name) +{ +#if defined (OCTAVE_USE_WINDOWS_API) + std::wstring wname = u8_to_wstring (name); + wchar_t *env = _wgetenv (wname.c_str ()); + return env ? u8_from_wstring (env) : ""; +#else + char *env = ::getenv (name.c_str ()); + return env ? env : ""; +#endif +} - if (octave_putenv_wrapper (new_item) < 0) - (*current_liboctave_error_handler) ("putenv (%s) failed", new_item); -#endif - } +int +unsetenv_wrapper (const std::string& name) +{ +#if defined (OCTAVE_USE_WINDOWS_API) + putenv_wrapper (name, ""); - std::string - getenv_wrapper (const std::string& name) + std::wstring wname = u8_to_wstring (name); + return (SetEnvironmentVariableW (wname.c_str (), nullptr) ? 0 : -1); +#else + return octave_unsetenv_wrapper (name.c_str ()); +#endif +} + +std::wstring +u8_to_wstring (const std::string& utf8_string) +{ + // convert multibyte UTF-8 string to wide character string + static std::wstring_convert, wchar_t> + wchar_conv; + + std::wstring retval = L""; + + try { -#if defined (OCTAVE_USE_WINDOWS_API) - std::wstring wname = u8_to_wstring (name); - wchar_t *env = _wgetenv (wname.c_str ()); - return env ? u8_from_wstring (env) : ""; -#else - char *env = ::getenv (name.c_str ()); - return env ? env : ""; -#endif + retval = wchar_conv.from_bytes (utf8_string); + } + catch (const std::range_error& e) + { + // What to do in case of error? + // error ("u8_to_wstring: converting from UTF-8 to wchar_t: %s", + // e.what ()); } - int - unsetenv_wrapper (const std::string& name) - { -#if defined (OCTAVE_USE_WINDOWS_API) - putenv_wrapper (name, ""); + return retval; +} - std::wstring wname = u8_to_wstring (name); - return (SetEnvironmentVariableW (wname.c_str (), nullptr) ? 0 : -1); -#else - return octave_unsetenv_wrapper (name.c_str ()); -#endif - } - - std::wstring - u8_to_wstring (const std::string& utf8_string) - { - // convert multibyte UTF-8 string to wide character string - static std::wstring_convert, wchar_t> - wchar_conv; - - std::wstring retval = L""; +std::string +u8_from_wstring (const std::wstring& wchar_string) +{ + // convert wide character string to multibyte UTF-8 string + static std::wstring_convert, wchar_t> + wchar_conv; - try - { - retval = wchar_conv.from_bytes (utf8_string); - } - catch (const std::range_error& e) - { - // What to do in case of error? - // error ("u8_to_wstring: converting from UTF-8 to wchar_t: %s", - // e.what ()); - } + std::string retval = ""; - return retval; - } - - std::string - u8_from_wstring (const std::wstring& wchar_string) + try { - // convert wide character string to multibyte UTF-8 string - static std::wstring_convert, wchar_t> - wchar_conv; - - std::string retval = ""; - - try - { - retval = wchar_conv.to_bytes (wchar_string); - } - catch (const std::range_error& e) - { - // What to do in case of error? - // error ("u8_from_wstring: converting from wchar_t to UTF-8: %s", - // e.what ()); - } - - return retval; + retval = wchar_conv.to_bytes (wchar_string); + } + catch (const std::range_error& e) + { + // What to do in case of error? + // error ("u8_from_wstring: converting from wchar_t to UTF-8: %s", + // e.what ()); } - // At quite a few places in the code we are passing file names as - // char arrays to external library functions. + return retval; +} - // When these functions try to locate the corresponding file on the - // disc, they need to use the wide character API on Windows to - // correctly open files with non-ASCII characters. +// At quite a few places in the code we are passing file names as +// char arrays to external library functions. + +// When these functions try to locate the corresponding file on the +// disc, they need to use the wide character API on Windows to +// correctly open files with non-ASCII characters. - // But they have no way of knowing which encoding we are using for - // the passed string. So they have no way of reliably converting to - // a wchar_t array. (I.e. there is no possible fix for these - // functions with current C or C++.) +// But they have no way of knowing which encoding we are using for +// the passed string. So they have no way of reliably converting to +// a wchar_t array. (I.e. there is no possible fix for these +// functions with current C or C++.) - // To solve the dilemma, the function "get_ASCII_filename" first - // checks whether there are any non-ASCII characters in the passed - // file name. If there are not, it returns the original name. +// To solve the dilemma, the function "get_ASCII_filename" first +// checks whether there are any non-ASCII characters in the passed +// file name. If there are not, it returns the original name. - // Otherwise, it optionally tries to convert the file name to the locale - // charset. +// 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 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 - // possible level that doesn't contain non-ASCII characters. At - // that level a hidden folder is created that holds the hard links. - // That means we need to have write access on that location. A path - // to that hard link is returned. +// 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 +// possible level that doesn't contain non-ASCII characters. At +// that level a hidden folder is created that holds the hard links. +// That means we need to have write access on that location. A path +// to that hard link is returned. - // If the file system is FAT32, there are no hard links. But FAT32 - // always stores short file names. So we are safe. +// If the file system is FAT32, there are no hard links. But FAT32 +// always stores short file names. So we are safe. - // ExFAT that is occasionally used on USB sticks and SD cards stores - // neither short file names nor does it support hard links. So for - // exFAT with this function, there is (currently) no way to generate - // a file name that is stripped from non-ASCII characters but still - // is valid. +// ExFAT that is occasionally used on USB sticks and SD cards stores +// neither short file names nor does it support hard links. So for +// exFAT with this function, there is (currently) no way to generate +// a file name that is stripped from non-ASCII characters but still +// is valid. - // For Unixy systems, this function does nothing. +// For Unixy systems, this function does nothing. - std::string - get_ASCII_filename (const std::string& orig_file_name, - const bool allow_locale) - { +std::string +get_ASCII_filename (const std::string& orig_file_name, + const bool allow_locale) +{ #if defined (OCTAVE_USE_WINDOWS_API) - // Return file name that only contains ASCII characters that can - // be used to access the file orig_file_name. The original file - // must exist in the file system before calling this function. - // This is useful for passing file names to functions that are not - // aware of the character encoding we are using. + // Return file name that only contains ASCII characters that can + // be used to access the file orig_file_name. The original file + // must exist in the file system before calling this function. + // This is useful for passing file names to functions that are not + // aware of the character encoding we are using. - // 0. 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 (), - [](char c) { return (c < 0 || c >= 128); }); + std::string::const_iterator first_non_ASCII + = std::find_if (orig_file_name.begin (), orig_file_name.end (), + [](char c) { return (c < 0 || c >= 128); }); - if (first_non_ASCII == orig_file_name.end ()) - return orig_file_name; + 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) + // 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 char *locale = octave_locale_charset_wrapper (); - if (locale) + const uint8_t *name_u8 = reinterpret_cast + (orig_file_name.c_str ()); + std::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) { - const uint8_t *name_u8 = reinterpret_cast - (orig_file_name.c_str ()); - std::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; - } + std::string file_name_locale (name_locale, length); + free (name_locale); + return file_name_locale; } } + } - // 2. Check if file system stores short filenames (might be ASCII-only). + // 2. Check if file system stores short filenames (might be ASCII-only). + + std::wstring w_orig_file_name_str = u8_to_wstring (orig_file_name); + const wchar_t *w_orig_file_name = w_orig_file_name_str.c_str (); + + // Get full path to file + wchar_t w_full_file_name[_MAX_PATH]; + if (_wfullpath (w_full_file_name, w_orig_file_name, _MAX_PATH) == nullptr) + return orig_file_name; + + std::wstring w_full_file_name_str = w_full_file_name; + + // Get short filename (8.3) from UTF-16 filename. + + long length = GetShortPathNameW (w_full_file_name, nullptr, 0); + + if (length > 0) + { + // Dynamically allocate the correct size (terminating null char + // was included in 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 + = std::wstring (w_short_file_name, length); - std::wstring w_orig_file_name_str = u8_to_wstring (orig_file_name); - const wchar_t *w_orig_file_name = w_orig_file_name_str.c_str (); + if (w_short_file_name_str.compare (0, length-1, w_full_file_name_str) != 0) + { + // Check whether short file name contains non-ASCII characters + std::string short_file_name + = u8_from_wstring (w_short_file_name_str); + first_non_ASCII + = std::find_if (short_file_name.begin (), + short_file_name.end (), + [](char c) { return (c < 0 || c >= 128); }); + if (first_non_ASCII == short_file_name.end ()) + return short_file_name; + } + } + + // 3. Create hard link with only-ASCII characters. + // Get longest possible part of path that only contains ASCII chars. - // Get full path to file - wchar_t w_full_file_name[_MAX_PATH]; - if (_wfullpath (w_full_file_name, w_orig_file_name, _MAX_PATH) == nullptr) + std::wstring::iterator w_first_non_ASCII + = std::find_if (w_full_file_name_str.begin (), w_full_file_name_str.end (), + [](wchar_t c) { return (c < 0 || c >= 128); }); + std::wstring tmp_substr + = std::wstring (w_full_file_name_str.begin (), w_first_non_ASCII); + + std::size_t pos + = tmp_substr.find_last_of (u8_to_wstring (file_ops::dir_sep_chars ())); + + std::string par_dir + = u8_from_wstring (w_full_file_name_str.substr (0, pos+1)); + + // Create .oct_ascii directory. + // FIXME: We need to have write permission in this location. + + std::string oct_ascii_dir = par_dir + ".oct_ascii"; + std::string test_dir = canonicalize_file_name (oct_ascii_dir); + + if (test_dir.empty ()) + { + std::string msg; + int status = sys::mkdir (oct_ascii_dir, 0777, msg); + + if (status < 0) return orig_file_name; - std::wstring w_full_file_name_str = w_full_file_name; - - // Get short filename (8.3) from UTF-16 filename. - - long length = GetShortPathNameW (w_full_file_name, nullptr, 0); - - if (length > 0) - { - // Dynamically allocate the correct size (terminating null char - // was included in 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 - = std::wstring (w_short_file_name, length); + // Set hidden property. + SetFileAttributesA (oct_ascii_dir.c_str (), FILE_ATTRIBUTE_HIDDEN); + } - if (w_short_file_name_str.compare (0, length-1, w_full_file_name_str) != 0) - { - // Check whether short file name contains non-ASCII characters - std::string short_file_name - = u8_from_wstring (w_short_file_name_str); - first_non_ASCII - = std::find_if (short_file_name.begin (), - short_file_name.end (), - [](char c) { return (c < 0 || c >= 128); }); - if (first_non_ASCII == short_file_name.end ()) - return short_file_name; - } - } - - // 3. Create hard link with only-ASCII characters. - // Get longest possible part of path that only contains ASCII chars. - - std::wstring::iterator w_first_non_ASCII - = std::find_if (w_full_file_name_str.begin (), w_full_file_name_str.end (), - [](wchar_t c) { return (c < 0 || c >= 128); }); - std::wstring tmp_substr - = std::wstring (w_full_file_name_str.begin (), w_first_non_ASCII); + // Create file from hash of full filename. + std::string filename_hash + = (oct_ascii_dir + file_ops::dir_sep_str () + + crypto::hash ("SHA1", orig_file_name)); - std::size_t pos - = tmp_substr.find_last_of (u8_to_wstring (file_ops::dir_sep_chars ())); - - std::string par_dir - = u8_from_wstring (w_full_file_name_str.substr (0, pos+1)); - - // Create .oct_ascii directory. - // FIXME: We need to have write permission in this location. + // FIXME: This is just to check if the file exists. Use a more efficient + // method. + std::string abs_filename_hash = canonicalize_file_name (filename_hash); - std::string oct_ascii_dir = par_dir + ".oct_ascii"; - std::string test_dir = canonicalize_file_name (oct_ascii_dir); - - if (test_dir.empty ()) - { - std::string msg; - int status = sys::mkdir (oct_ascii_dir, 0777, msg); - - if (status < 0) - return orig_file_name; + if (! abs_filename_hash.empty ()) + sys::unlink (filename_hash); - // Set hidden property. - SetFileAttributesA (oct_ascii_dir.c_str (), FILE_ATTRIBUTE_HIDDEN); - } - - // Create file from hash of full filename. - std::string filename_hash - = (oct_ascii_dir + file_ops::dir_sep_str () - + crypto::hash ("SHA1", orig_file_name)); + // At this point, we know that we have only ASCII characters. + // So instead of converting, just copy the characters to std::wstring. + std::wstring w_filename_hash (filename_hash.begin (), + filename_hash.end ()); - // FIXME: This is just to check if the file exists. Use a more efficient - // method. - std::string abs_filename_hash = canonicalize_file_name (filename_hash); - - if (! abs_filename_hash.empty ()) - sys::unlink (filename_hash); - - // At this point, we know that we have only ASCII characters. - // So instead of converting, just copy the characters to std::wstring. - std::wstring w_filename_hash (filename_hash.begin (), - filename_hash.end ()); - - if (CreateHardLinkW (w_filename_hash.c_str (), w_orig_file_name, nullptr)) - return filename_hash; + if (CreateHardLinkW (w_filename_hash.c_str (), w_orig_file_name, nullptr)) + return filename_hash; #else - octave_unused_parameter (allow_locale); + octave_unused_parameter (allow_locale); #endif - return orig_file_name; - } + return orig_file_name; +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/lo-sysdep.h --- a/liboctave/system/lo-sysdep.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/lo-sysdep.h Thu Dec 01 20:05:44 2022 -0800 @@ -41,48 +41,48 @@ OCTAVE_BEGIN_NAMESPACE(sys) - extern OCTAVE_API int system (const std::string& cmd_str); +extern OCTAVE_API int system (const std::string& cmd_str); - extern OCTAVE_API std::string getcwd (void); +extern OCTAVE_API std::string getcwd (void); - extern OCTAVE_API int chdir (const std::string&); +extern OCTAVE_API int chdir (const std::string&); - extern OCTAVE_API bool - get_dirlist (const std::string& dirname, string_vector& dirlist, - std::string& msg); +extern OCTAVE_API bool +get_dirlist (const std::string& dirname, string_vector& dirlist, + std::string& msg); - extern OCTAVE_API std::FILE * - fopen (const std::string& name, const std::string& mode); +extern OCTAVE_API std::FILE * +fopen (const std::string& name, const std::string& mode); - extern OCTAVE_API std::FILE * - fopen_tmp (const std::string& name, const std::string& mode); +extern OCTAVE_API std::FILE * +fopen_tmp (const std::string& name, const std::string& mode); - extern OCTAVE_API std::fstream - fstream (const std::string& name, - const std::ios::openmode mode = std::ios::in | std::ios::out); +extern OCTAVE_API std::fstream +fstream (const std::string& name, + const std::ios::openmode mode = std::ios::in | std::ios::out); - extern OCTAVE_API std::ifstream - ifstream (const std::string& name, - const std::ios::openmode mode = std::ios::in); +extern OCTAVE_API std::ifstream +ifstream (const std::string& name, + const std::ios::openmode mode = std::ios::in); - extern OCTAVE_API std::ofstream - ofstream (const std::string& name, - const std::ios::openmode mode = std::ios::out); +extern OCTAVE_API std::ofstream +ofstream (const std::string& name, + const std::ios::openmode mode = std::ios::out); - extern OCTAVE_API void - putenv_wrapper (const std::string& name, const std::string& value); +extern OCTAVE_API void +putenv_wrapper (const std::string& name, const std::string& value); - extern OCTAVE_API std::string getenv_wrapper (const std::string&); +extern OCTAVE_API std::string getenv_wrapper (const std::string&); - extern OCTAVE_API int unsetenv_wrapper (const std::string&); +extern OCTAVE_API int unsetenv_wrapper (const std::string&); - extern OCTAVE_API std::wstring u8_to_wstring (const std::string&); +extern OCTAVE_API std::wstring u8_to_wstring (const std::string&); - extern OCTAVE_API std::string u8_from_wstring (const std::wstring&); +extern OCTAVE_API std::string u8_from_wstring (const std::wstring&); - extern OCTAVE_API std::string - get_ASCII_filename (const std::string& long_file_name, - const bool allow_locale = false); +extern OCTAVE_API std::string +get_ASCII_filename (const std::string& long_file_name, + const bool allow_locale = false); OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/lo-sysinfo.cc --- a/liboctave/system/lo-sysinfo.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/lo-sysinfo.cc Thu Dec 01 20:05:44 2022 -0800 @@ -42,155 +42,155 @@ OCTAVE_BEGIN_NAMESPACE(sys) - std::string blas_version (void) - { - dynamic_library dyn_libs (""); +std::string blas_version (void) +{ + dynamic_library dyn_libs (""); - if (! dyn_libs) - return "unknown BLAS"; - - std::string retval; - - // Check for functions that are specific to certain BLAS implementations. + if (! dyn_libs) + return "unknown BLAS"; - // FlexiBLAS - typedef void (*flexi_f_type) (int *, int *, int *); - flexi_f_type flexi_f_ptr = reinterpret_cast - (dyn_libs.search ("flexiblas_get_version")); + std::string retval; + + // Check for functions that are specific to certain BLAS implementations. - if (flexi_f_ptr) - { - int v_major = 0; - int v_minor = 0; - int v_patch = 0; - flexi_f_ptr (&v_major, &v_minor, &v_patch); - - std::ostringstream s; - s << "FlexiBLAS Version " - << v_major << "." << v_minor << "." << v_patch; + // FlexiBLAS + typedef void (*flexi_f_type) (int *, int *, int *); + flexi_f_type flexi_f_ptr = reinterpret_cast + (dyn_libs.search ("flexiblas_get_version")); - retval = s.str (); - } - - // OpenBLAS - typedef char * (*open_fcn_type) (void); - open_fcn_type open_f_ptr = reinterpret_cast - (dyn_libs.search ("openblas_get_config")); - - if (open_f_ptr) - { - if (! retval.empty ()) - retval += "\n"; + if (flexi_f_ptr) + { + int v_major = 0; + int v_minor = 0; + int v_patch = 0; + flexi_f_ptr (&v_major, &v_minor, &v_patch); - retval += "OpenBLAS (config: " + std::string (open_f_ptr ()) + ")"; - } - - // OpenBLAS with minimal extension functions included in the library - else if (dyn_libs.search ("openblas_get_num_threads")) - { - if (! retval.empty ()) - retval += "\n"; + std::ostringstream s; + s << "FlexiBLAS Version " + << v_major << "." << v_minor << "." << v_patch; - retval += "OpenBLAS (config: unknown)"; - } + retval = s.str (); + } - // GotoBLAS(2) - if (dyn_libs.search ("gotoblas_profile_init")) - { - if (! retval.empty ()) - retval += "\n"; + // OpenBLAS + typedef char *(*open_fcn_type) (void); + open_fcn_type open_f_ptr = reinterpret_cast + (dyn_libs.search ("openblas_get_config")); - retval += "GotoBLAS(2)"; - } + if (open_f_ptr) + { + if (! retval.empty ()) + retval += "\n"; - // ATLAS - // FIXME: If we are really interested, we could use a pipe to - // redirect the output of "ATL_buildinfo". - if (dyn_libs.search ("ATL_buildinfo")) - { - if (! retval.empty ()) - retval += "\n"; + retval += "OpenBLAS (config: " + std::string (open_f_ptr ()) + ")"; + } - retval += "ATLAS"; - } + // OpenBLAS with minimal extension functions included in the library + else if (dyn_libs.search ("openblas_get_num_threads")) + { + if (! retval.empty ()) + retval += "\n"; - // ACML - typedef void (*acml_f_type) (int *, int *, int *); - acml_f_type acml_f_ptr = reinterpret_cast - (dyn_libs.search ("acmlversion")); - - if (acml_f_ptr) - { - int v_major = 0; - int v_minor = 0; - int v_patch = 0; - acml_f_ptr (&v_major, &v_minor, &v_patch); + retval += "OpenBLAS (config: unknown)"; + } - std::ostringstream s; - s << "ACML BLAS Version " - << v_major << "." << v_minor << "." << v_patch; - - if (! retval.empty ()) - retval += "\n"; + // GotoBLAS(2) + if (dyn_libs.search ("gotoblas_profile_init")) + { + if (! retval.empty ()) + retval += "\n"; - retval += s.str (); - } - - // Intel MKL - typedef void (*mkl_f_type) (char *, int); - mkl_f_type mkl_f_ptr = reinterpret_cast - (dyn_libs.search ("mkl_get_version_string")); + retval += "GotoBLAS(2)"; + } - if (mkl_f_ptr) - { - char buf[198]; - int len = 198; - mkl_f_ptr (buf, len); - - if (! retval.empty ()) - retval += "\n"; + // ATLAS + // FIXME: If we are really interested, we could use a pipe to + // redirect the output of "ATL_buildinfo". + if (dyn_libs.search ("ATL_buildinfo")) + { + if (! retval.empty ()) + retval += "\n"; - retval += std::string (buf); - } - - // Otherwise - if (retval.empty ()) - retval = "unknown or reference BLAS"; - - return retval; + retval += "ATLAS"; } - std::string lapack_version (void) + // ACML + typedef void (*acml_f_type) (int *, int *, int *); + acml_f_type acml_f_ptr = reinterpret_cast + (dyn_libs.search ("acmlversion")); + + if (acml_f_ptr) { - std::string retval = "unknown LAPACK"; + int v_major = 0; + int v_minor = 0; + int v_patch = 0; + acml_f_ptr (&v_major, &v_minor, &v_patch); - dynamic_library dyn_libs (""); + std::ostringstream s; + s << "ACML BLAS Version " + << v_major << "." << v_minor << "." << v_patch; + + if (! retval.empty ()) + retval += "\n"; - if (! dyn_libs) - return retval; + retval += s.str (); + } + + // Intel MKL + typedef void (*mkl_f_type) (char *, int); + mkl_f_type mkl_f_ptr = reinterpret_cast + (dyn_libs.search ("mkl_get_version_string")); - // query LAPACK version - typedef F77_RET_T - (*ilaver_fcn_type) (const F77_INT&, const F77_INT&, const F77_INT&); - ilaver_fcn_type f_ptr = reinterpret_cast - (dyn_libs.search (STRINGIZE (F77_FUNC (ilaver, ILAVER)))); + if (mkl_f_ptr) + { + char buf[198]; + int len = 198; + mkl_f_ptr (buf, len); + + if (! retval.empty ()) + retval += "\n"; + + retval += std::string (buf); + } - if (f_ptr) - { - int v_major = 0; - int v_minor = 0; - int v_patch = 0; - f_ptr (v_major, v_minor, v_patch); + // Otherwise + if (retval.empty ()) + retval = "unknown or reference BLAS"; + + return retval; +} + +std::string lapack_version (void) +{ + std::string retval = "unknown LAPACK"; + + dynamic_library dyn_libs (""); + + if (! dyn_libs) + return retval; - std::ostringstream s; - s << "Linear Algebra PACKage Version " - << v_major << "." << v_minor << "." << v_patch; + // query LAPACK version + typedef F77_RET_T + (*ilaver_fcn_type) (const F77_INT&, const F77_INT&, const F77_INT&); + ilaver_fcn_type f_ptr = reinterpret_cast + (dyn_libs.search (STRINGIZE (F77_FUNC (ilaver, ILAVER)))); - retval = s.str (); - } + if (f_ptr) + { + int v_major = 0; + int v_minor = 0; + int v_patch = 0; + f_ptr (v_major, v_minor, v_patch); - return retval; + std::ostringstream s; + s << "Linear Algebra PACKage Version " + << v_major << "." << v_minor << "." << v_patch; + + retval = s.str (); } + return retval; +} + OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/lo-sysinfo.h --- a/liboctave/system/lo-sysinfo.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/lo-sysinfo.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,9 +34,9 @@ OCTAVE_BEGIN_NAMESPACE(sys) - extern OCTAVE_API std::string blas_version (void); +extern OCTAVE_API std::string blas_version (void); - extern OCTAVE_API std::string lapack_version (void); +extern OCTAVE_API std::string lapack_version (void); OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/mach-info.cc --- a/liboctave/system/mach-info.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/mach-info.cc Thu Dec 01 20:05:44 2022 -0800 @@ -42,86 +42,86 @@ OCTAVE_BEGIN_NAMESPACE(mach_info) - static float_format get_float_format (void) +static float_format get_float_format (void) +{ + switch (octave_get_float_format ()) { - switch (octave_get_float_format ()) - { - case 1: - return flt_fmt_ieee_little_endian; + case 1: + return flt_fmt_ieee_little_endian; + + case 2: + return flt_fmt_ieee_big_endian; + + default: + return flt_fmt_unknown; + } +} - case 2: - return flt_fmt_ieee_big_endian; +static bool is_big_endian (void) +{ + return octave_is_big_endian (); +} + +float_format native_float_format (void) +{ + static float_format fmt = get_float_format (); - default: - return flt_fmt_unknown; - } - } + return fmt; +} + +bool words_big_endian (void) +{ + static bool big_endian = is_big_endian (); + + return big_endian; +} + +bool words_little_endian (void) +{ + static bool little_endian = ! is_big_endian (); - static bool is_big_endian (void) - { - return octave_is_big_endian (); - } + return little_endian; +} + +float_format string_to_float_format (const std::string& s) +{ + float_format retval = flt_fmt_unknown; - float_format native_float_format (void) - { - static float_format fmt = get_float_format (); + if (s == "native" || s == "n") + retval = native_float_format (); + else if (s == "ieee-be" || s == "b") + retval = flt_fmt_ieee_big_endian; + else if (s == "ieee-le" || s == "l") + retval = flt_fmt_ieee_little_endian; + else if (s == "unknown") + retval = flt_fmt_unknown; + else + (*current_liboctave_error_handler) + ("invalid architecture type specified"); - return fmt; - } + return retval; +} + +std::string float_format_as_string (float_format flt_fmt) +{ + std::string retval = "unknown"; - bool words_big_endian (void) + switch (flt_fmt) { - static bool big_endian = is_big_endian (); + case flt_fmt_ieee_big_endian: + retval = "ieee-be"; + break; - return big_endian; + case flt_fmt_ieee_little_endian: + retval = "ieee-le"; + break; + + default: + break; } - bool words_little_endian (void) - { - static bool little_endian = ! is_big_endian (); - - return little_endian; - } - - float_format string_to_float_format (const std::string& s) - { - float_format retval = flt_fmt_unknown; - - if (s == "native" || s == "n") - retval = native_float_format (); - else if (s == "ieee-be" || s == "b") - retval = flt_fmt_ieee_big_endian; - else if (s == "ieee-le" || s == "l") - retval = flt_fmt_ieee_little_endian; - else if (s == "unknown") - retval = flt_fmt_unknown; - else - (*current_liboctave_error_handler) - ("invalid architecture type specified"); - - return retval; - } - - std::string float_format_as_string (float_format flt_fmt) - { - std::string retval = "unknown"; - - switch (flt_fmt) - { - case flt_fmt_ieee_big_endian: - retval = "ieee-be"; - break; - - case flt_fmt_ieee_little_endian: - retval = "ieee-le"; - break; - - default: - break; - } - - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(mach_info) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/mach-info.h --- a/liboctave/system/mach-info.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/mach-info.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,25 +34,25 @@ OCTAVE_BEGIN_NAMESPACE(mach_info) - enum float_format - { - // If these values change, you must also change the values - // returned by octave_get_float_format. +enum float_format +{ + // If these values change, you must also change the values + // returned by octave_get_float_format. - flt_fmt_unknown = 0, - flt_fmt_ieee_little_endian = 1, - flt_fmt_ieee_big_endian = 2, - }; + flt_fmt_unknown = 0, + flt_fmt_ieee_little_endian = 1, + flt_fmt_ieee_big_endian = 2, +}; - OCTAVE_API float_format native_float_format (void); +OCTAVE_API float_format native_float_format (void); - OCTAVE_API bool words_big_endian (void); +OCTAVE_API bool words_big_endian (void); - OCTAVE_API bool words_little_endian (void); +OCTAVE_API bool words_little_endian (void); - OCTAVE_API float_format string_to_float_format (const std::string&); +OCTAVE_API float_format string_to_float_format (const std::string&); - OCTAVE_API std::string float_format_as_string (float_format); +OCTAVE_API std::string float_format_as_string (float_format); OCTAVE_END_NAMESPACE(mach_info) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-env.cc --- a/liboctave/system/oct-env.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-env.cc Thu Dec 01 20:05:44 2022 -0800 @@ -69,611 +69,611 @@ OCTAVE_BEGIN_NAMESPACE(sys) - env::env (void) - : m_follow_symbolic_links (true), m_verbatim_pwd (true), - m_current_directory (), m_prog_name (), m_prog_invocation_name (), - m_user_name (), m_host_name () - { - // Get a real value for the current directory. - do_getcwd (); - - // Etc. - do_get_user_name (); - - do_get_host_name (); - } +env::env (void) + : m_follow_symbolic_links (true), m_verbatim_pwd (true), + m_current_directory (), m_prog_name (), m_prog_invocation_name (), + m_user_name (), m_host_name () +{ + // Get a real value for the current directory. + do_getcwd (); - env *env::m_instance = nullptr; - - bool - env::instance_ok (void) - { - bool retval = true; - - if (! m_instance) - { - m_instance = new env (); - singleton_cleanup_list::add (cleanup_instance); - } - - return retval; - } + // Etc. + do_get_user_name (); - std::string - env::polite_directory_format (const std::string& name) - { - return (instance_ok ()) - ? m_instance->do_polite_directory_format (name) : ""; - } + do_get_host_name (); +} + +env *env::m_instance = nullptr; - bool - env::absolute_pathname (const std::string& s) - { - return (instance_ok ()) - ? m_instance->do_absolute_pathname (s) : false; - } +bool +env::instance_ok (void) +{ + bool retval = true; - bool - env::rooted_relative_pathname (const std::string& s) + if (! m_instance) { - return (instance_ok ()) - ? m_instance->do_rooted_relative_pathname (s) : false; - } - - std::string - env::base_pathname (const std::string& s) - { - return (instance_ok ()) - ? m_instance->do_base_pathname (s) : ""; - } - - std::string - env::make_absolute (const std::string& s, const std::string& dot_path) - { - return (instance_ok ()) - ? m_instance->do_make_absolute (s, dot_path) : ""; + m_instance = new env (); + singleton_cleanup_list::add (cleanup_instance); } - std::string - env::get_current_directory () - { - return (instance_ok ()) - ? m_instance->do_getcwd () : ""; - } + return retval; +} + +std::string +env::polite_directory_format (const std::string& name) +{ + return (instance_ok ()) + ? m_instance->do_polite_directory_format (name) : ""; +} - std::string - env::get_home_directory () - { - return (instance_ok ()) - ? m_instance->do_get_home_directory () : ""; - } +bool +env::absolute_pathname (const std::string& s) +{ + return (instance_ok ()) + ? m_instance->do_absolute_pathname (s) : false; +} + +bool +env::rooted_relative_pathname (const std::string& s) +{ + return (instance_ok ()) + ? m_instance->do_rooted_relative_pathname (s) : false; +} - std::string - env::get_temp_directory () - { - return (instance_ok ()) - ? m_instance->do_get_temp_directory () : ""; - } +std::string +env::base_pathname (const std::string& s) +{ + return (instance_ok ()) + ? m_instance->do_base_pathname (s) : ""; +} + +std::string +env::make_absolute (const std::string& s, const std::string& dot_path) +{ + return (instance_ok ()) + ? m_instance->do_make_absolute (s, dot_path) : ""; +} - std::string - env::get_user_config_directory () - { - return (instance_ok ()) - ? m_instance->do_get_user_config_directory () : ""; - } +std::string +env::get_current_directory () +{ + return (instance_ok ()) + ? m_instance->do_getcwd () : ""; +} - std::string - env::get_user_data_directory () - { - return (instance_ok ()) - ? m_instance->do_get_user_data_directory () : ""; - } +std::string +env::get_home_directory () +{ + return (instance_ok ()) + ? m_instance->do_get_home_directory () : ""; +} - std::string - env::get_program_name (void) - { - return (instance_ok ()) - ? m_instance->m_prog_name : ""; - } +std::string +env::get_temp_directory () +{ + return (instance_ok ()) + ? m_instance->do_get_temp_directory () : ""; +} + +std::string +env::get_user_config_directory () +{ + return (instance_ok ()) + ? m_instance->do_get_user_config_directory () : ""; +} - std::string - env::get_program_invocation_name (void) - { - return (instance_ok ()) - ? m_instance->m_prog_invocation_name : ""; - } +std::string +env::get_user_data_directory () +{ + return (instance_ok ()) + ? m_instance->do_get_user_data_directory () : ""; +} + +std::string +env::get_program_name (void) +{ + return (instance_ok ()) + ? m_instance->m_prog_name : ""; +} - void - env::set_program_name (const std::string& s) - { - if (instance_ok ()) - m_instance->do_set_program_name (s); - } +std::string +env::get_program_invocation_name (void) +{ + return (instance_ok ()) + ? m_instance->m_prog_invocation_name : ""; +} + +void +env::set_program_name (const std::string& s) +{ + if (instance_ok ()) + m_instance->do_set_program_name (s); +} - std::string - env::get_user_name (void) - { - return (instance_ok ()) - ? m_instance->do_get_user_name () : ""; - } +std::string +env::get_user_name (void) +{ + return (instance_ok ()) + ? m_instance->do_get_user_name () : ""; +} - std::string - env::get_host_name (void) - { - return (instance_ok ()) - ? m_instance->do_get_host_name () : ""; - } +std::string +env::get_host_name (void) +{ + return (instance_ok ()) + ? m_instance->do_get_host_name () : ""; +} - std::string - env::do_get_temp_directory (void) const - { - std::string tempd = do_getenv ("TMPDIR"); +std::string +env::do_get_temp_directory (void) const +{ + std::string tempd = do_getenv ("TMPDIR"); #if defined (__MINGW32__) || defined (_MSC_VER) - if (tempd.empty ()) - tempd = do_getenv ("TEMP"); + if (tempd.empty ()) + tempd = do_getenv ("TEMP"); - if (tempd.empty ()) - tempd = do_getenv ("TMP"); + if (tempd.empty ()) + tempd = do_getenv ("TMP"); #if defined (P_tmpdir) - if (tempd.empty ()) - tempd = P_tmpdir; + if (tempd.empty ()) + tempd = P_tmpdir; #endif - // Some versions of MinGW and MSVC either don't define P_tmpdir, or - // define it to a single backslash. In such cases just use C:\temp. - if (tempd.empty () || tempd == R"(\)") - tempd = R"(c:\temp)"; + // Some versions of MinGW and MSVC either don't define P_tmpdir, or + // define it to a single backslash. In such cases just use C:\temp. + if (tempd.empty () || tempd == R"(\)") + tempd = R"(c:\temp)"; #else - if (tempd.empty ()) - tempd = do_getenv ("TMP"); + if (tempd.empty ()) + tempd = do_getenv ("TMP"); #if defined (P_tmpdir) - if (tempd.empty ()) - tempd = P_tmpdir; + if (tempd.empty ()) + tempd = P_tmpdir; #else - if (tempd.empty ()) - tempd = "/tmp"; + if (tempd.empty ()) + tempd = "/tmp"; #endif #endif - return tempd; - } + return tempd; +} - std::string - env::do_get_user_config_directory (void) - { - std::string cfg_dir; +std::string +env::do_get_user_config_directory (void) +{ + std::string cfg_dir; #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && defined (OCTAVE_USE_WINDOWS_API) - wchar_t path[MAX_PATH+1]; - if (SHGetFolderPathW (nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, - nullptr, SHGFP_TYPE_CURRENT, path) == S_OK) - cfg_dir = u8_from_wstring (path); + wchar_t path[MAX_PATH+1]; + if (SHGetFolderPathW (nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, + nullptr, SHGFP_TYPE_CURRENT, path) == S_OK) + cfg_dir = u8_from_wstring (path); #else - cfg_dir = do_getenv ("XDG_CONFIG_HOME"); + cfg_dir = do_getenv ("XDG_CONFIG_HOME"); #endif - if (cfg_dir.empty ()) - cfg_dir = do_get_home_directory () + sys::file_ops::dir_sep_str () - + ".config"; + if (cfg_dir.empty ()) + cfg_dir = do_get_home_directory () + sys::file_ops::dir_sep_str () + + ".config"; - return cfg_dir; - } + return cfg_dir; +} - std::string - env::do_get_user_data_directory (void) - { - std::string data_dir; +std::string +env::do_get_user_data_directory (void) +{ + std::string data_dir; #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) && defined (OCTAVE_USE_WINDOWS_API) - wchar_t path[MAX_PATH+1]; - if (SHGetFolderPathW (nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, - nullptr, SHGFP_TYPE_CURRENT, path) == S_OK) - data_dir = u8_from_wstring (path); + wchar_t path[MAX_PATH+1]; + if (SHGetFolderPathW (nullptr, CSIDL_APPDATA | CSIDL_FLAG_DONT_VERIFY, + nullptr, SHGFP_TYPE_CURRENT, path) == S_OK) + data_dir = u8_from_wstring (path); #else - data_dir = do_getenv ("XDG_DATA_HOME"); + data_dir = do_getenv ("XDG_DATA_HOME"); #endif - if (data_dir.empty ()) - data_dir = do_get_home_directory () + sys::file_ops::dir_sep_str () - + ".local" + sys::file_ops::dir_sep_str () + "share"; + if (data_dir.empty ()) + data_dir = do_get_home_directory () + sys::file_ops::dir_sep_str () + + ".local" + sys::file_ops::dir_sep_str () + "share"; - return data_dir; - } + return data_dir; +} - // FIXME: this leaves no way to distinguish between a - // variable that is not set and one that is set to the empty string. - // Is this a problem? +// FIXME: this leaves no way to distinguish between a +// variable that is not set and one that is set to the empty string. +// Is this a problem? + +std::string +env::getenv (const std::string& name) +{ + return (instance_ok ()) + ? m_instance->do_getenv (name) : ""; +} + +void +env::putenv (const std::string& name, const std::string& value) +{ + putenv_wrapper (name, value); +} - std::string - env::getenv (const std::string& name) - { - return (instance_ok ()) - ? m_instance->do_getenv (name) : ""; - } +bool +env::have_x11_display (void) +{ + std::string display = getenv ("DISPLAY"); + + return ! display.empty (); +} - void - env::putenv (const std::string& name, const std::string& value) +bool +env::chdir (const std::string& newdir) +{ + return (instance_ok ()) + ? m_instance->do_chdir (newdir) : false; +} + +void +env::do_set_program_name (const std::string& s) +{ + static bool initialized = false; + + if (! initialized) { - putenv_wrapper (name, value); - } + // octave_set_program_name_wrapper returns a cleaned up + // version of the program name (stripping libtool's "lt-" + // prefix, for example). + + // The string passed to gnulib's ::set_program_name function must + // exist for the duration of the program so allocate a copy here + // instead of passing S.c_str () which only exists as long as the + // string object S. + + m_prog_invocation_name + = octave_set_program_name_wrapper (strsave (s.c_str ())); + + std::size_t pos + = m_prog_invocation_name.find_last_of (sys::file_ops::dir_sep_chars ()); - bool - env::have_x11_display (void) - { - std::string display = getenv ("DISPLAY"); + // Also keep a shortened version of the program name. + m_prog_name = (pos == std::string::npos + ? m_prog_invocation_name + : m_prog_invocation_name.substr (pos+1)); + + initialized = true; + } +} + +// Return a pretty pathname. If the first part of the pathname is the +// same as $HOME, then replace that with '~'. - return ! display.empty (); - } +std::string +env::do_polite_directory_format (const std::string& name) +{ + std::string retval; - bool - env::chdir (const std::string& newdir) + std::string home_dir = do_get_home_directory (); + + std::size_t len = home_dir.length (); + + if (len > 1 && home_dir == name.substr (0, len) + && (name.length () == len || sys::file_ops::is_dir_sep (name[len]))) { - return (instance_ok ()) - ? m_instance->do_chdir (newdir) : false; + retval = "~"; + retval.append (name.substr (len)); } + else + retval = name; + + return retval; +} + +bool +env::do_absolute_pathname (const std::string& s) const +{ + std::size_t len = s.length (); + + if (len == 0) + return false; + + if (sys::file_ops::is_dir_sep (s[0])) + return true; + +#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) + if ((len == 2 && isalpha (s[0]) && s[1] == ':') + || (len > 2 && isalpha (s[0]) && s[1] == ':' + && sys::file_ops::is_dir_sep (s[2]))) + return true; +#endif + + return false; +} - void - env::do_set_program_name (const std::string& s) - { - static bool initialized = false; +bool +env::do_rooted_relative_pathname (const std::string& s) const +{ + std::size_t len = s.length (); + + if (len == 0) + return false; + + if (len == 1 && s[0] == '.') + return true; + + if (len > 1 && s[0] == '.' && sys::file_ops::is_dir_sep (s[1])) + return true; + + if (len == 2 && s[0] == '.' && s[1] == '.') + return true; - if (! initialized) - { - // octave_set_program_name_wrapper returns a cleaned up - // version of the program name (stripping libtool's "lt-" - // prefix, for example). + if (len > 2 && s[0] == '.' && s[1] == '.' + && sys::file_ops::is_dir_sep (s[2])) + return true; + + return false; +} + +// Return the 'basename' of the pathname in STRING (the stuff after +// the last directory separator). If STRING is not a full pathname, +// simply return it. + +std::string +env::do_base_pathname (const std::string& s) const +{ + if (! (do_absolute_pathname (s) || do_rooted_relative_pathname (s))) + return s; + + std::size_t pos = s.find_last_of (sys::file_ops::dir_sep_chars ()); - // The string passed to gnulib's ::set_program_name function must - // exist for the duration of the program so allocate a copy here - // instead of passing S.c_str () which only exists as long as the - // string object S. + if (pos == std::string::npos) + return s; + else + return s.substr (pos+1); +} + +// Turn STRING (a pathname) into an absolute pathname, assuming that +// DOT_PATH contains the symbolic location of the current directory. + +std::string +env::do_make_absolute (const std::string& s, + const std::string& dot_path) const +{ + if (dot_path.empty () || s.empty () || do_absolute_pathname (s)) + return s; - m_prog_invocation_name - = octave_set_program_name_wrapper (strsave (s.c_str ())); + // Optimization: every time Octave returns to the prompt it calls + // make_absolute_filename with '.' as argument. + if (s == ".") + return dot_path; + + std::string current_dir = dot_path; + + if (! sys::file_ops::is_dir_sep (current_dir.back ())) + current_dir.append (sys::file_ops::dir_sep_str ()); + + std::size_t i = 0; + std::size_t slen = s.length (); + + while (i < slen) + { + if (s[i] == '.') + { + if (i + 1 == slen) + break; - std::size_t pos - = m_prog_invocation_name.find_last_of (sys::file_ops::dir_sep_chars ()); + if (sys::file_ops::is_dir_sep (s[i+1])) + { + i += 2; + continue; + } + + if (s[i+1] == '.' + && (i + 2 == slen + || sys::file_ops::is_dir_sep (s[i+2]))) + { + i += 2; + if (i != slen) + i++; + + pathname_backup (current_dir, 1); - // Also keep a shortened version of the program name. - m_prog_name = (pos == std::string::npos - ? m_prog_invocation_name - : m_prog_invocation_name.substr (pos+1)); + continue; + } + } + + std::size_t sep_pos; + sep_pos = s.find_first_of (sys::file_ops::dir_sep_chars (), i); - initialized = true; + if (sep_pos == std::string::npos) + { + current_dir.append (s, i, sep_pos-i); + break; + } + else if (sep_pos == i) + { + /* Two separators in a row, skip adding 2nd separator */ + i++; + } + else + { + current_dir.append (s, i, sep_pos-i+1); + i = sep_pos + 1; } } - // Return a pretty pathname. If the first part of the pathname is the - // same as $HOME, then replace that with '~'. + // Strip any trailing directory separator + if (sys::file_ops::is_dir_sep (current_dir.back ())) + current_dir.pop_back (); + + return current_dir; +} + +// Return a string which is the current working directory. - std::string - env::do_polite_directory_format (const std::string& name) - { - std::string retval; +std::string +env::do_getcwd (void) +{ + if (! m_follow_symbolic_links) + m_current_directory = ""; + + if (m_verbatim_pwd || m_current_directory.empty ()) + m_current_directory = sys::getcwd (); - std::string home_dir = do_get_home_directory (); + return m_current_directory; +} - std::size_t len = home_dir.length (); +// This value is not cached because it can change while Octave is +// running. - if (len > 1 && home_dir == name.substr (0, len) - && (name.length () == len || sys::file_ops::is_dir_sep (name[len]))) - { - retval = "~"; - retval.append (name.substr (len)); - } +std::string +env::do_get_home_directory (void) +{ + std::string hd = do_getenv ("HOME"); + +#if defined (__MINGW32__) || defined (_MSC_VER) + // Maybe we are started directly from cmd.exe. + if (hd.empty ()) + { + std::string drv = do_getenv ("HOMEDRIVE"); + if (drv.empty ()) + hd = do_getenv ("HOMEPATH"); else - retval = name; - - return retval; + hd = drv + do_getenv ("HOMEPATH"); } - - bool - env::do_absolute_pathname (const std::string& s) const - { - std::size_t len = s.length (); - - if (len == 0) - return false; - - if (sys::file_ops::is_dir_sep (s[0])) - return true; - -#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) - if ((len == 2 && isalpha (s[0]) && s[1] == ':') - || (len > 2 && isalpha (s[0]) && s[1] == ':' - && sys::file_ops::is_dir_sep (s[2]))) - return true; #endif - return false; + if (hd.empty ()) + { + sys::password pw = sys::password::getpwuid (sys::getuid ()); + + hd = (pw ? pw.dir () : std::string (sys::file_ops::dir_sep_str ())); } - bool - env::do_rooted_relative_pathname (const std::string& s) const - { - std::size_t len = s.length (); - - if (len == 0) - return false; - - if (len == 1 && s[0] == '.') - return true; - - if (len > 1 && s[0] == '.' && sys::file_ops::is_dir_sep (s[1])) - return true; - - if (len == 2 && s[0] == '.' && s[1] == '.') - return true; + return hd; +} - if (len > 2 && s[0] == '.' && s[1] == '.' - && sys::file_ops::is_dir_sep (s[2])) - return true; - - return false; - } - - // Return the 'basename' of the pathname in STRING (the stuff after - // the last directory separator). If STRING is not a full pathname, - // simply return it. +std::string +env::do_get_user_name (void) +{ + if (m_user_name.empty ()) + { + sys::password pw = sys::password::getpwuid (sys::getuid ()); - std::string - env::do_base_pathname (const std::string& s) const - { - if (! (do_absolute_pathname (s) || do_rooted_relative_pathname (s))) - return s; - - std::size_t pos = s.find_last_of (sys::file_ops::dir_sep_chars ()); - - if (pos == std::string::npos) - return s; - else - return s.substr (pos+1); + m_user_name = (pw ? pw.name () : "unknown"); } - // Turn STRING (a pathname) into an absolute pathname, assuming that - // DOT_PATH contains the symbolic location of the current directory. - - std::string - env::do_make_absolute (const std::string& s, - const std::string& dot_path) const - { - if (dot_path.empty () || s.empty () || do_absolute_pathname (s)) - return s; - - // Optimization: every time Octave returns to the prompt it calls - // make_absolute_filename with '.' as argument. - if (s == ".") - return dot_path; - - std::string current_dir = dot_path; - - if (! sys::file_ops::is_dir_sep (current_dir.back ())) - current_dir.append (sys::file_ops::dir_sep_str ()); - - std::size_t i = 0; - std::size_t slen = s.length (); - - while (i < slen) - { - if (s[i] == '.') - { - if (i + 1 == slen) - break; - - if (sys::file_ops::is_dir_sep (s[i+1])) - { - i += 2; - continue; - } + return m_user_name; +} - if (s[i+1] == '.' - && (i + 2 == slen - || sys::file_ops::is_dir_sep (s[i+2]))) - { - i += 2; - if (i != slen) - i++; - - pathname_backup (current_dir, 1); - - continue; - } - } - - std::size_t sep_pos; - sep_pos = s.find_first_of (sys::file_ops::dir_sep_chars (), i); +std::string +env::do_get_host_name (void) +{ + if (m_host_name.empty ()) + { + char hostname[1024]; - if (sep_pos == std::string::npos) - { - current_dir.append (s, i, sep_pos-i); - break; - } - else if (sep_pos == i) - { - /* Two separators in a row, skip adding 2nd separator */ - i++; - } - else - { - current_dir.append (s, i, sep_pos-i+1); - i = sep_pos + 1; - } - } + int status = octave_gethostname_wrapper (hostname, 1023); - // Strip any trailing directory separator - if (sys::file_ops::is_dir_sep (current_dir.back ())) - current_dir.pop_back (); - - return current_dir; + m_host_name = (status < 0) ? "unknown" : hostname; } - // Return a string which is the current working directory. + return m_host_name; +} + +std::string +env::do_getenv (const std::string& name) const +{ + return getenv_wrapper (name); +} - std::string - env::do_getcwd (void) +// Do the work of changing to the directory NEWDIR. +// Handle symbolic link following, etc. + +bool +env::do_chdir (const std::string& newdir) +{ + bool retval = false; + + std::string tmp; + + if (m_follow_symbolic_links) { - if (! m_follow_symbolic_links) - m_current_directory = ""; + if (m_current_directory.empty ()) + do_getcwd (); - if (m_verbatim_pwd || m_current_directory.empty ()) - m_current_directory = sys::getcwd (); + if (m_current_directory.empty ()) + tmp = newdir; + else + tmp = do_make_absolute (newdir, m_current_directory); - return m_current_directory; - } + // Get rid of trailing directory separator. + if (tmp.length () > 1 && sys::file_ops::is_dir_sep (tmp.back ())) + tmp.pop_back (); - // This value is not cached because it can change while Octave is - // running. + if (! sys::chdir (tmp)) + { + m_current_directory = tmp; + retval = true; + } + } + else + retval = (! sys::chdir (newdir)); - std::string - env::do_get_home_directory (void) - { - std::string hd = do_getenv ("HOME"); + return retval; +} + +// Remove the last N directories from PATH. -#if defined (__MINGW32__) || defined (_MSC_VER) - // Maybe we are started directly from cmd.exe. - if (hd.empty ()) +void +env::pathname_backup (std::string& path, int n) const +{ + if (path.empty ()) + return; + + std::size_t i = path.length () - 1; + + while (n--) + { + while (sys::file_ops::is_dir_sep (path[i]) && i > 0) + i--; + +#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) + // Don't strip file letter part. + if (i == 1 && path[i] == ':') { - std::string drv = do_getenv ("HOMEDRIVE"); - if (drv.empty ()) - hd = do_getenv ("HOMEPATH"); - else - hd = drv + do_getenv ("HOMEPATH"); + // Keep path separator if present. + i = std::min (i+2, path.length ()); + break; } #endif - if (hd.empty ()) - { - sys::password pw = sys::password::getpwuid (sys::getuid ()); - - hd = (pw ? pw.dir () : std::string (sys::file_ops::dir_sep_str ())); - } - - return hd; - } - - std::string - env::do_get_user_name (void) - { - if (m_user_name.empty ()) - { - sys::password pw = sys::password::getpwuid (sys::getuid ()); - - m_user_name = (pw ? pw.name () : "unknown"); - } + while (! sys::file_ops::is_dir_sep (path[i]) && i > 0) + i--; - return m_user_name; - } - - std::string - env::do_get_host_name (void) - { - if (m_host_name.empty ()) - { - char hostname[1024]; - - int status = octave_gethostname_wrapper (hostname, 1023); - - m_host_name = (status < 0) ? "unknown" : hostname; - } - - return m_host_name; - } - - std::string - env::do_getenv (const std::string& name) const - { - return getenv_wrapper (name); + i++; } - // Do the work of changing to the directory NEWDIR. - // Handle symbolic link following, etc. - - bool - env::do_chdir (const std::string& newdir) - { - bool retval = false; - - std::string tmp; - - if (m_follow_symbolic_links) - { - if (m_current_directory.empty ()) - do_getcwd (); - - if (m_current_directory.empty ()) - tmp = newdir; - else - tmp = do_make_absolute (newdir, m_current_directory); - - // Get rid of trailing directory separator. - if (tmp.length () > 1 && sys::file_ops::is_dir_sep (tmp.back ())) - tmp.pop_back (); - - if (! sys::chdir (tmp)) - { - m_current_directory = tmp; - retval = true; - } - } - else - retval = (! sys::chdir (newdir)); - - return retval; - } - - // Remove the last N directories from PATH. + path.resize (i); +} - void - env::pathname_backup (std::string& path, int n) const - { - if (path.empty ()) - return; - - std::size_t i = path.length () - 1; - - while (n--) - { - while (sys::file_ops::is_dir_sep (path[i]) && i > 0) - i--; +void +env::error (int err_num) const +{ + (*current_liboctave_error_handler) ("%s", std::strerror (err_num)); +} -#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) - // Don't strip file letter part. - if (i == 1 && path[i] == ':') - { - // Keep path separator if present. - i = std::min (i+2, path.length ()); - break; - } -#endif - - while (! sys::file_ops::is_dir_sep (path[i]) && i > 0) - i--; - - i++; - } - - path.resize (i); - } - - void - env::error (int err_num) const - { - (*current_liboctave_error_handler) ("%s", std::strerror (err_num)); - } - - void - env::error (const std::string& s) const - { - (*current_liboctave_error_handler) ("%s", s.c_str ()); - } +void +env::error (const std::string& s) const +{ + (*current_liboctave_error_handler) ("%s", s.c_str ()); +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-env.h --- a/liboctave/system/oct-env.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-env.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,131 +34,131 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class - OCTAVE_API - env - { - protected: +class +OCTAVE_API +env +{ +protected: - env (void); + env (void); - public: +public: - // No copying! + // No copying! - env (const env&) = delete; + env (const env&) = delete; - env& operator = (const env&) = delete; + env& operator = (const env&) = delete; - static std::string polite_directory_format (const std::string& name); + static std::string polite_directory_format (const std::string& name); - static bool absolute_pathname (const std::string& s); + static bool absolute_pathname (const std::string& s); - static bool rooted_relative_pathname (const std::string& s); + static bool rooted_relative_pathname (const std::string& s); - static std::string base_pathname (const std::string& s); + static std::string base_pathname (const std::string& s); - static std::string - make_absolute (const std::string& s, - const std::string& dot_path = get_current_directory ()); + static std::string + make_absolute (const std::string& s, + const std::string& dot_path = get_current_directory ()); - static std::string get_current_directory (void); + static std::string get_current_directory (void); - static std::string get_home_directory (void); + static std::string get_home_directory (void); - static std::string get_temp_directory (void); + static std::string get_temp_directory (void); - static std::string get_user_config_directory (void); + static std::string get_user_config_directory (void); - static std::string get_user_data_directory (void); + static std::string get_user_data_directory (void); - static std::string get_program_name (void); + static std::string get_program_name (void); - static std::string get_program_invocation_name (void); + static std::string get_program_invocation_name (void); - static std::string get_user_name (void); + static std::string get_user_name (void); - static std::string get_host_name (void); + static std::string get_host_name (void); - static std::string getenv (const std::string& name); + static std::string getenv (const std::string& name); - static void putenv (const std::string& name, const std::string& value); + static void putenv (const std::string& name, const std::string& value); - static bool have_x11_display (void); + static bool have_x11_display (void); - static bool chdir (const std::string& newdir); + static bool chdir (const std::string& newdir); - static void set_program_name (const std::string& s); + static void set_program_name (const std::string& s); - private: +private: - static bool instance_ok (void); + static bool instance_ok (void); - std::string do_polite_directory_format (const std::string& name); + std::string do_polite_directory_format (const std::string& name); - bool do_absolute_pathname (const std::string& s) const; + bool do_absolute_pathname (const std::string& s) const; - bool do_rooted_relative_pathname (const std::string& s) const; + bool do_rooted_relative_pathname (const std::string& s) const; - std::string do_base_pathname (const std::string& s) const; + std::string do_base_pathname (const std::string& s) const; - std::string do_make_absolute (const std::string& s, - const std::string& dot_path) const; + std::string do_make_absolute (const std::string& s, + const std::string& dot_path) const; - std::string do_getcwd (void); + std::string do_getcwd (void); - std::string do_get_home_directory (void); + std::string do_get_home_directory (void); - std::string do_get_temp_directory (void) const; + std::string do_get_temp_directory (void) const; - std::string do_get_user_config_directory (void); + std::string do_get_user_config_directory (void); - std::string do_get_user_data_directory (void); + std::string do_get_user_data_directory (void); - std::string do_get_user_name (void); + std::string do_get_user_name (void); - std::string do_get_host_name (void); + std::string do_get_host_name (void); - std::string do_getenv (const std::string& name) const; + std::string do_getenv (const std::string& name) const; - void do_putenv (const std::string& name, const std::string& value) const; + void do_putenv (const std::string& name, const std::string& value) const; - bool do_chdir (const std::string& newdir); + bool do_chdir (const std::string& newdir); - void do_set_program_name (const std::string& s); + void do_set_program_name (const std::string& s); - void pathname_backup (std::string& path, int n) const; + void pathname_backup (std::string& path, int n) const; - void error (int) const; + void error (int) const; - void error (const std::string&) const; + void error (const std::string&) const; - // The real thing. - static env *m_instance; + // The real thing. + static env *m_instance; - static void cleanup_instance (void) - { delete m_instance; m_instance = nullptr; } + static void cleanup_instance (void) + { delete m_instance; m_instance = nullptr; } - // TRUE means follow symbolic links that point to directories just - // as if they are real directories. - bool m_follow_symbolic_links; + // TRUE means follow symbolic links that point to directories just + // as if they are real directories. + bool m_follow_symbolic_links; - // TRUE means that pwd always give verbatim directory, regardless - // of symbolic link following. - bool m_verbatim_pwd; + // TRUE means that pwd always give verbatim directory, regardless + // of symbolic link following. + bool m_verbatim_pwd; - // Where are we? - std::string m_current_directory; + // Where are we? + std::string m_current_directory; - // Etc. - std::string m_prog_name; + // Etc. + std::string m_prog_name; - std::string m_prog_invocation_name; + std::string m_prog_invocation_name; - std::string m_user_name; + std::string m_user_name; - std::string m_host_name; - }; + std::string m_host_name; +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-group.cc --- a/liboctave/system/oct-group.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-group.cc Thu Dec 01 20:05:44 2022 -0800 @@ -51,188 +51,188 @@ OCTAVE_BEGIN_NAMESPACE(sys) - std::string - group::name (void) const - { - if (! ok ()) - err_invalid (); +std::string +group::name (void) const +{ + if (! ok ()) + err_invalid (); - return m_name; - } + return m_name; +} - std::string - group::passwd (void) const - { - if (! ok ()) - err_invalid (); +std::string +group::passwd (void) const +{ + if (! ok ()) + err_invalid (); - return m_passwd; - } + return m_passwd; +} - gid_t - group::gid (void) const - { - if (! ok ()) - err_invalid (); +gid_t +group::gid (void) const +{ + if (! ok ()) + err_invalid (); - return m_gid; - } + return m_gid; +} - string_vector - group::mem (void) const - { - if (! ok ()) - err_invalid (); +string_vector +group::mem (void) const +{ + if (! ok ()) + err_invalid (); - return m_mem; - } + return m_mem; +} - group - group::getgrent (void) - { - std::string msg; - return getgrent (msg); - } +group +group::getgrent (void) +{ + std::string msg; + return getgrent (msg); +} - group - group::getgrent (std::string& msg) - { +group +group::getgrent (std::string& msg) +{ #if defined (HAVE_GETGRENT) - msg = ""; - return group (::getgrent (), msg); + msg = ""; + return group (::getgrent (), msg); #else - msg = NOT_SUPPORTED ("getgrent"); - return group (); + msg = NOT_SUPPORTED ("getgrent"); + return group (); #endif - } +} - group - group::getgrgid (gid_t gid) - { - std::string msg; - return getgrgid (gid, msg); - } +group +group::getgrgid (gid_t gid) +{ + std::string msg; + return getgrgid (gid, msg); +} - group - group::getgrgid (gid_t gid, std::string& msg) - { +group +group::getgrgid (gid_t gid, std::string& msg) +{ #if defined (HAVE_GETGRGID) - msg = ""; - return group (::getgrgid (gid), msg); + msg = ""; + return group (::getgrgid (gid), msg); #else - octave_unused_parameter (gid); + octave_unused_parameter (gid); - msg = NOT_SUPPORTED ("getgruid"); - return group (); + msg = NOT_SUPPORTED ("getgruid"); + return group (); #endif - } +} - group - group::getgrnam (const std::string& nm) - { - std::string msg; - return getgrnam (nm, msg); - } +group +group::getgrnam (const std::string& nm) +{ + std::string msg; + return getgrnam (nm, msg); +} - group - group::getgrnam (const std::string& nm, std::string& msg) - { +group +group::getgrnam (const std::string& nm, std::string& msg) +{ #if defined (HAVE_GETGRNAM) - msg = ""; - return group (::getgrnam (nm.c_str ()), msg); + msg = ""; + return group (::getgrnam (nm.c_str ()), msg); #else - octave_unused_parameter (nm); + octave_unused_parameter (nm); - msg = NOT_SUPPORTED ("getgrnam"); - return group (); + msg = NOT_SUPPORTED ("getgrnam"); + return group (); #endif - } +} - int - group::setgrent (void) - { - std::string msg; - return setgrent (msg); - } +int +group::setgrent (void) +{ + std::string msg; + return setgrent (msg); +} - int - group::setgrent (std::string& msg) - { +int +group::setgrent (std::string& msg) +{ #if defined (HAVE_SETGRENT) - msg = ""; - ::setgrent (); - return 0; + msg = ""; + ::setgrent (); + return 0; #else - msg = NOT_SUPPORTED ("setgrent"); - return -1; + msg = NOT_SUPPORTED ("setgrent"); + return -1; #endif - } +} - int - group::endgrent (void) - { - std::string msg; - return endgrent (msg); - } +int +group::endgrent (void) +{ + std::string msg; + return endgrent (msg); +} - int - group::endgrent (std::string& msg) - { +int +group::endgrent (std::string& msg) +{ #if defined (HAVE_ENDGRENT) - msg = ""; - ::endgrent (); - return 0; + msg = ""; + ::endgrent (); + return 0; #else - msg = NOT_SUPPORTED ("endgrent"); - return -1; + msg = NOT_SUPPORTED ("endgrent"); + return -1; #endif - } +} - group::group (void *p, std::string& msg) - : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false) - { +group::group (void *p, std::string& msg) + : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false) +{ #if defined (HAVE_GRP_H) - msg = ""; + msg = ""; - if (p) - { - struct ::group *gr = static_cast (p); + if (p) + { + struct ::group *gr = static_cast (p); - m_name = gr->gr_name; + m_name = gr->gr_name; #if defined (HAVE_GR_PASSWD) - m_passwd = gr->gr_passwd; + m_passwd = gr->gr_passwd; #endif - m_gid = gr->gr_gid; + m_gid = gr->gr_gid; - // FIXME: Maybe there should be a string_vector constructor - // that takes a NUL terminated list of C strings? + // FIXME: Maybe there should be a string_vector constructor + // that takes a NUL terminated list of C strings? - const char * const *tmp = gr->gr_mem; + const char *const *tmp = gr->gr_mem; - int k = 0; - while (*tmp++) - k++; + int k = 0; + while (*tmp++) + k++; - if (k > 0) - { - tmp = gr->gr_mem; + if (k > 0) + { + tmp = gr->gr_mem; - m_mem.resize (k); + m_mem.resize (k); - for (int i = 0; i < k; i++) - m_mem[i] = tmp[i]; - } + for (int i = 0; i < k; i++) + m_mem[i] = tmp[i]; + } - m_valid = true; - } + m_valid = true; + } #else - octave_unused_parameter (p); + octave_unused_parameter (p); - msg = NOT_SUPPORTED ("group functions"); + msg = NOT_SUPPORTED ("group functions"); #endif - } +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-group.h --- a/liboctave/system/oct-group.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-group.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,83 +38,83 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class - OCTAVE_API - group - { - public: +class +OCTAVE_API +group +{ +public: - group (void) - : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false) - { } + group (void) + : m_name (), m_passwd (), m_gid (0), m_mem (), m_valid (false) + { } - group (const group& gr) - : m_name (gr.m_name), m_passwd (gr.m_passwd), - m_gid (gr.m_gid), m_mem (gr.m_mem), m_valid (gr.m_valid) - { } + group (const group& gr) + : m_name (gr.m_name), m_passwd (gr.m_passwd), + m_gid (gr.m_gid), m_mem (gr.m_mem), m_valid (gr.m_valid) + { } - group& operator = (const group& gr) + group& operator = (const group& gr) + { + if (this != &gr) { - if (this != &gr) - { - m_name = gr.m_name; - m_passwd = gr.m_passwd; - m_gid = gr.m_gid; - m_mem = gr.m_mem; - m_valid = gr.m_valid; - } - - return *this; + m_name = gr.m_name; + m_passwd = gr.m_passwd; + m_gid = gr.m_gid; + m_mem = gr.m_mem; + m_valid = gr.m_valid; } - std::string name (void) const; + return *this; + } - std::string passwd (void) const; - - gid_t gid (void) const; + std::string name (void) const; - string_vector mem (void) const; + std::string passwd (void) const; - bool ok (void) const { return m_valid; } + gid_t gid (void) const; - operator bool () const { return ok (); } + string_vector mem (void) const; - static group getgrent (void); - static group getgrent (std::string& msg); + bool ok (void) const { return m_valid; } - static group getgrgid (gid_t gid); - static group getgrgid (gid_t gid, std::string& msg); + operator bool () const { return ok (); } - static group getgrnam (const std::string& nm); - static group getgrnam (const std::string& nm, std::string& msg); + static group getgrent (void); + static group getgrent (std::string& msg); - static int setgrent (void); - static int setgrent (std::string& msg); + static group getgrgid (gid_t gid); + static group getgrgid (gid_t gid, std::string& msg); + + static group getgrnam (const std::string& nm); + static group getgrnam (const std::string& nm, std::string& msg); - static int endgrent (void); - static int endgrent (std::string& msg); + static int setgrent (void); + static int setgrent (std::string& msg); - private: + static int endgrent (void); + static int endgrent (std::string& msg); - // The group name. - std::string m_name; +private: - // The group password. - std::string m_passwd; + // The group name. + std::string m_name; + + // The group password. + std::string m_passwd; - // The numeric group id. - gid_t m_gid; + // The numeric group id. + gid_t m_gid; - // The members of the group; - string_vector m_mem; + // The members of the group; + string_vector m_mem; - // Flag that says whether we have been properly initialized. - bool m_valid; + // Flag that says whether we have been properly initialized. + bool m_valid; - // This is how we will create an group object from a pointer - // to a struct group. - group (void *p, std::string& msg); - }; + // This is how we will create an group object from a pointer + // to a struct group. + group (void *p, std::string& msg); +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-password.cc --- a/liboctave/system/oct-password.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-password.cc Thu Dec 01 20:05:44 2022 -0800 @@ -50,197 +50,197 @@ OCTAVE_BEGIN_NAMESPACE(sys) - std::string - password::name (void) const - { - if (! ok ()) - err_invalid (); +std::string +password::name (void) const +{ + if (! ok ()) + err_invalid (); - return m_name; - } + return m_name; +} - std::string - password::passwd (void) const - { - if (! ok ()) - err_invalid (); +std::string +password::passwd (void) const +{ + if (! ok ()) + err_invalid (); - return m_passwd; - } + return m_passwd; +} - uid_t - password::uid (void) const - { - if (! ok ()) - err_invalid (); +uid_t +password::uid (void) const +{ + if (! ok ()) + err_invalid (); - return m_uid; - } + return m_uid; +} - gid_t - password::gid (void) const - { - if (! ok ()) - err_invalid (); +gid_t +password::gid (void) const +{ + if (! ok ()) + err_invalid (); - return m_gid; - } + return m_gid; +} - std::string - password::gecos (void) const - { - if (! ok ()) - err_invalid (); +std::string +password::gecos (void) const +{ + if (! ok ()) + err_invalid (); - return m_gecos; - } + return m_gecos; +} - std::string - password::dir (void) const - { - if (! ok ()) - err_invalid (); +std::string +password::dir (void) const +{ + if (! ok ()) + err_invalid (); - return m_dir; - } + return m_dir; +} - std::string - password::shell (void) const - { - if (! ok ()) - err_invalid (); +std::string +password::shell (void) const +{ + if (! ok ()) + err_invalid (); - return m_shell; - } + return m_shell; +} - password - password::getpwent (void) - { - std::string msg; - return getpwent (msg); - } +password +password::getpwent (void) +{ + std::string msg; + return getpwent (msg); +} - password - password::getpwent (std::string& msg) - { +password +password::getpwent (std::string& msg) +{ #if defined HAVE_GETPWENT - msg = ""; - return password (::getpwent (), msg); + msg = ""; + return password (::getpwent (), msg); #else - msg = NOT_SUPPORTED ("getpwent"); - return password (); + msg = NOT_SUPPORTED ("getpwent"); + return password (); #endif - } +} - password - password::getpwuid (uid_t uid) - { - std::string msg; - return getpwuid (uid, msg); - } +password +password::getpwuid (uid_t uid) +{ + std::string msg; + return getpwuid (uid, msg); +} - password - password::getpwuid (uid_t uid, std::string& msg) - { +password +password::getpwuid (uid_t uid, std::string& msg) +{ #if defined (HAVE_GETPWUID) - msg = ""; - return password (::getpwuid (uid), msg); + msg = ""; + return password (::getpwuid (uid), msg); #else - octave_unused_parameter (uid); + octave_unused_parameter (uid); - msg = NOT_SUPPORTED ("getpwuid"); - return password (); + msg = NOT_SUPPORTED ("getpwuid"); + return password (); #endif - } +} - password - password::getpwnam (const std::string& nm) - { - std::string msg; - return getpwnam (nm, msg); - } +password +password::getpwnam (const std::string& nm) +{ + std::string msg; + return getpwnam (nm, msg); +} - password - password::getpwnam (const std::string& nm, std::string& msg) - { +password +password::getpwnam (const std::string& nm, std::string& msg) +{ #if defined (HAVE_GETPWNAM) - msg = ""; - return password (::getpwnam (nm.c_str ()), msg); + msg = ""; + return password (::getpwnam (nm.c_str ()), msg); #else - octave_unused_parameter (nm); + octave_unused_parameter (nm); - msg = NOT_SUPPORTED ("getpwnam"); - return password (); + msg = NOT_SUPPORTED ("getpwnam"); + return password (); #endif - } +} - int - password::setpwent (void) - { - std::string msg; - return setpwent (msg); - } +int +password::setpwent (void) +{ + std::string msg; + return setpwent (msg); +} - int - password::setpwent (std::string& msg) - { +int +password::setpwent (std::string& msg) +{ #if defined (HAVE_SETPWENT) - msg = ""; - ::setpwent (); - return 0; + msg = ""; + ::setpwent (); + return 0; #else - msg = NOT_SUPPORTED ("setpwent"); - return -1; + msg = NOT_SUPPORTED ("setpwent"); + return -1; #endif - } +} - int - password::endpwent (void) - { - std::string msg; - return endpwent (msg); - } +int +password::endpwent (void) +{ + std::string msg; + return endpwent (msg); +} - int - password::endpwent (std::string& msg) - { +int +password::endpwent (std::string& msg) +{ #if defined (HAVE_ENDPWENT) - msg = ""; - ::endpwent (); - return 0; + msg = ""; + ::endpwent (); + return 0; #else - msg = NOT_SUPPORTED ("endpwent"); - return -1; + msg = NOT_SUPPORTED ("endpwent"); + return -1; #endif - } +} - password::password (void *p, std::string& msg) - : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (), - m_dir (), m_shell (), m_valid (false) +password::password (void *p, std::string& msg) + : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (), + m_dir (), m_shell (), m_valid (false) +{ +#if defined (HAVE_PWD_H) + msg = ""; + + if (p) { -#if defined (HAVE_PWD_H) - msg = ""; - - if (p) - { - struct ::passwd *pw = static_cast (p); + struct ::passwd *pw = static_cast (p); - m_name = pw->pw_name; - m_passwd = pw->pw_passwd; - m_uid = pw->pw_uid; - m_gid = pw->pw_gid; - m_gecos = pw->pw_gecos; - m_dir = pw->pw_dir; - m_shell = pw->pw_shell; + m_name = pw->pw_name; + m_passwd = pw->pw_passwd; + m_uid = pw->pw_uid; + m_gid = pw->pw_gid; + m_gecos = pw->pw_gecos; + m_dir = pw->pw_dir; + m_shell = pw->pw_shell; - m_valid = true; - } + m_valid = true; + } #else - octave_unused_parameter (p); + octave_unused_parameter (p); - msg = NOT_SUPPORTED ("password functions"); + msg = NOT_SUPPORTED ("password functions"); #endif - } +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-password.h --- a/liboctave/system/oct-password.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-password.h Thu Dec 01 20:05:44 2022 -0800 @@ -36,105 +36,105 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class - OCTAVE_API - password - { - public: +class +OCTAVE_API +password +{ +public: - password (void) - : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (), - m_dir (), m_shell (), m_valid (false) - { } + password (void) + : m_name (), m_passwd (), m_uid (0), m_gid (0), m_gecos (), + m_dir (), m_shell (), m_valid (false) + { } - password (const password& pw) - : m_name (pw.m_name), m_passwd (pw.m_passwd), - m_uid (pw.m_uid), m_gid (pw.m_gid), m_gecos (pw.m_gecos), - m_dir (pw.m_dir), m_shell (pw.m_shell), m_valid (pw.m_valid) - { } + password (const password& pw) + : m_name (pw.m_name), m_passwd (pw.m_passwd), + m_uid (pw.m_uid), m_gid (pw.m_gid), m_gecos (pw.m_gecos), + m_dir (pw.m_dir), m_shell (pw.m_shell), m_valid (pw.m_valid) + { } - password& operator = (const password& pw) + password& operator = (const password& pw) + { + if (this != &pw) { - if (this != &pw) - { - m_name = pw.m_name; - m_passwd = pw.m_passwd; - m_uid = pw.m_uid; - m_gid = pw.m_gid; - m_gecos = pw.m_gecos; - m_dir = pw.m_dir; - m_shell = pw.m_shell; - m_valid = pw.m_valid; - } - - return *this; + m_name = pw.m_name; + m_passwd = pw.m_passwd; + m_uid = pw.m_uid; + m_gid = pw.m_gid; + m_gecos = pw.m_gecos; + m_dir = pw.m_dir; + m_shell = pw.m_shell; + m_valid = pw.m_valid; } - ~password (void) = default; - - std::string name (void) const; + return *this; + } - std::string passwd (void) const; + ~password (void) = default; - uid_t uid (void) const; + std::string name (void) const; - gid_t gid (void) const; + std::string passwd (void) const; - std::string gecos (void) const; + uid_t uid (void) const; - std::string dir (void) const; + gid_t gid (void) const; - std::string shell (void) const; + std::string gecos (void) const; - bool ok (void) const { return m_valid; } + std::string dir (void) const; + + std::string shell (void) const; - operator bool () const { return ok (); } + bool ok (void) const { return m_valid; } - static password getpwent (void); - static password getpwent (std::string& msg); + operator bool () const { return ok (); } - static password getpwuid (uid_t uid); - static password getpwuid (uid_t uid, std::string& msg); + static password getpwent (void); + static password getpwent (std::string& msg); - static password getpwnam (const std::string& nm); - static password getpwnam (const std::string& nm, std::string& msg); + static password getpwuid (uid_t uid); + static password getpwuid (uid_t uid, std::string& msg); - static int setpwent (void); - static int setpwent (std::string& msg); + static password getpwnam (const std::string& nm); + static password getpwnam (const std::string& nm, std::string& msg); - static int endpwent (void); - static int endpwent (std::string& msg); + static int setpwent (void); + static int setpwent (std::string& msg); - private: + static int endpwent (void); + static int endpwent (std::string& msg); - // User name. - std::string m_name; +private: - // Encrypted password. - std::string m_passwd; + // User name. + std::string m_name; - // Numeric user id. - uid_t m_uid; + // Encrypted password. + std::string m_passwd; - // Numeric group id. - gid_t m_gid; + // Numeric user id. + uid_t m_uid; - // Miscellaneous junk. - std::string m_gecos; + // Numeric group id. + gid_t m_gid; - // Home directory. - std::string m_dir; + // Miscellaneous junk. + std::string m_gecos; + + // Home directory. + std::string m_dir; - // Login shell. - std::string m_shell; + // Login shell. + std::string m_shell; - // Flag that says whether we have been properly initialized. - bool m_valid; + // Flag that says whether we have been properly initialized. + bool m_valid; - // This is how we will create a password object from a pointer - // to a struct passwd. - password (void *p, std::string& msg); - }; + // This is how we will create a password object from a pointer + // to a struct passwd. + password (void *p, std::string& msg); +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-syscalls.cc --- a/liboctave/system/oct-syscalls.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-syscalls.cc Thu Dec 01 20:05:44 2022 -0800 @@ -48,323 +48,323 @@ OCTAVE_BEGIN_NAMESPACE(sys) - int - dup2 (int old_fd, int new_fd) - { - std::string msg; - return sys::dup2 (old_fd, new_fd, msg); - } +int +dup2 (int old_fd, int new_fd) +{ + std::string msg; + return sys::dup2 (old_fd, new_fd, msg); +} - int - dup2 (int old_fd, int new_fd, std::string& msg) - { - msg = ""; +int +dup2 (int old_fd, int new_fd, std::string& msg) +{ + msg = ""; + + int status = -1; - int status = -1; + status = octave_dup2_wrapper (old_fd, new_fd); - status = octave_dup2_wrapper (old_fd, new_fd); + if (status < 0) + msg = std::strerror (errno); - if (status < 0) - msg = std::strerror (errno); + return status; +} - return status; - } +int +execvp (const std::string& file, const string_vector& argv) +{ + std::string msg; + return sys::execvp (file, argv, msg); +} - int - execvp (const std::string& file, const string_vector& argv) - { - std::string msg; - return sys::execvp (file, argv, msg); - } +int +execvp (const std::string& file, const string_vector& args, + std::string& msg) +{ + msg = ""; + + char **argv = args.c_str_vec (); + + int status = octave_execvp_wrapper (file.c_str (), argv); - int - execvp (const std::string& file, const string_vector& args, - std::string& msg) - { - msg = ""; + string_vector::delete_c_str_vec (argv); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} - char **argv = args.c_str_vec (); +pid_t +fork (std::string& msg) +{ + pid_t status = -1; - int status = octave_execvp_wrapper (file.c_str (), argv); - - string_vector::delete_c_str_vec (argv); + if (octave_have_fork ()) + { + status = octave_fork_wrapper (); if (status < 0) msg = std::strerror (errno); - - return status; } - - pid_t - fork (std::string& msg) - { - pid_t status = -1; - - if (octave_have_fork ()) - { - status = octave_fork_wrapper (); - - if (status < 0) - msg = std::strerror (errno); - } - else - msg = NOT_SUPPORTED ("fork"); - - return status; - } + else + msg = NOT_SUPPORTED ("fork"); - pid_t - vfork (std::string& msg) - { - pid_t status = -1; - - if (octave_have_vfork () || octave_have_fork ()) - { - if (octave_have_vfork ()) - status = octave_vfork_wrapper (); - else - status = octave_fork_wrapper (); - - if (status < 0) - msg = std::strerror (errno); - } - else - msg = NOT_SUPPORTED ("vfork"); - - return status; - } - - pid_t - getpgrp (std::string& msg) - { - pid_t status = octave_getpgrp_wrapper (); - - if (status < 0) - msg = std::strerror (errno); + return status; +} - return status; - } - - pid_t - getpid (void) - { - return octave_getpid_wrapper (); - } - - pid_t - getppid (void) - { - return octave_getppid_wrapper (); - } - - gid_t - getgid (void) - { - return octave_getgid_wrapper (); - } - - gid_t - getegid (void) - { - return octave_getegid_wrapper (); - } +pid_t +vfork (std::string& msg) +{ + pid_t status = -1; - uid_t - getuid (void) - { - return octave_getuid_wrapper (); - } - - uid_t - geteuid (void) + if (octave_have_vfork () || octave_have_fork ()) { - return octave_geteuid_wrapper (); - } - - int - pipe (int *fildes) - { - std::string msg; - return sys::pipe (fildes, msg); - } - - int - pipe (int *fildes, std::string& msg) - { - msg = ""; - - int status = -1; - - status = octave_pipe_wrapper (fildes); + if (octave_have_vfork ()) + status = octave_vfork_wrapper (); + else + status = octave_fork_wrapper (); if (status < 0) msg = std::strerror (errno); + } + else + msg = NOT_SUPPORTED ("vfork"); - return status; - } + return status; +} - pid_t - waitpid (pid_t pid, int *status, int options) - { - std::string msg; - return sys::waitpid (pid, status, options, msg); - } +pid_t +getpgrp (std::string& msg) +{ + pid_t status = octave_getpgrp_wrapper (); - pid_t - waitpid (pid_t pid, int *status, int options, - std::string& msg) - { - pid_t retval = -1; - msg = ""; + if (status < 0) + msg = std::strerror (errno); + + return status; +} - retval = octave_waitpid_wrapper (pid, status, options); +pid_t +getpid (void) +{ + return octave_getpid_wrapper (); +} - if (retval < 0) - msg = std::strerror (errno); - - return retval; - } +pid_t +getppid (void) +{ + return octave_getppid_wrapper (); +} - int - wcontinue (void) - { - return octave_wcontinue_wrapper (); - } +gid_t +getgid (void) +{ + return octave_getgid_wrapper (); +} - int - wcoredump (int status) - { - return octave_wcoredump_wrapper (status); - } +gid_t +getegid (void) +{ + return octave_getegid_wrapper (); +} - bool - wifcontinued (int status) - { - return octave_wifcontinued_wrapper (status); - } +uid_t +getuid (void) +{ + return octave_getuid_wrapper (); +} + +uid_t +geteuid (void) +{ + return octave_geteuid_wrapper (); +} - bool - wifexited (int status) - { - return octave_wifexited_wrapper (status); - } +int +pipe (int *fildes) +{ + std::string msg; + return sys::pipe (fildes, msg); +} - bool - wifsignaled (int status) - { - return octave_wifsignaled_wrapper (status); - } +int +pipe (int *fildes, std::string& msg) +{ + msg = ""; - bool - wifstopped (int status) - { - return octave_wifstopped_wrapper (status); - } + int status = -1; + + status = octave_pipe_wrapper (fildes); - int - wexitstatus (int status) - { - return octave_wexitstatus_wrapper (status); - } + if (status < 0) + msg = std::strerror (errno); + + return status; +} - int - wnohang (void) - { - return octave_wnohang_wrapper (); - } +pid_t +waitpid (pid_t pid, int *status, int options) +{ + std::string msg; + return sys::waitpid (pid, status, options, msg); +} - int - wstopsig (int status) - { - return octave_wstopsig_wrapper (status); - } +pid_t +waitpid (pid_t pid, int *status, int options, + std::string& msg) +{ + pid_t retval = -1; + msg = ""; - int - wtermsig (int status) - { - return octave_wtermsig_wrapper (status); - } + retval = octave_waitpid_wrapper (pid, status, options); + + if (retval < 0) + msg = std::strerror (errno); + + return retval; +} - int - wuntraced (void) - { - return octave_wuntraced_wrapper (); - } +int +wcontinue (void) +{ + return octave_wcontinue_wrapper (); +} - int - kill (pid_t pid, int sig) - { - std::string msg; - return sys::kill (pid, sig, msg); - } +int +wcoredump (int status) +{ + return octave_wcoredump_wrapper (status); +} - int - kill (pid_t pid, int sig, std::string& msg) - { - msg = ""; +bool +wifcontinued (int status) +{ + return octave_wifcontinued_wrapper (status); +} - int status = -1; +bool +wifexited (int status) +{ + return octave_wifexited_wrapper (status); +} - if (octave_have_kill ()) - { - status = octave_kill_wrapper (pid, sig); +bool +wifsignaled (int status) +{ + return octave_wifsignaled_wrapper (status); +} - if (status < 0) - msg = std::strerror (errno); - } - else - msg = NOT_SUPPORTED ("kill"); - - return status; - } +bool +wifstopped (int status) +{ + return octave_wifstopped_wrapper (status); +} - pid_t - popen2 (const std::string& cmd, const string_vector& args, - bool sync_mode, int *fildes) - { - std::string msg; - return sys::popen2 (cmd, args, sync_mode, fildes, msg); - } +int +wexitstatus (int status) +{ + return octave_wexitstatus_wrapper (status); +} + +int +wnohang (void) +{ + return octave_wnohang_wrapper (); +} - pid_t - popen2 (const std::string& cmd, const string_vector& args, - bool sync_mode, int *fildes, std::string& msg) - { - char **argv = args.c_str_vec (); - const char *errmsg; +int +wstopsig (int status) +{ + return octave_wstopsig_wrapper (status); +} - pid_t pid = octave_popen2 (cmd.c_str (), argv, sync_mode, fildes, - &errmsg); - - string_vector::delete_c_str_vec (argv); +int +wtermsig (int status) +{ + return octave_wtermsig_wrapper (status); +} - if (pid < 0) - msg = errmsg; +int +wuntraced (void) +{ + return octave_wuntraced_wrapper (); +} - return pid; - } +int +kill (pid_t pid, int sig) +{ + std::string msg; + return sys::kill (pid, sig, msg); +} - int - fcntl (int fd, int cmd, long arg) +int +kill (pid_t pid, int sig, std::string& msg) +{ + msg = ""; + + int status = -1; + + if (octave_have_kill ()) { - std::string msg; - return sys::fcntl (fd, cmd, arg, msg); - } - - int - fcntl (int fd, int cmd, long arg, std::string& msg) - { - msg = ""; - - int status = -1; - - status = octave_fcntl_wrapper (fd, cmd, arg); + status = octave_kill_wrapper (pid, sig); if (status < 0) msg = std::strerror (errno); + } + else + msg = NOT_SUPPORTED ("kill"); - return status; - } + return status; +} + +pid_t +popen2 (const std::string& cmd, const string_vector& args, + bool sync_mode, int *fildes) +{ + std::string msg; + return sys::popen2 (cmd, args, sync_mode, fildes, msg); +} + +pid_t +popen2 (const std::string& cmd, const string_vector& args, + bool sync_mode, int *fildes, std::string& msg) +{ + char **argv = args.c_str_vec (); + const char *errmsg; + + pid_t pid = octave_popen2 (cmd.c_str (), argv, sync_mode, fildes, + &errmsg); + + string_vector::delete_c_str_vec (argv); + + if (pid < 0) + msg = errmsg; + + return pid; +} + +int +fcntl (int fd, int cmd, long arg) +{ + std::string msg; + return sys::fcntl (fd, cmd, arg, msg); +} + +int +fcntl (int fd, int cmd, long arg, std::string& msg) +{ + msg = ""; + + int status = -1; + + status = octave_fcntl_wrapper (fd, cmd, arg); + + if (status < 0) + msg = std::strerror (errno); + + return status; +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-syscalls.h --- a/liboctave/system/oct-syscalls.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-syscalls.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,71 +38,71 @@ OCTAVE_BEGIN_NAMESPACE(sys) - extern OCTAVE_API int dup2 (int, int); - extern OCTAVE_API int dup2 (int, int, std::string&); +extern OCTAVE_API int dup2 (int, int); +extern OCTAVE_API int dup2 (int, int, std::string&); - extern OCTAVE_API int execvp (const std::string&, const string_vector&); - extern OCTAVE_API int execvp (const std::string&, const string_vector&, - std::string&); +extern OCTAVE_API int execvp (const std::string&, const string_vector&); +extern OCTAVE_API int execvp (const std::string&, const string_vector&, + std::string&); - extern OCTAVE_API pid_t fork (std::string&); +extern OCTAVE_API pid_t fork (std::string&); - extern OCTAVE_API pid_t vfork (std::string&); +extern OCTAVE_API pid_t vfork (std::string&); - extern OCTAVE_API pid_t getpgrp (std::string&); +extern OCTAVE_API pid_t getpgrp (std::string&); - extern OCTAVE_API pid_t getpid (void); +extern OCTAVE_API pid_t getpid (void); - extern OCTAVE_API pid_t getppid (void); +extern OCTAVE_API pid_t getppid (void); - extern OCTAVE_API gid_t getgid (void); +extern OCTAVE_API gid_t getgid (void); - extern OCTAVE_API gid_t getegid (void); +extern OCTAVE_API gid_t getegid (void); - extern OCTAVE_API uid_t getuid (void); +extern OCTAVE_API uid_t getuid (void); - extern OCTAVE_API uid_t geteuid (void); +extern OCTAVE_API uid_t geteuid (void); - extern OCTAVE_API int pipe (int *); - extern OCTAVE_API int pipe (int *, std::string&); +extern OCTAVE_API int pipe (int *); +extern OCTAVE_API int pipe (int *, std::string&); - extern OCTAVE_API pid_t waitpid (pid_t, int *status, int); - extern OCTAVE_API pid_t waitpid (pid_t, int *status, int, std::string&); +extern OCTAVE_API pid_t waitpid (pid_t, int *status, int); +extern OCTAVE_API pid_t waitpid (pid_t, int *status, int, std::string&); - extern OCTAVE_API int wcontinue (void); +extern OCTAVE_API int wcontinue (void); - extern OCTAVE_API int wcoredump (int status); +extern OCTAVE_API int wcoredump (int status); - extern OCTAVE_API bool wifcontinued (int status); +extern OCTAVE_API bool wifcontinued (int status); - extern OCTAVE_API bool wifexited (int status); +extern OCTAVE_API bool wifexited (int status); - extern OCTAVE_API bool wifsignaled (int status); +extern OCTAVE_API bool wifsignaled (int status); - extern OCTAVE_API bool wifstopped (int status); +extern OCTAVE_API bool wifstopped (int status); - extern OCTAVE_API int wexitstatus (int status); +extern OCTAVE_API int wexitstatus (int status); - extern OCTAVE_API int wnohang (void); +extern OCTAVE_API int wnohang (void); - extern OCTAVE_API int wstopsig (int status); +extern OCTAVE_API int wstopsig (int status); - extern OCTAVE_API int wtermsig (int status); +extern OCTAVE_API int wtermsig (int status); - extern OCTAVE_API int wuntraced (void); +extern OCTAVE_API int wuntraced (void); - extern OCTAVE_API int kill (pid_t, int); - extern OCTAVE_API int kill (pid_t, int, std::string&); +extern OCTAVE_API int kill (pid_t, int); +extern OCTAVE_API int kill (pid_t, int, std::string&); - extern OCTAVE_API pid_t - popen2 (const std::string&, const string_vector&, bool, int *); +extern OCTAVE_API pid_t +popen2 (const std::string&, const string_vector&, bool, int *); - extern OCTAVE_API pid_t - popen2 (const std::string&, const string_vector&, bool, int *, - std::string&); +extern OCTAVE_API pid_t +popen2 (const std::string&, const string_vector&, bool, int *, + std::string&); - extern OCTAVE_API int fcntl (int, int, long); - extern OCTAVE_API int fcntl (int, int, long, std::string&); +extern OCTAVE_API int fcntl (int, int, long); +extern OCTAVE_API int fcntl (int, int, long, std::string&); OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-time.cc --- a/liboctave/system/oct-time.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-time.cc Thu Dec 01 20:05:44 2022 -0800 @@ -52,84 +52,84 @@ OCTAVE_BEGIN_NAMESPACE(sys) - time::time (double d) - : m_ot_unix_time (static_cast (d)), m_ot_usec (0) - { - double ip; - m_ot_usec = static_cast (std::modf (d, &ip) * 1e6); - } +time::time (double d) + : m_ot_unix_time (static_cast (d)), m_ot_usec (0) +{ + double ip; + m_ot_usec = static_cast (std::modf (d, &ip) * 1e6); +} - time::time (const base_tm& tm) - : m_ot_unix_time (), m_ot_usec () - { - struct ::tm t; +time::time (const base_tm& tm) + : m_ot_unix_time (), m_ot_usec () +{ + struct ::tm t; - t.tm_sec = tm.sec (); - t.tm_min = tm.min (); - t.tm_hour = tm.hour (); - t.tm_mday = tm.mday (); - t.tm_mon = tm.mon (); - t.tm_year = tm.year (); - t.tm_wday = tm.wday (); - t.tm_yday = tm.yday (); - t.tm_isdst = tm.isdst (); + t.tm_sec = tm.sec (); + t.tm_min = tm.min (); + t.tm_hour = tm.hour (); + t.tm_mday = tm.mday (); + t.tm_mon = tm.mon (); + t.tm_year = tm.year (); + t.tm_wday = tm.wday (); + t.tm_yday = tm.yday (); + t.tm_isdst = tm.isdst (); #if defined (HAVE_TM_GMTOFF) - t.tm_gmtoff = tm.gmtoff (); + t.tm_gmtoff = tm.gmtoff (); #endif #if defined (HAVE_STRUCT_TM_TM_ZONE) - std::string s = tm.zone (); - char *ps = strsave (s.c_str ()); - t.tm_zone = ps; + std::string s = tm.zone (); + char *ps = strsave (s.c_str ()); + t.tm_zone = ps; #endif - m_ot_unix_time = octave_mktime_wrapper (&t); + m_ot_unix_time = octave_mktime_wrapper (&t); #if defined (HAVE_STRUCT_TM_TM_ZONE) - delete [] ps; + delete [] ps; #endif - m_ot_usec = tm.usec (); - } + m_ot_usec = tm.usec (); +} - std::string - time::ctime (void) const - { - return localtime (*this).asctime (); - } +std::string +time::ctime (void) const +{ + return localtime (*this).asctime (); +} - std::ostream& - operator << (std::ostream& os, const time& ot) - { - preserve_stream_state stream_state (os); +std::ostream& +operator << (std::ostream& os, const time& ot) +{ + preserve_stream_state stream_state (os); - os << ot.m_ot_unix_time << '.' - << std::setw (6) << std::setfill ('0') << ot.m_ot_usec; + os << ot.m_ot_unix_time << '.' + << std::setw (6) << std::setfill ('0') << ot.m_ot_usec; - return os; - } + return os; +} - void - time::stamp (void) - { - time_t ot_unix_time; - octave_gettimeofday_wrapper (&ot_unix_time, &m_ot_usec); - m_ot_unix_time = ot_unix_time; - } +void +time::stamp (void) +{ + time_t ot_unix_time; + octave_gettimeofday_wrapper (&ot_unix_time, &m_ot_usec); + m_ot_unix_time = ot_unix_time; +} - // From the mktime() manual page: - // - // The mktime() function converts a broken-down time structure, - // expressed as local time, to calendar time representation. - // - // - // - // If structure members are outside their legal interval, they - // will be normalized (so that, e.g., 40 October is changed into - // 9 November). - // - // So, we no longer check limits here. +// From the mktime() manual page: +// +// The mktime() function converts a broken-down time structure, +// expressed as local time, to calendar time representation. +// +// +// +// If structure members are outside their legal interval, they +// will be normalized (so that, e.g., 40 October is changed into +// 9 November). +// +// So, we no longer check limits here. #define DEFINE_SET_FIELD_FCN(type, f, lo, hi) \ base_tm& \ @@ -143,232 +143,232 @@ #define DEFINE_SET_INT_FIELD_FCN(f, lo, hi) \ DEFINE_SET_FIELD_FCN (int, f, lo, hi) - DEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000) - DEFINE_SET_INT_FIELD_FCN (sec, 0, 61) - DEFINE_SET_INT_FIELD_FCN (min, 0, 59) - DEFINE_SET_INT_FIELD_FCN (hour, 0, 23) - DEFINE_SET_INT_FIELD_FCN (mday, 1, 31) - DEFINE_SET_INT_FIELD_FCN (mon, 0, 11) - DEFINE_SET_INT_FIELD_FCN (year, std::numeric_limits::min (), - std::numeric_limitd::max ()) - DEFINE_SET_INT_FIELD_FCN (wday, 0, 6) - DEFINE_SET_INT_FIELD_FCN (yday, 0, 365) - DEFINE_SET_INT_FIELD_FCN (isdst, 0, 1) - DEFINE_SET_FIELD_FCN (long, gmtoff, -86400, 0) +DEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000) +DEFINE_SET_INT_FIELD_FCN (sec, 0, 61) +DEFINE_SET_INT_FIELD_FCN (min, 0, 59) +DEFINE_SET_INT_FIELD_FCN (hour, 0, 23) +DEFINE_SET_INT_FIELD_FCN (mday, 1, 31) +DEFINE_SET_INT_FIELD_FCN (mon, 0, 11) +DEFINE_SET_INT_FIELD_FCN (year, std::numeric_limits::min (), + std::numeric_limitd::max ()) +DEFINE_SET_INT_FIELD_FCN (wday, 0, 6) +DEFINE_SET_INT_FIELD_FCN (yday, 0, 365) +DEFINE_SET_INT_FIELD_FCN (isdst, 0, 1) +DEFINE_SET_FIELD_FCN (long, gmtoff, -86400, 0) - base_tm& - base_tm::zone (const std::string& s) - { - m_zone = s; - return *this; - } +base_tm& +base_tm::zone (const std::string& s) +{ + m_zone = s; + return *this; +} #if ! defined STRFTIME_BUF_INITIAL_SIZE # define STRFTIME_BUF_INITIAL_SIZE 128 #endif - std::string - base_tm::strftime (const std::string& fmt) const +std::string +base_tm::strftime (const std::string& fmt) const +{ + std::string retval; + + if (! fmt.empty ()) { - std::string retval; - - if (! fmt.empty ()) - { - struct ::tm t; + struct ::tm t; - t.tm_sec = m_sec; - t.tm_min = m_min; - t.tm_hour = m_hour; - t.tm_mday = m_mday; - t.tm_mon = m_mon; - t.tm_year = m_year; - t.tm_wday = m_wday; - t.tm_yday = m_yday; - t.tm_isdst = m_isdst; + t.tm_sec = m_sec; + t.tm_min = m_min; + t.tm_hour = m_hour; + t.tm_mday = m_mday; + t.tm_mon = m_mon; + t.tm_year = m_year; + t.tm_wday = m_wday; + t.tm_yday = m_yday; + t.tm_isdst = m_isdst; #if defined (HAVE_TM_GMTOFF) - t.tm_gmtoff = m_gmtoff; + t.tm_gmtoff = m_gmtoff; #endif #if defined (HAVE_STRUCT_TM_TM_ZONE) - char *ps = strsave (m_zone.c_str ()); - t.tm_zone = ps; -#endif - - const char *fmt_str = fmt.c_str (); - - char *buf = nullptr; - std::size_t bufsize = STRFTIME_BUF_INITIAL_SIZE; - std::size_t chars_written = 0; - - while (chars_written == 0) - { - delete [] buf; - buf = new char [bufsize]; - buf[0] = '\0'; - - chars_written - = octave_strftime_wrapper (buf, bufsize, fmt_str, &t); - - bufsize *= 2; - } - -#if defined (HAVE_STRUCT_TM_TM_ZONE) - delete [] ps; -#endif - - retval = buf; - - delete [] buf; - } - - return retval; - } - - void - base_tm::init (void *p) - { - if (! p) - return; - - struct ::tm *t = static_cast (p); - - m_sec = t->tm_sec; - m_min = t->tm_min; - m_hour = t->tm_hour; - m_mday = t->tm_mday; - m_mon = t->tm_mon; - m_year = t->tm_year; - m_wday = t->tm_wday; - m_yday = t->tm_yday; - m_isdst = t->tm_isdst; - -#if defined (HAVE_TM_GMTOFF) - m_gmtoff = t->tm_gmtoff; -#elif defined (OCTAVE_USE_WINDOWS_API) - TIME_ZONE_INFORMATION tzi; - - GetTimeZoneInformationForYear (m_year, nullptr, &tzi); - - if (m_isdst) - m_gmtoff = -60 * (tzi.Bias + tzi.DaylightBias); - else - m_gmtoff = -60 * (tzi.Bias + tzi.StandardBias); -#endif - -#if defined (HAVE_STRUCT_TM_TM_ZONE) - if (t->tm_zone) - m_zone = t->tm_zone; -#elif defined (OCTAVE_USE_WINDOWS_API) - if (m_isdst) - m_zone = sys::u8_from_wstring (tzi.DaylightName); - else - m_zone = sys::u8_from_wstring (tzi.StandardName); -#elif defined (HAVE_TZNAME) - if (t->tm_isdst == 0 || t->tm_isdst == 1) - m_zone = tzname[t->tm_isdst]; -#endif - } - - void - localtime::init (const time& ot) - { - m_usec = ot.usec (); - - time_t t = ot.unix_time (); - - base_tm::init (std::localtime (&t)); - } - - void - gmtime::init (const time& ot) - { - m_usec = ot.usec (); - - time_t t = ot.unix_time (); - - base_tm::init (std::gmtime (&t)); - } - - void - strptime::init (const std::string& str, const std::string& fmt) - { - struct ::tm t; - - t.tm_sec = 0; - t.tm_min = 0; - t.tm_hour = 0; - t.tm_mday = 0; - t.tm_mon = -1; - t.tm_year = std::numeric_limits::min (); - t.tm_wday = 0; - t.tm_yday = 0; - t.tm_isdst = 0; - -#if defined (HAVE_TM_GMTOFF) - t.tm_gmtoff = 0; -#endif - -#if defined (HAVE_STRUCT_TM_TM_ZONE) - char *ps = strsave (""); + char *ps = strsave (m_zone.c_str ()); t.tm_zone = ps; #endif - const char *p = str.c_str (); - - char *q = octave_strptime_wrapper (p, fmt.c_str (), &t); + const char *fmt_str = fmt.c_str (); - // Fill in wday and yday, but only if mday is valid and the mon and year - // are filled in, avoiding issues with mktime and invalid dates. - if (t.tm_mday != 0 && t.tm_mon >= 0 - && t.tm_year != std::numeric_limits::min ()) - { - t.tm_isdst = -1; - octave_mktime_wrapper (&t); - } + char *buf = nullptr; + std::size_t bufsize = STRFTIME_BUF_INITIAL_SIZE; + std::size_t chars_written = 0; - if (t.tm_mon < 0) - t.tm_mon = 0; - - if (t.tm_year == std::numeric_limits::min ()) - t.tm_year = 0; + while (chars_written == 0) + { + delete [] buf; + buf = new char [bufsize]; + buf[0] = '\0'; - if (q) - m_nchars = q - p + 1; - else - m_nchars = 0; + chars_written + = octave_strftime_wrapper (buf, bufsize, fmt_str, &t); - base_tm::init (&t); + bufsize *= 2; + } #if defined (HAVE_STRUCT_TM_TM_ZONE) delete [] ps; #endif - } - void - cpu_time::stamp (void) - { - time_t usr_sec, sys_sec; - octave_cpu_time (&usr_sec, &sys_sec, &m_usr_usec, &m_sys_usec); - m_usr_sec = usr_sec; - m_sys_sec = sys_sec; + retval = buf; + + delete [] buf; } - void - resource_usage::stamp (void) - { - time_t usr_sec, sys_sec; - long usr_usec, sys_usec; + return retval; +} + +void +base_tm::init (void *p) +{ + if (! p) + return; + + struct ::tm *t = static_cast (p); + + m_sec = t->tm_sec; + m_min = t->tm_min; + m_hour = t->tm_hour; + m_mday = t->tm_mday; + m_mon = t->tm_mon; + m_year = t->tm_year; + m_wday = t->tm_wday; + m_yday = t->tm_yday; + m_isdst = t->tm_isdst; + +#if defined (HAVE_TM_GMTOFF) + m_gmtoff = t->tm_gmtoff; +#elif defined (OCTAVE_USE_WINDOWS_API) + TIME_ZONE_INFORMATION tzi; + + GetTimeZoneInformationForYear (m_year, nullptr, &tzi); + + if (m_isdst) + m_gmtoff = -60 * (tzi.Bias + tzi.DaylightBias); + else + m_gmtoff = -60 * (tzi.Bias + tzi.StandardBias); +#endif + +#if defined (HAVE_STRUCT_TM_TM_ZONE) + if (t->tm_zone) + m_zone = t->tm_zone; +#elif defined (OCTAVE_USE_WINDOWS_API) + if (m_isdst) + m_zone = sys::u8_from_wstring (tzi.DaylightName); + else + m_zone = sys::u8_from_wstring (tzi.StandardName); +#elif defined (HAVE_TZNAME) + if (t->tm_isdst == 0 || t->tm_isdst == 1) + m_zone = tzname[t->tm_isdst]; +#endif +} + +void +localtime::init (const time& ot) +{ + m_usec = ot.usec (); + + time_t t = ot.unix_time (); + + base_tm::init (std::localtime (&t)); +} + +void +gmtime::init (const time& ot) +{ + m_usec = ot.usec (); + + time_t t = ot.unix_time (); + + base_tm::init (std::gmtime (&t)); +} + +void +strptime::init (const std::string& str, const std::string& fmt) +{ + struct ::tm t; - octave_getrusage_wrapper (&usr_sec, &sys_sec, &usr_usec, - &sys_usec, &m_maxrss, &m_ixrss, - &m_idrss, &m_isrss, &m_minflt, - &m_majflt, &m_nswap, &m_inblock, - &m_oublock, &m_msgsnd, &m_msgrcv, - &m_nsignals, &m_nvcsw, &m_nivcsw); + t.tm_sec = 0; + t.tm_min = 0; + t.tm_hour = 0; + t.tm_mday = 0; + t.tm_mon = -1; + t.tm_year = std::numeric_limits::min (); + t.tm_wday = 0; + t.tm_yday = 0; + t.tm_isdst = 0; + +#if defined (HAVE_TM_GMTOFF) + t.tm_gmtoff = 0; +#endif + +#if defined (HAVE_STRUCT_TM_TM_ZONE) + char *ps = strsave (""); + t.tm_zone = ps; +#endif + + const char *p = str.c_str (); + + char *q = octave_strptime_wrapper (p, fmt.c_str (), &t); + + // Fill in wday and yday, but only if mday is valid and the mon and year + // are filled in, avoiding issues with mktime and invalid dates. + if (t.tm_mday != 0 && t.tm_mon >= 0 + && t.tm_year != std::numeric_limits::min ()) + { + t.tm_isdst = -1; + octave_mktime_wrapper (&t); + } + + if (t.tm_mon < 0) + t.tm_mon = 0; - m_cpu = cpu_time (usr_sec, sys_sec, usr_usec, sys_usec); - } + if (t.tm_year == std::numeric_limits::min ()) + t.tm_year = 0; + + if (q) + m_nchars = q - p + 1; + else + m_nchars = 0; + + base_tm::init (&t); + +#if defined (HAVE_STRUCT_TM_TM_ZONE) + delete [] ps; +#endif +} + +void +cpu_time::stamp (void) +{ + time_t usr_sec, sys_sec; + octave_cpu_time (&usr_sec, &sys_sec, &m_usr_usec, &m_sys_usec); + m_usr_sec = usr_sec; + m_sys_sec = sys_sec; +} + +void +resource_usage::stamp (void) +{ + time_t usr_sec, sys_sec; + long usr_usec, sys_usec; + + octave_getrusage_wrapper (&usr_sec, &sys_sec, &usr_usec, + &sys_usec, &m_maxrss, &m_ixrss, + &m_idrss, &m_isrss, &m_minflt, + &m_majflt, &m_nswap, &m_inblock, + &m_oublock, &m_msgsnd, &m_msgrcv, + &m_nsignals, &m_nvcsw, &m_nivcsw); + + m_cpu = cpu_time (usr_sec, sys_sec, usr_usec, sys_usec); +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-time.h --- a/liboctave/system/oct-time.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-time.h Thu Dec 01 20:05:44 2022 -0800 @@ -45,489 +45,489 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class base_tm; +class base_tm; - class - time - { - public: +class +time +{ +public: + + time (void) + : m_ot_unix_time (0), m_ot_usec (0) { stamp (); } - time (void) - : m_ot_unix_time (0), m_ot_usec (0) { stamp (); } + time (OCTAVE_TIME_T t) + : m_ot_unix_time (t), m_ot_usec (0) { } - time (OCTAVE_TIME_T t) - : m_ot_unix_time (t), m_ot_usec (0) { } + time (OCTAVE_TIME_T t, long us) + : m_ot_unix_time (t), m_ot_usec () + { + long rem, extra; - time (OCTAVE_TIME_T t, long us) - : m_ot_unix_time (t), m_ot_usec () + if (us >= 0) { - long rem, extra; - - if (us >= 0) - { - rem = us % 1000000; - extra = (us - rem) / 1000000; - } - else - { - us = -us; - rem = us % 1000000; - extra = - (1 + (us - rem) / 1000000); - rem = 1000000 - us % 1000000; - } - - m_ot_usec = rem; - m_ot_unix_time += extra; + rem = us % 1000000; + extra = (us - rem) / 1000000; + } + else + { + us = -us; + rem = us % 1000000; + extra = - (1 + (us - rem) / 1000000); + rem = 1000000 - us % 1000000; } - OCTAVE_API time (double d); + m_ot_usec = rem; + m_ot_unix_time += extra; + } - OCTAVE_API time (const base_tm& tm); + OCTAVE_API time (double d); - time (const time& ot) - : m_ot_unix_time (ot.m_ot_unix_time), m_ot_usec (ot.m_ot_usec) { } + OCTAVE_API time (const base_tm& tm); - time& operator = (const time& ot) + time (const time& ot) + : m_ot_unix_time (ot.m_ot_unix_time), m_ot_usec (ot.m_ot_usec) { } + + time& operator = (const time& ot) + { + if (this != &ot) { - if (this != &ot) - { - m_ot_unix_time = ot.m_ot_unix_time; - m_ot_usec = ot.m_ot_usec; - } - - return *this; - } - - ~time (void) = default; - - OCTAVE_API void stamp (void); - - double double_value (void) const - { - return as_double (m_ot_unix_time, m_ot_usec); + m_ot_unix_time = ot.m_ot_unix_time; + m_ot_usec = ot.m_ot_usec; } - OCTAVE_TIME_T unix_time (void) const { return m_ot_unix_time; } + return *this; + } - long usec (void) const { return m_ot_usec; } + ~time (void) = default; + + OCTAVE_API void stamp (void); - OCTAVE_API std::string ctime (void) const; + double double_value (void) const + { + return as_double (m_ot_unix_time, m_ot_usec); + } - friend OCTAVE_API std::ostream& operator << (std::ostream& os, const time& ot); - - private: + OCTAVE_TIME_T unix_time (void) const { return m_ot_unix_time; } - // Seconds since the epoch. - OCTAVE_TIME_T m_ot_unix_time; + long usec (void) const { return m_ot_usec; } + + OCTAVE_API std::string ctime (void) const; + + friend OCTAVE_API std::ostream& operator << (std::ostream& os, const time& ot); - // Additional microseconds. - long m_ot_usec; - }; +private: - inline bool - operator == (const time& t1, const time& t2) - { - return (t1.unix_time () == t2.unix_time () && t1.usec () == t2.usec ()); - } + // Seconds since the epoch. + OCTAVE_TIME_T m_ot_unix_time; + + // Additional microseconds. + long m_ot_usec; +}; - inline bool - operator != (const time& t1, const time& t2) - { - return ! (t1 == t2); - } +inline bool +operator == (const time& t1, const time& t2) +{ + return (t1.unix_time () == t2.unix_time () && t1.usec () == t2.usec ()); +} + +inline bool +operator != (const time& t1, const time& t2) +{ + return ! (t1 == t2); +} - inline bool - operator < (const time& t1, const time& t2) - { - if (t1.unix_time () < t2.unix_time ()) - return true; - else if (t1.unix_time () > t2.unix_time ()) - return false; - else if (t1.usec () < t2.usec ()) - return true; - else - return false; - } +inline bool +operator < (const time& t1, const time& t2) +{ + if (t1.unix_time () < t2.unix_time ()) + return true; + else if (t1.unix_time () > t2.unix_time ()) + return false; + else if (t1.usec () < t2.usec ()) + return true; + else + return false; +} - inline bool - operator <= (const time& t1, const time& t2) - { - return (t1 < t2 || t1 == t2); - } +inline bool +operator <= (const time& t1, const time& t2) +{ + return (t1 < t2 || t1 == t2); +} - inline bool - operator > (const time& t1, const time& t2) - { - if (t1.unix_time () > t2.unix_time ()) - return true; - else if (t1.unix_time () < t2.unix_time ()) - return false; - else if (t1.usec () > t2.usec ()) - return true; - else - return false; - } +inline bool +operator > (const time& t1, const time& t2) +{ + if (t1.unix_time () > t2.unix_time ()) + return true; + else if (t1.unix_time () < t2.unix_time ()) + return false; + else if (t1.usec () > t2.usec ()) + return true; + else + return false; +} - inline bool - operator >= (const time& t1, const time& t2) - { - return (t1 > t2 || t1 == t2); - } +inline bool +operator >= (const time& t1, const time& t2) +{ + return (t1 > t2 || t1 == t2); +} - inline time - operator + (const time& t1, const time& t2) - { - return time (t1.unix_time () + t2.unix_time (), - t1.usec () + t2.usec ()); - } - - class - base_tm - { - public: +inline time +operator + (const time& t1, const time& t2) +{ + return time (t1.unix_time () + t2.unix_time (), + t1.usec () + t2.usec ()); +} - base_tm (void) - : m_usec (0), m_sec (0), m_min (0), m_hour (0), - m_mday (0), m_mon (0), m_year (0), m_wday (0), - m_yday (0), m_isdst (0), m_gmtoff (0), m_zone ("unknown") - { } +class +base_tm +{ +public: + + base_tm (void) + : m_usec (0), m_sec (0), m_min (0), m_hour (0), + m_mday (0), m_mon (0), m_year (0), m_wday (0), + m_yday (0), m_isdst (0), m_gmtoff (0), m_zone ("unknown") + { } - base_tm (const base_tm& tm) - : m_usec (tm.m_usec), m_sec (tm.m_sec), m_min (tm.m_min), - m_hour (tm.m_hour), m_mday (tm.m_mday), m_mon (tm.m_mon), - m_year (tm.m_year), m_wday (tm.m_wday), m_yday (tm.m_yday), - m_isdst (tm.m_isdst), m_gmtoff (tm.m_gmtoff), m_zone (tm.m_zone) - { } + base_tm (const base_tm& tm) + : m_usec (tm.m_usec), m_sec (tm.m_sec), m_min (tm.m_min), + m_hour (tm.m_hour), m_mday (tm.m_mday), m_mon (tm.m_mon), + m_year (tm.m_year), m_wday (tm.m_wday), m_yday (tm.m_yday), + m_isdst (tm.m_isdst), m_gmtoff (tm.m_gmtoff), m_zone (tm.m_zone) + { } - base_tm& operator = (const base_tm& tm) + base_tm& operator = (const base_tm& tm) + { + if (this != &tm) { - if (this != &tm) - { - m_usec = tm.m_usec; - m_sec = tm.m_sec; - m_min = tm.m_min; - m_hour = tm.m_hour; - m_mday = tm.m_mday; - m_mon = tm.m_mon; - m_year = tm.m_year; - m_wday = tm.m_wday; - m_yday = tm.m_yday; - m_isdst = tm.m_isdst; - m_gmtoff = tm.m_gmtoff; - m_zone = tm.m_zone; - } - - return *this; + m_usec = tm.m_usec; + m_sec = tm.m_sec; + m_min = tm.m_min; + m_hour = tm.m_hour; + m_mday = tm.m_mday; + m_mon = tm.m_mon; + m_year = tm.m_year; + m_wday = tm.m_wday; + m_yday = tm.m_yday; + m_isdst = tm.m_isdst; + m_gmtoff = tm.m_gmtoff; + m_zone = tm.m_zone; } - virtual ~base_tm (void) = default; + return *this; + } + + virtual ~base_tm (void) = default; - int usec (void) const { return m_usec; } - int sec (void) const { return m_sec; } - int min (void) const { return m_min; } - int hour (void) const { return m_hour; } - int mday (void) const { return m_mday; } - int mon (void) const { return m_mon; } - int year (void) const { return m_year; } - int wday (void) const { return m_wday; } - int yday (void) const { return m_yday; } - int isdst (void) const { return m_isdst; } - long gmtoff (void) const { return m_gmtoff; } - std::string zone (void) const { return m_zone; } + int usec (void) const { return m_usec; } + int sec (void) const { return m_sec; } + int min (void) const { return m_min; } + int hour (void) const { return m_hour; } + int mday (void) const { return m_mday; } + int mon (void) const { return m_mon; } + int year (void) const { return m_year; } + int wday (void) const { return m_wday; } + int yday (void) const { return m_yday; } + int isdst (void) const { return m_isdst; } + long gmtoff (void) const { return m_gmtoff; } + std::string zone (void) const { return m_zone; } - OCTAVE_API base_tm& usec (int v); - OCTAVE_API base_tm& sec (int v); - OCTAVE_API base_tm& min (int v); - OCTAVE_API base_tm& hour (int v); - OCTAVE_API base_tm& mday (int v); - OCTAVE_API base_tm& mon (int v); - OCTAVE_API base_tm& year (int v); - OCTAVE_API base_tm& wday (int v); - OCTAVE_API base_tm& yday (int v); - OCTAVE_API base_tm& isdst (int v); - OCTAVE_API base_tm& gmtoff (long v); - OCTAVE_API base_tm& zone (const std::string& s); + OCTAVE_API base_tm& usec (int v); + OCTAVE_API base_tm& sec (int v); + OCTAVE_API base_tm& min (int v); + OCTAVE_API base_tm& hour (int v); + OCTAVE_API base_tm& mday (int v); + OCTAVE_API base_tm& mon (int v); + OCTAVE_API base_tm& year (int v); + OCTAVE_API base_tm& wday (int v); + OCTAVE_API base_tm& yday (int v); + OCTAVE_API base_tm& isdst (int v); + OCTAVE_API base_tm& gmtoff (long v); + OCTAVE_API base_tm& zone (const std::string& s); - OCTAVE_API std::string strftime (const std::string& fmt) const; + OCTAVE_API std::string strftime (const std::string& fmt) const; + + std::string asctime (void) const + { return strftime ("%a %b %d %H:%M:%S %Y\n"); } - std::string asctime (void) const - { return strftime ("%a %b %d %H:%M:%S %Y\n"); } +protected: - protected: + // Microseconds after the second (0, 999999). + int m_usec; + + // Seconds after the minute (0, 61). + int m_sec; - // Microseconds after the second (0, 999999). - int m_usec; + // Minutes after the hour (0, 59). + int m_min; - // Seconds after the minute (0, 61). - int m_sec; + // Hours since midnight (0, 23). + int m_hour; - // Minutes after the hour (0, 59). - int m_min; + // Day of the month (1, 31). + int m_mday; - // Hours since midnight (0, 23). - int m_hour; + // Months since January (0, 11). + int m_mon; + + // Years since 1900. + int m_year; - // Day of the month (1, 31). - int m_mday; + // Days since Sunday (0, 6). + int m_wday; - // Months since January (0, 11). - int m_mon; + // Days since January 1 (0, 365). + int m_yday; - // Years since 1900. - int m_year; + // Daylight saving time flag. + int m_isdst; + + // Time zone. + long m_gmtoff; - // Days since Sunday (0, 6). - int m_wday; + // Time zone. + std::string m_zone; - // Days since January 1 (0, 365). - int m_yday; + OCTAVE_API void init (void *p); +}; - // Daylight saving time flag. - int m_isdst; +class +localtime : public base_tm +{ +public: - // Time zone. - long m_gmtoff; + localtime (void) + : base_tm () { init (time ()); } - // Time zone. - std::string m_zone; + localtime (const time& ot) + : base_tm () { init (ot); } + + localtime (const localtime& t) + : base_tm (t) { } - OCTAVE_API void init (void *p); - }; + localtime& operator = (const localtime& t) + { + base_tm::operator = (t); + return *this; + } - class - localtime : public base_tm - { - public: + ~localtime (void) = default; + +private: - localtime (void) - : base_tm () { init (time ()); } + OCTAVE_API void init (const time& ot); +}; - localtime (const time& ot) - : base_tm () { init (ot); } +class +gmtime : public base_tm +{ +public: - localtime (const localtime& t) - : base_tm (t) { } + gmtime (void) + : base_tm () { init (time ()); } + + gmtime (const time& ot) + : base_tm () { init (ot); } - localtime& operator = (const localtime& t) - { - base_tm::operator = (t); - return *this; - } + gmtime& operator = (const gmtime& t) + { + base_tm::operator = (t); + return *this; + } - ~localtime (void) = default; + ~gmtime (void) = default; + +private: - private: - - OCTAVE_API void init (const time& ot); - }; + OCTAVE_API void init (const time& ot); +}; - class - gmtime : public base_tm - { - public: +class +strptime : public base_tm +{ +public: + + strptime (const std::string& str, const std::string& fmt) + : base_tm (), m_nchars (0) + { + init (str, fmt); + } - gmtime (void) - : base_tm () { init (time ()); } + strptime (const strptime& s) + : base_tm (s), m_nchars (s.m_nchars) { } - gmtime (const time& ot) - : base_tm () { init (ot); } + strptime& operator = (const strptime& s) + { + base_tm::operator = (s); + m_nchars = s.m_nchars; + return *this; + } - gmtime& operator = (const gmtime& t) - { - base_tm::operator = (t); - return *this; - } + int characters_converted (void) const { return m_nchars; } + + ~strptime (void) = default; - ~gmtime (void) = default; +private: - private: + int m_nchars; - OCTAVE_API void init (const time& ot); - }; + OCTAVE_API void init (const std::string& str, const std::string& fmt); +}; - class - strptime : public base_tm - { - public: +class +cpu_time +{ +public: + + friend class resource_usage; - strptime (const std::string& str, const std::string& fmt) - : base_tm (), m_nchars (0) + cpu_time (void) + : m_usr_sec (0), m_sys_sec (0), m_usr_usec (0), m_sys_usec (0) + { + stamp (); + } + + cpu_time (const cpu_time& tm) + : m_usr_sec (tm.m_usr_sec), m_sys_sec (tm.m_sys_sec), + m_usr_usec (tm.m_usr_usec), m_sys_usec (tm.m_sys_usec) + { } + + cpu_time& operator = (const cpu_time& tm) + { + if (&tm != this) { - init (str, fmt); - } - - strptime (const strptime& s) - : base_tm (s), m_nchars (s.m_nchars) { } - - strptime& operator = (const strptime& s) - { - base_tm::operator = (s); - m_nchars = s.m_nchars; - return *this; + m_usr_sec = tm.m_usr_sec; + m_sys_sec = tm.m_sys_sec; + m_usr_usec = tm.m_usr_usec; + m_sys_usec = tm.m_sys_usec; } - int characters_converted (void) const { return m_nchars; } + return *this; + } - ~strptime (void) = default; + OCTAVE_API void stamp (void); - private: + double user (void) const + { + return as_double (m_usr_sec, m_usr_usec); + } - int m_nchars; + double system (void) const + { + return as_double (m_sys_sec, m_sys_usec); + } - OCTAVE_API void init (const std::string& str, const std::string& fmt); - }; + OCTAVE_TIME_T user_sec (void) const { return m_usr_sec; } + long user_usec (void) const { return m_usr_usec; } - class - cpu_time - { - public: + OCTAVE_TIME_T system_sec (void) const { return m_sys_sec; } + long system_usec (void) const { return m_sys_usec; } + +private: + + OCTAVE_TIME_T m_usr_sec; + OCTAVE_TIME_T m_sys_sec; + + long m_usr_usec; + long m_sys_usec; - friend class resource_usage; + cpu_time (OCTAVE_TIME_T usr_sec, OCTAVE_TIME_T sys_sec, long usr_usec, long sys_usec) + : m_usr_sec (usr_sec), m_sys_sec (sys_sec), + m_usr_usec (usr_usec), m_sys_usec (sys_usec) + { } +}; - cpu_time (void) - : m_usr_sec (0), m_sys_sec (0), m_usr_usec (0), m_sys_usec (0) - { - stamp (); - } +class +resource_usage +{ +public: - cpu_time (const cpu_time& tm) - : m_usr_sec (tm.m_usr_sec), m_sys_sec (tm.m_sys_sec), - m_usr_usec (tm.m_usr_usec), m_sys_usec (tm.m_sys_usec) - { } + resource_usage (void) + : m_cpu (), m_maxrss (0), m_ixrss (0), m_idrss (0), + m_isrss (0), m_minflt (0), m_majflt (0), m_nswap (0), + m_inblock (0), m_oublock (0), m_msgsnd (0), m_msgrcv (0), + m_nsignals (0), m_nvcsw (0), m_nivcsw (0) + { + stamp (); + } - cpu_time& operator = (const cpu_time& tm) + resource_usage (const resource_usage& ru) + : m_cpu (ru.m_cpu), m_maxrss (ru.m_maxrss), + m_ixrss (ru.m_ixrss), m_idrss (ru.m_idrss), + m_isrss (ru.m_isrss), m_minflt (ru.m_minflt), + m_majflt (ru.m_majflt), m_nswap (ru.m_nswap), + m_inblock (ru.m_inblock), m_oublock (ru.m_oublock), + m_msgsnd (ru.m_msgsnd), m_msgrcv (ru.m_msgrcv), + m_nsignals (ru.m_nsignals), m_nvcsw (ru.m_nvcsw), + m_nivcsw (ru.m_nivcsw) + { } + + resource_usage& operator = (const resource_usage& ru) + { + if (&ru != this) { - if (&tm != this) - { - m_usr_sec = tm.m_usr_sec; - m_sys_sec = tm.m_sys_sec; - m_usr_usec = tm.m_usr_usec; - m_sys_usec = tm.m_sys_usec; - } - - return *this; - } + m_cpu = ru.m_cpu; - OCTAVE_API void stamp (void); - - double user (void) const - { - return as_double (m_usr_sec, m_usr_usec); - } - - double system (void) const - { - return as_double (m_sys_sec, m_sys_usec); + m_maxrss = ru.m_maxrss; + m_ixrss = ru.m_ixrss; + m_idrss = ru.m_idrss; + m_isrss = ru.m_isrss; + m_minflt = ru.m_minflt; + m_majflt = ru.m_majflt; + m_nswap = ru.m_nswap; + m_inblock = ru.m_inblock; + m_oublock = ru.m_oublock; + m_msgsnd = ru.m_msgsnd; + m_msgrcv = ru.m_msgrcv; + m_nsignals = ru.m_nsignals; + m_nvcsw = ru.m_nvcsw; + m_nivcsw = ru.m_nivcsw; } - OCTAVE_TIME_T user_sec (void) const { return m_usr_sec; } - long user_usec (void) const { return m_usr_usec; } - - OCTAVE_TIME_T system_sec (void) const { return m_sys_sec; } - long system_usec (void) const { return m_sys_usec; } - - private: - - OCTAVE_TIME_T m_usr_sec; - OCTAVE_TIME_T m_sys_sec; - - long m_usr_usec; - long m_sys_usec; - - cpu_time (OCTAVE_TIME_T usr_sec, OCTAVE_TIME_T sys_sec, long usr_usec, long sys_usec) - : m_usr_sec (usr_sec), m_sys_sec (sys_sec), - m_usr_usec (usr_usec), m_sys_usec (sys_usec) - { } - }; - - class - resource_usage - { - public: + return *this; + } - resource_usage (void) - : m_cpu (), m_maxrss (0), m_ixrss (0), m_idrss (0), - m_isrss (0), m_minflt (0), m_majflt (0), m_nswap (0), - m_inblock (0), m_oublock (0), m_msgsnd (0), m_msgrcv (0), - m_nsignals (0), m_nvcsw (0), m_nivcsw (0) - { - stamp (); - } + OCTAVE_API void stamp (void); - resource_usage (const resource_usage& ru) - : m_cpu (ru.m_cpu), m_maxrss (ru.m_maxrss), - m_ixrss (ru.m_ixrss), m_idrss (ru.m_idrss), - m_isrss (ru.m_isrss), m_minflt (ru.m_minflt), - m_majflt (ru.m_majflt), m_nswap (ru.m_nswap), - m_inblock (ru.m_inblock), m_oublock (ru.m_oublock), - m_msgsnd (ru.m_msgsnd), m_msgrcv (ru.m_msgrcv), - m_nsignals (ru.m_nsignals), m_nvcsw (ru.m_nvcsw), - m_nivcsw (ru.m_nivcsw) - { } - - resource_usage& operator = (const resource_usage& ru) - { - if (&ru != this) - { - m_cpu = ru.m_cpu; + cpu_time cpu (void) const { return m_cpu; } - m_maxrss = ru.m_maxrss; - m_ixrss = ru.m_ixrss; - m_idrss = ru.m_idrss; - m_isrss = ru.m_isrss; - m_minflt = ru.m_minflt; - m_majflt = ru.m_majflt; - m_nswap = ru.m_nswap; - m_inblock = ru.m_inblock; - m_oublock = ru.m_oublock; - m_msgsnd = ru.m_msgsnd; - m_msgrcv = ru.m_msgrcv; - m_nsignals = ru.m_nsignals; - m_nvcsw = ru.m_nvcsw; - m_nivcsw = ru.m_nivcsw; - } + long maxrss (void) const { return m_maxrss; } + long ixrss (void) const { return m_ixrss; } + long idrss (void) const { return m_idrss; } + long isrss (void) const { return m_isrss; } + long minflt (void) const { return m_minflt; } + long majflt (void) const { return m_majflt; } + long nswap (void) const { return m_nswap; } + long inblock (void) const { return m_inblock; } + long oublock (void) const { return m_oublock; } + long msgsnd (void) const { return m_msgsnd; } + long msgrcv (void) const { return m_msgrcv; } + long nsignals (void) const { return m_nsignals; } + long nvcsw (void) const { return m_nvcsw; } + long nivcsw (void) const { return m_nivcsw; } - return *this; - } - - OCTAVE_API void stamp (void); - - cpu_time cpu (void) const { return m_cpu; } +private: - long maxrss (void) const { return m_maxrss; } - long ixrss (void) const { return m_ixrss; } - long idrss (void) const { return m_idrss; } - long isrss (void) const { return m_isrss; } - long minflt (void) const { return m_minflt; } - long majflt (void) const { return m_majflt; } - long nswap (void) const { return m_nswap; } - long inblock (void) const { return m_inblock; } - long oublock (void) const { return m_oublock; } - long msgsnd (void) const { return m_msgsnd; } - long msgrcv (void) const { return m_msgrcv; } - long nsignals (void) const { return m_nsignals; } - long nvcsw (void) const { return m_nvcsw; } - long nivcsw (void) const { return m_nivcsw; } - - private: + cpu_time m_cpu; - cpu_time m_cpu; - - long m_maxrss; - long m_ixrss; - long m_idrss; - long m_isrss; - long m_minflt; - long m_majflt; - long m_nswap; - long m_inblock; - long m_oublock; - long m_msgsnd; - long m_msgrcv; - long m_nsignals; - long m_nvcsw; - long m_nivcsw; - }; + long m_maxrss; + long m_ixrss; + long m_idrss; + long m_isrss; + long m_minflt; + long m_majflt; + long m_nswap; + long m_inblock; + long m_oublock; + long m_msgsnd; + long m_msgrcv; + long m_nsignals; + long m_nvcsw; + long m_nivcsw; +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-uname.cc --- a/liboctave/system/oct-uname.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-uname.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,26 +37,26 @@ OCTAVE_BEGIN_NAMESPACE(sys) - void - uname::init (void) - { - char *sysname, *nodename, *release, *version, *machine; +void +uname::init (void) +{ + char *sysname, *nodename, *release, *version, *machine; - m_errno = octave_uname_wrapper (&sysname, &nodename, &release, - &version, &machine); + m_errno = octave_uname_wrapper (&sysname, &nodename, &release, + &version, &machine); - if (m_errno < 0) - m_errmsg = std::strerror (errno); - else - { - m_sysname = sysname; - m_nodename = nodename; - m_release = release; - m_version = version; - m_machine = machine; - m_errmsg = ""; - } + if (m_errno < 0) + m_errmsg = std::strerror (errno); + else + { + m_sysname = sysname; + m_nodename = nodename; + m_release = release; + m_version = version; + m_machine = machine; + m_errmsg = ""; } +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/system/oct-uname.h --- a/liboctave/system/oct-uname.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/system/oct-uname.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,67 +34,67 @@ OCTAVE_BEGIN_NAMESPACE(sys) - class - OCTAVE_API - uname - { - public: +class +OCTAVE_API +uname +{ +public: - uname (void) - : m_sysname ("unknown"), m_nodename ("unknown"), - m_release ("unknown"), m_version ("unknown"), - m_machine ("unknown"), - m_errmsg ("uname not supported on this system"), m_errno (-1) - { init (); } + uname (void) + : m_sysname ("unknown"), m_nodename ("unknown"), + m_release ("unknown"), m_version ("unknown"), + m_machine ("unknown"), + m_errmsg ("uname not supported on this system"), m_errno (-1) + { init (); } - uname (const uname& unm) - : m_sysname (unm.m_sysname), m_nodename (unm.m_nodename), - m_release (unm.m_release), m_version (unm.m_version), - m_machine (unm.m_machine), - m_errmsg (unm.m_errmsg), m_errno (unm.m_errno) - { } + uname (const uname& unm) + : m_sysname (unm.m_sysname), m_nodename (unm.m_nodename), + m_release (unm.m_release), m_version (unm.m_version), + m_machine (unm.m_machine), + m_errmsg (unm.m_errmsg), m_errno (unm.m_errno) + { } - uname& operator = (const uname& unm) + uname& operator = (const uname& unm) + { + if (this != &unm) { - if (this != &unm) - { - m_sysname = unm.m_sysname; - m_nodename = unm.m_nodename; - m_release = unm.m_release; - m_version = unm.m_version; - m_machine = unm.m_machine; + m_sysname = unm.m_sysname; + m_nodename = unm.m_nodename; + m_release = unm.m_release; + m_version = unm.m_version; + m_machine = unm.m_machine; - m_errmsg = unm.m_errmsg; - m_errno = unm.m_errno; - } - - return *this; + m_errmsg = unm.m_errmsg; + m_errno = unm.m_errno; } - ~uname (void) = default; + return *this; + } + + ~uname (void) = default; - std::string sysname (void) const { return m_sysname; } - std::string nodename (void) const { return m_nodename; } - std::string release (void) const { return m_release; } - std::string version (void) const { return m_version; } - std::string machine (void) const { return m_machine; } + std::string sysname (void) const { return m_sysname; } + std::string nodename (void) const { return m_nodename; } + std::string release (void) const { return m_release; } + std::string version (void) const { return m_version; } + std::string machine (void) const { return m_machine; } - std::string message (void) const { return m_errmsg; } - int error (void) const { return m_errno; } + std::string message (void) const { return m_errmsg; } + int error (void) const { return m_errno; } - private: +private: - std::string m_sysname; - std::string m_nodename; - std::string m_release; - std::string m_version; - std::string m_machine; + std::string m_sysname; + std::string m_nodename; + std::string m_release; + std::string m_version; + std::string m_machine; - std::string m_errmsg; - int m_errno; + std::string m_errmsg; + int m_errno; - void init (void); - }; + void init (void); +}; OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/action-container.cc --- a/liboctave/util/action-container.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/action-container.cc Thu Dec 01 20:05:44 2022 -0800 @@ -32,25 +32,25 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void action_container::run (std::size_t num) - { - if (num > size ()) - num = size (); +void action_container::run (std::size_t num) +{ + if (num > size ()) + num = size (); - for (std::size_t i = 0; i < num; i++) - { - run_first (); + for (std::size_t i = 0; i < num; i++) + { + run_first (); - // If event_loop_interrupted is TRUE, a user callback event has - // requested that we break out of the readline event handler to - // process a command or other action. + // If event_loop_interrupted is TRUE, a user callback event has + // requested that we break out of the readline event handler to + // process a command or other action. - if (command_editor::event_loop_interrupted ()) - { - command_editor::interrupt_event_loop (false); - break; - } - } - } + if (command_editor::event_loop_interrupted ()) + { + command_editor::interrupt_event_loop (false); + break; + } + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/action-container.h --- a/liboctave/util/action-container.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/action-container.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,189 +39,189 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - action_container +class +action_container +{ +public: + + // A generic unwind_protect element. Knows how to run itself and + // discard itself. Also, contains a pointer to the next element. + class elem + { + public: + + friend class action_container; + + elem (void) { } + + // No copying! + + elem (const elem&) = delete; + + elem& operator = (const elem&) = delete; + + virtual ~elem (void) = default; + + virtual void run (void) { } + }; + + // An element that merely runs a void (*)(void) function. + + class fcn_elem : public elem + { + public: + + // FIXME: Do we need to apply std::forward to the arguments to + // std::bind here? + + template + fcn_elem (F&& fcn, Args&& ... args) + : m_fcn (std::bind (fcn, args...)) + { } + + void run (void) { m_fcn (); } + + private: + + std::function m_fcn; + }; + + // An element that stores arbitrary variable, and restores it. + + template + class restore_var_elem : public elem + { + public: + + restore_var_elem (T& ref, const T& val) + : m_ptr (&ref), m_val (val) { } + + // No copying! + + restore_var_elem (const restore_var_elem&) = delete; + + restore_var_elem& operator = (const restore_var_elem&) = delete; + + void run (void) { *m_ptr = m_val; } + + private: + + T *m_ptr, m_val; + }; + + // Deletes a class allocated using new. + + template + class delete_ptr_elem : public elem { public: - // A generic unwind_protect element. Knows how to run itself and - // discard itself. Also, contains a pointer to the next element. - class elem - { - public: - - friend class action_container; - - elem (void) { } - - // No copying! - - elem (const elem&) = delete; - - elem& operator = (const elem&) = delete; - - virtual ~elem (void) = default; - - virtual void run (void) { } - }; - - // An element that merely runs a void (*)(void) function. - - class fcn_elem : public elem - { - public: - - // FIXME: Do we need to apply std::forward to the arguments to - // std::bind here? - - template - fcn_elem (F&& fcn, Args&&... args) - : m_fcn (std::bind (fcn, args...)) - { } - - void run (void) { m_fcn (); } - - private: - - std::function m_fcn; - }; - - // An element that stores arbitrary variable, and restores it. - - template - class restore_var_elem : public elem - { - public: - - restore_var_elem (T& ref, const T& val) - : m_ptr (&ref), m_val (val) { } - - // No copying! - - restore_var_elem (const restore_var_elem&) = delete; - - restore_var_elem& operator = (const restore_var_elem&) = delete; - - void run (void) { *m_ptr = m_val; } - - private: - - T *m_ptr, m_val; - }; - - // Deletes a class allocated using new. - - template - class delete_ptr_elem : public elem - { - public: - - delete_ptr_elem (T *ptr) - : m_ptr (ptr) { } - - // No copying! - - delete_ptr_elem (const delete_ptr_elem&) = delete; - - delete_ptr_elem operator = (const delete_ptr_elem&) = delete; - - void run (void) { delete m_ptr; } - - private: - - T *m_ptr; - }; - - action_container (void) { } + delete_ptr_elem (T *ptr) + : m_ptr (ptr) { } // No copying! - action_container (const action_container&) = delete; + delete_ptr_elem (const delete_ptr_elem&) = delete; + + delete_ptr_elem operator = (const delete_ptr_elem&) = delete; - action_container& operator = (const action_container&) = delete; + void run (void) { delete m_ptr; } - virtual ~action_container (void) = default; + private: - template - void add (F&& fcn, Args&&... args) - { - add_action (new fcn_elem (std::forward (fcn), - std::forward (args)...)); - } + T *m_ptr; + }; + + action_container (void) { } - // Use separate template types for function pointer parameter - // declarations and captured arguments so that differences in - // const are handled properly. + // No copying! + + action_container (const action_container&) = delete; + + action_container& operator = (const action_container&) = delete; + + virtual ~action_container (void) = default; - template - void add_fcn (void (*fcn) (Params...), Args&&... args) - { - add_action (new fcn_elem (fcn, std::forward (args)...)); - } + template + void add (F&& fcn, Args&& ... args) + { + add_action (new fcn_elem (std::forward (fcn), + std::forward (args)...)); + } - template - void add_method (T *obj, void (T::*method) (Params...), Args&&... args) - { - add_action (new fcn_elem (method, obj, std::forward (args)...)); - } + // Use separate template types for function pointer parameter + // declarations and captured arguments so that differences in + // const are handled properly. - template - void add_method (T& obj, void (T::*method) (Params...), Args&&... args) - { - add_action (new fcn_elem (method, &obj, std::forward (args)...)); - } + template + void add_fcn (void (*fcn) (Params...), Args&& ... args) + { + add_action (new fcn_elem (fcn, std::forward (args)...)); + } - // Call to delete (T*). + template + void add_method (T *obj, void (T::*method) (Params...), Args&& ... args) + { + add_action (new fcn_elem (method, obj, std::forward (args)...)); + } - template - void add_delete (T *obj) - { - add_action (new delete_ptr_elem (obj)); - } + template + void add_method (T& obj, void (T::*method) (Params...), Args&& ... args) + { + add_action (new fcn_elem (method, &obj, std::forward (args)...)); + } - // Protect any variable. - template - void protect_var (T& var) - { - add_action (new restore_var_elem (var, var)); - } + // Call to delete (T*). + + template + void add_delete (T *obj) + { + add_action (new delete_ptr_elem (obj)); + } - // Protect any variable, value given. - template - void protect_var (T& var, const T& val) - { - add_action (new restore_var_elem (var, val)); - } + // Protect any variable. + template + void protect_var (T& var) + { + add_action (new restore_var_elem (var, var)); + } - operator bool (void) const { return ! empty (); } - - virtual void run_first (void) = 0; + // Protect any variable, value given. + template + void protect_var (T& var, const T& val) + { + add_action (new restore_var_elem (var, val)); + } - OCTAVE_API void run (std::size_t num); + operator bool (void) const { return ! empty (); } - void run (void) { run (size ()); } + virtual void run_first (void) = 0; - virtual void discard_first (void) = 0; + OCTAVE_API void run (std::size_t num); + + void run (void) { run (size ()); } - void discard (std::size_t num) - { - if (num > size ()) - num = size (); + virtual void discard_first (void) = 0; - for (std::size_t i = 0; i < num; i++) - discard_first (); - } + void discard (std::size_t num) + { + if (num > size ()) + num = size (); - void discard (void) { discard (size ()); } + for (std::size_t i = 0; i < num; i++) + discard_first (); + } - virtual std::size_t size (void) const = 0; + void discard (void) { discard (size ()); } - bool empty (void) const { return size () == 0; } + virtual std::size_t size (void) const = 0; + + bool empty (void) const { return size () == 0; } - protected: +protected: - virtual void add_action (elem *new_elem) = 0; - }; + virtual void add_action (elem *new_elem) = 0; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/base-list.h --- a/liboctave/util/base-list.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/base-list.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,77 +34,77 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template - class - base_list - { - public: +template +class +base_list +{ +public: - typedef typename std::list::iterator iterator; - typedef typename std::list::const_iterator const_iterator; + typedef typename std::list::iterator iterator; + typedef typename std::list::const_iterator const_iterator; - typedef typename std::list::reverse_iterator reverse_iterator; - typedef typename std::list::const_reverse_iterator - const_reverse_iterator; + typedef typename std::list::reverse_iterator reverse_iterator; + typedef typename std::list::const_reverse_iterator + const_reverse_iterator; - bool empty (void) const { return m_lst.empty (); } + bool empty (void) const { return m_lst.empty (); } - std::size_t size (void) const { return m_lst.size (); } - std::size_t length (void) const { return size (); } + std::size_t size (void) const { return m_lst.size (); } + std::size_t length (void) const { return size (); } - iterator erase (iterator pos) { return m_lst.erase (pos); } + iterator erase (iterator pos) { return m_lst.erase (pos); } - template - void remove_if (P pred) - { - m_lst.remove_if (pred); - } + template + void remove_if (P pred) + { + m_lst.remove_if (pred); + } - void clear (void) { m_lst.clear (); } + void clear (void) { m_lst.clear (); } - iterator begin (void) { return iterator (m_lst.begin ()); } - const_iterator begin (void) const { return const_iterator (m_lst.begin ()); } + iterator begin (void) { return iterator (m_lst.begin ()); } + const_iterator begin (void) const { return const_iterator (m_lst.begin ()); } - iterator end (void) { return iterator (m_lst.end ()); } - const_iterator end (void) const { return const_iterator (m_lst.end ()); } + iterator end (void) { return iterator (m_lst.end ()); } + const_iterator end (void) const { return const_iterator (m_lst.end ()); } - reverse_iterator rbegin (void) { return reverse_iterator (m_lst.rbegin ()); } - const_reverse_iterator rbegin (void) const - { return const_reverse_iterator (m_lst.rbegin ()); } + reverse_iterator rbegin (void) { return reverse_iterator (m_lst.rbegin ()); } + const_reverse_iterator rbegin (void) const + { return const_reverse_iterator (m_lst.rbegin ()); } - reverse_iterator rend (void) { return reverse_iterator (m_lst.rend ()); } - const_reverse_iterator rend (void) const - { return const_reverse_iterator (m_lst.rend ()); } + reverse_iterator rend (void) { return reverse_iterator (m_lst.rend ()); } + const_reverse_iterator rend (void) const + { return const_reverse_iterator (m_lst.rend ()); } - elt_type& front (void) { return m_lst.front (); } - elt_type& back (void) { return m_lst.back (); } + elt_type& front (void) { return m_lst.front (); } + elt_type& back (void) { return m_lst.back (); } - const elt_type& front (void) const { return m_lst.front (); } - const elt_type& back (void) const { return m_lst.back (); } + const elt_type& front (void) const { return m_lst.front (); } + const elt_type& back (void) const { return m_lst.back (); } - void push_front (const elt_type& s) { m_lst.push_front (s); } - void push_back (const elt_type& s) { m_lst.push_back (s); } + void push_front (const elt_type& s) { m_lst.push_front (s); } + void push_back (const elt_type& s) { m_lst.push_back (s); } - void pop_front (void) { m_lst.pop_front (); } - void pop_back (void) { m_lst.pop_back (); } + void pop_front (void) { m_lst.pop_front (); } + void pop_back (void) { m_lst.pop_back (); } - // For backward compatibility. - void append (const elt_type& s) { m_lst.push_back (s); } + // For backward compatibility. + void append (const elt_type& s) { m_lst.push_back (s); } - base_list (void) = default; + base_list (void) = default; - base_list (const std::list& l) : m_lst (l) { } + base_list (const std::list& l) : m_lst (l) { } - base_list (const base_list& bl) = default; + base_list (const base_list& bl) = default; - base_list& operator = (const base_list& bl) = default; + base_list& operator = (const base_list& bl) = default; - virtual ~base_list (void) = default; + virtual ~base_list (void) = default; - protected: +protected: - std::list m_lst; - }; + std::list m_lst; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/cmd-edit.cc --- a/liboctave/util/cmd-edit.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/cmd-edit.cc Thu Dec 01 20:05:44 2022 -0800 @@ -54,1916 +54,1916 @@ OCTAVE_BEGIN_NAMESPACE(octave) - char * do_completer_word_break_hook (); +char * do_completer_word_break_hook (); - command_editor *command_editor::s_instance = nullptr; +command_editor *command_editor::s_instance = nullptr; - std::set command_editor::m_startup_hook_set; +std::set command_editor::m_startup_hook_set; - std::set command_editor::m_pre_input_hook_set; +std::set command_editor::m_pre_input_hook_set; - std::set command_editor::m_event_hook_set; +std::set command_editor::m_event_hook_set; - static mutex event_hook_lock; +static mutex event_hook_lock; #if defined (USE_READLINE) - class - gnu_readline : public command_editor - { - public: - - typedef command_editor::startup_hook_fcn startup_hook_fcn; - - typedef command_editor::pre_input_hook_fcn pre_input_hook_fcn; - - typedef command_editor::event_hook_fcn event_hook_fcn; - - typedef command_editor::completion_fcn completion_fcn; - - gnu_readline (void); - - ~gnu_readline (void) = default; - - void do_set_name (const std::string& n); - - std::string do_readline (const std::string& prompt, bool& eof); - - void do_set_input_stream (FILE *f); - - FILE * do_get_input_stream (void); - - void do_set_output_stream (FILE *f); - - FILE * do_get_output_stream (void); - - void do_redisplay (void); +class +gnu_readline : public command_editor +{ +public: - int do_terminal_rows (void); - - int do_terminal_cols (void); - - void do_clear_screen (bool skip_redisplay); - - void do_resize_terminal (void); - - void do_set_screen_size (int ht, int wd); - - std::string newline_chars (void); - - void do_restore_terminal_state (void); - - void do_blink_matching_paren (bool flag); + typedef command_editor::startup_hook_fcn startup_hook_fcn; - bool do_erase_empty_line (bool flag); - - void do_set_basic_word_break_characters (const std::string& s); - - void do_set_completer_word_break_characters (const std::string& s); - - void do_set_basic_quote_characters (const std::string& s); - - void do_set_filename_quote_characters (const std::string& s); - - void do_set_completer_quote_characters (const std::string& s); - - void do_set_completion_append_character (char c); - - void do_set_completion_function (completion_fcn f); - - void do_set_quoting_function (quoting_fcn f); + typedef command_editor::pre_input_hook_fcn pre_input_hook_fcn; - void do_set_dequoting_function (dequoting_fcn f); - - void do_set_char_is_quoted_function (char_is_quoted_fcn f); - - void do_set_user_accept_line_function (user_accept_line_fcn f); - - completion_fcn do_get_completion_function (void) const; - - quoting_fcn do_get_quoting_function (void) const; - - dequoting_fcn do_get_dequoting_function (void) const; - - char_is_quoted_fcn do_get_char_is_quoted_function (void) const; + typedef command_editor::event_hook_fcn event_hook_fcn; - user_accept_line_fcn do_get_user_accept_line_function (void) const; - - string_vector - do_generate_filename_completions (const std::string& text); - - std::string do_get_line_buffer (void) const; - - std::string do_get_current_line (void) const; - - char do_get_prev_char (int) const; - - void do_replace_line (const std::string& text, bool clear_undo); - - void do_kill_full_line (void); - - void do_insert_text (const std::string& text); + typedef command_editor::completion_fcn completion_fcn; - void do_newline (void); - - void do_accept_line (void); - - bool do_undo (void); - - void do_clear_undo_list (void); - - void set_startup_hook (startup_hook_fcn f); - - void restore_startup_hook (void); - - void set_pre_input_hook (pre_input_hook_fcn f); - - void restore_pre_input_hook (void); + gnu_readline (void); - void set_event_hook (event_hook_fcn f); - - void restore_event_hook (void); - - void do_restore_event_hook (void); - - void do_read_init_file (const std::string& file); + ~gnu_readline (void) = default; - void do_re_read_init_file (void); - - bool do_filename_completion_desired (bool); - - bool do_filename_quoting_desired (bool); - - bool do_prefer_env_winsize (bool); - - void do_interrupt (bool); + void do_set_name (const std::string& n); - void do_handle_interrupt_signal (void); - - static int operate_and_get_next (int, int); - - static int history_search_backward (int, int); - - static int history_search_forward (int, int); - - private: - - static char * command_generator (const char *text, int state); - - static char * command_quoter (char *text, int match_type, - char *quote_pointer); + std::string do_readline (const std::string& prompt, bool& eof); - static char * command_dequoter (char *text, int match_type); - - static int command_char_is_quoted (char *text, int index); - - static int command_accept_line (int count, int key); - - static char ** command_completer (const char *text, int start, int end); - - static char * do_completer_word_break_hook (); - - startup_hook_fcn m_previous_startup_hook; - - pre_input_hook_fcn m_previous_pre_input_hook; - - event_hook_fcn m_previous_event_hook; + void do_set_input_stream (FILE *f); - completion_fcn m_completion_function; - - quoting_fcn m_quoting_function; - - dequoting_fcn m_dequoting_function; - - char_is_quoted_fcn m_char_is_quoted_function; - - user_accept_line_fcn user_accept_line_function; - - static std::string s_completer_quote_characters; - }; - - std::string gnu_readline::s_completer_quote_characters = ""; + FILE * do_get_input_stream (void); - gnu_readline::gnu_readline () - : command_editor (), m_previous_startup_hook (nullptr), - m_previous_pre_input_hook (nullptr), - m_previous_event_hook (nullptr), m_completion_function (nullptr), - m_quoting_function (nullptr), m_dequoting_function (nullptr), - m_char_is_quoted_function (nullptr), user_accept_line_function (nullptr) - { - // FIXME: need interface to rl_add_defun, rl_initialize, and - // a function to set rl_terminal_name + void do_set_output_stream (FILE *f); - std::string term = sys::env::getenv ("TERM"); - - octave_rl_set_terminal_name (term.c_str ()); - - octave_rl_initialize (); - - do_blink_matching_paren (true); + FILE * do_get_output_stream (void); - // Bind operate-and-get-next. - - octave_rl_add_defun ("operate-and-get-next", - gnu_readline::operate_and_get_next, - octave_rl_ctrl ('O')); - } - - void - gnu_readline::do_set_name (const std::string& nm) - { - ::octave_rl_set_name (nm.c_str ()); - } + void do_redisplay (void); - std::string - gnu_readline::do_readline (const std::string& prompt, bool& eof) - { - std::string retval; - - eof = false; - - const char *p = prompt.c_str (); - - char *line = ::octave_rl_readline (p); - - if (line) - { - retval = line; - - free (line); - } - else - eof = true; + int do_terminal_rows (void); - return retval; - } - - void - gnu_readline::do_set_input_stream (FILE *f) - { - ::octave_rl_set_input_stream (f); - } - - FILE * - gnu_readline::do_get_input_stream (void) - { - return ::octave_rl_get_input_stream (); - } + int do_terminal_cols (void); - void - gnu_readline::do_set_output_stream (FILE *f) - { - ::octave_rl_set_output_stream (f); - } + void do_clear_screen (bool skip_redisplay); - FILE * - gnu_readline::do_get_output_stream (void) - { - return ::octave_rl_get_output_stream (); - } - - void - gnu_readline::do_redisplay (void) - { - ::octave_rl_redisplay (); - } + void do_resize_terminal (void); - // GNU readline handles SIGWINCH, so these values have a good chance - // of being correct even if the window changes size (they may be - // wrong if, for example, the luser changes the window size while the - // pager is running, and the signal is handled by the pager instead of - // us. - - int - gnu_readline::do_terminal_rows (void) - { - int sh = ::octave_rl_screen_height (); - - return sh > 0 ? sh : 24; - } + void do_set_screen_size (int ht, int wd); - int - gnu_readline::do_terminal_cols (void) - { - int sw = ::octave_rl_screen_width (); - - return sw > 0 ? sw : 80; - } - - void - gnu_readline::do_clear_screen (bool skip_redisplay) - { - ::octave_rl_clear_screen (skip_redisplay); - } + std::string newline_chars (void); - void - gnu_readline::do_resize_terminal (void) - { - ::octave_rl_resize_terminal (); - } - - void - gnu_readline::do_set_screen_size (int ht, int wd) - { - ::octave_rl_set_screen_size (ht, wd); - } - - std::string - gnu_readline::newline_chars (void) - { - return "\r\n"; - } + void do_restore_terminal_state (void); - void - gnu_readline::do_restore_terminal_state (void) - { - ::octave_rl_restore_terminal_state (); - } + void do_blink_matching_paren (bool flag); - void - gnu_readline::do_blink_matching_paren (bool flag) - { - ::octave_rl_enable_paren_matching (flag ? 1 : 0); - } - - bool - gnu_readline::do_erase_empty_line (bool flag) - { - return ::octave_rl_erase_empty_line (flag ? 1 : 0); - } + bool do_erase_empty_line (bool flag); - void - gnu_readline::do_set_basic_word_break_characters (const std::string& s) - { - ::octave_rl_set_basic_word_break_characters (s.c_str ()); - } - - void - gnu_readline::do_set_completer_word_break_characters (const std::string& s) - { - ::octave_rl_set_completer_word_break_characters (s.c_str ()); - - ::octave_rl_set_completion_word_break_hook - (gnu_readline::do_completer_word_break_hook); + void do_set_basic_word_break_characters (const std::string& s); - } - - void - gnu_readline::do_set_basic_quote_characters (const std::string& s) - { - ::octave_rl_set_basic_quote_characters (s.c_str ()); - } - - void - gnu_readline::do_set_filename_quote_characters (const std::string& s) - { - ::octave_rl_set_filename_quote_characters (s.c_str ()); - } + void do_set_completer_word_break_characters (const std::string& s); - void - gnu_readline::do_set_completer_quote_characters (const std::string& s) - { - s_completer_quote_characters = s; - } - - void - gnu_readline::do_set_completion_append_character (char c) - { - ::octave_rl_set_completion_append_character (c); - } - - void - gnu_readline::do_set_completion_function (completion_fcn f) - { - m_completion_function = f; + void do_set_basic_quote_characters (const std::string& s); - rl_attempted_completion_fcn_ptr fp - = (f ? gnu_readline::command_completer : nullptr); - - ::octave_rl_set_completion_function (fp); - } - - void - gnu_readline::do_set_quoting_function (quoting_fcn f) - { - m_quoting_function = f; + void do_set_filename_quote_characters (const std::string& s); - rl_quoting_fcn_ptr fp - = (f ? gnu_readline::command_quoter : nullptr); - - ::octave_rl_set_quoting_function (fp); - } - - void - gnu_readline::do_set_dequoting_function (dequoting_fcn f) - { - m_dequoting_function = f; + void do_set_completer_quote_characters (const std::string& s); - rl_dequoting_fcn_ptr fp - = (f ? gnu_readline::command_dequoter : nullptr); - - ::octave_rl_set_dequoting_function (fp); - } - - void - gnu_readline::do_set_char_is_quoted_function (char_is_quoted_fcn f) - { - m_char_is_quoted_function = f; - - rl_char_is_quoted_fcn_ptr fp - = (f ? gnu_readline::command_char_is_quoted : nullptr); + void do_set_completion_append_character (char c); - ::octave_rl_set_char_is_quoted_function (fp); - } - - void - gnu_readline::do_set_user_accept_line_function (user_accept_line_fcn f) - { - user_accept_line_function = f; - - if (f) - octave_rl_add_defun ("accept-line", gnu_readline::command_accept_line, - ::octave_rl_ctrl ('M')); - else - octave_rl_add_defun ("accept-line", ::octave_rl_newline, - ::octave_rl_ctrl ('M')); - } + void do_set_completion_function (completion_fcn f); - gnu_readline::completion_fcn - gnu_readline::do_get_completion_function (void) const - { - return m_completion_function; - } - - gnu_readline::quoting_fcn - gnu_readline::do_get_quoting_function (void) const - { - return m_quoting_function; - } - - gnu_readline::dequoting_fcn - gnu_readline::do_get_dequoting_function (void) const - { - return m_dequoting_function; - } + void do_set_quoting_function (quoting_fcn f); - gnu_readline::char_is_quoted_fcn - gnu_readline::do_get_char_is_quoted_function (void) const - { - return m_char_is_quoted_function; - } + void do_set_dequoting_function (dequoting_fcn f); - gnu_readline::user_accept_line_fcn - gnu_readline::do_get_user_accept_line_function (void) const - { - return user_accept_line_function; - } - - // True if the last "word" of the string line (delimited by delim) is - // an existing directory. Used by do_completer_word_break_hook. - - static bool - looks_like_filename (const char *line, char delim) - { - bool retval = false; + void do_set_char_is_quoted_function (char_is_quoted_fcn f); - const char *s = strrchr (line, delim); - - if (s) - { - // Remove incomplete component. - const char *f = strrchr (line, sys::file_ops::dir_sep_char ()); - - if (f && (s[1] == '~' || f != s)) - { - // For something like "A /b", f==s; don't assume a file. - - std::string candidate_filename = s+1; - - candidate_filename = candidate_filename.substr (0, f - s); - - // Handles any complete ~, but doesn't expand usernames. + void do_set_user_accept_line_function (user_accept_line_fcn f); - if (candidate_filename[0] == '~') - candidate_filename - = sys::file_ops::tilde_expand (candidate_filename); - - sys::file_stat fs (candidate_filename); + completion_fcn do_get_completion_function (void) const; - retval = fs.is_dir (); - } - } - - return retval; - } - - // Decide whether to interpret partial commands like "abc/def" as a - // filename or division. Return the set of delimiters appropriate for - // the decision. + quoting_fcn do_get_quoting_function (void) const; - char * - gnu_readline::do_completer_word_break_hook () - { - static char *dir_sep = octave_strdup_wrapper (R"( '")"); - - std::string word; - std::string line = get_line_buffer (); - - // For now, assume space or quote delimiter for file names. - const char *l = line.c_str (); - - if (looks_like_filename (l, ' ') || looks_like_filename (l, '\'') - || looks_like_filename (l, '"')) - { - ::octave_rl_set_completer_quote_characters - (s_completer_quote_characters.c_str ()); + dequoting_fcn do_get_dequoting_function (void) const; - return dir_sep; - } - else - { - static char *word_break_chars = nullptr; - - ::octave_rl_set_completer_quote_characters (""); + char_is_quoted_fcn do_get_char_is_quoted_function (void) const; - free (word_break_chars); - - word_break_chars - = octave_strdup_wrapper (octave_rl_get_completer_word_break_characters ()); - - return word_break_chars; - } - } + user_accept_line_fcn do_get_user_accept_line_function (void) const; string_vector - gnu_readline::do_generate_filename_completions (const std::string& text) - { - string_vector retval; + do_generate_filename_completions (const std::string& text); + + std::string do_get_line_buffer (void) const; + + std::string do_get_current_line (void) const; + + char do_get_prev_char (int) const; + + void do_replace_line (const std::string& text, bool clear_undo); + + void do_kill_full_line (void); + + void do_insert_text (const std::string& text); + + void do_newline (void); + + void do_accept_line (void); + + bool do_undo (void); + + void do_clear_undo_list (void); - int n = 0; - int count = 0; + void set_startup_hook (startup_hook_fcn f); + + void restore_startup_hook (void); + + void set_pre_input_hook (pre_input_hook_fcn f); + + void restore_pre_input_hook (void); + + void set_event_hook (event_hook_fcn f); + + void restore_event_hook (void); - char *fn = nullptr; + void do_restore_event_hook (void); + + void do_read_init_file (const std::string& file); + + void do_re_read_init_file (void); - while (1) - { - fn = ::octave_rl_filename_completion_function (text.c_str (), count); + bool do_filename_completion_desired (bool); + + bool do_filename_quoting_desired (bool); + + bool do_prefer_env_winsize (bool); - if (fn) - { - if (count == n) - { - // Famous last words: Most large directories will not - // have more than a few hundred files, so we should not - // resize too many times even if the growth is linear... - n += 100; - retval.resize (n); - } + void do_interrupt (bool); + + void do_handle_interrupt_signal (void); + + static int operate_and_get_next (int, int); + + static int history_search_backward (int, int); + + static int history_search_forward (int, int); + +private: + + static char * command_generator (const char *text, int state); + + static char * command_quoter (char *text, int match_type, + char *quote_pointer); + + static char * command_dequoter (char *text, int match_type); + + static int command_char_is_quoted (char *text, int index); + + static int command_accept_line (int count, int key); - retval[count++] = fn; + static char ** command_completer (const char *text, int start, int end); + + static char * do_completer_word_break_hook (); + + startup_hook_fcn m_previous_startup_hook; + + pre_input_hook_fcn m_previous_pre_input_hook; + + event_hook_fcn m_previous_event_hook; + + completion_fcn m_completion_function; - free (fn); - } - else - break; - } + quoting_fcn m_quoting_function; + + dequoting_fcn m_dequoting_function; + + char_is_quoted_fcn m_char_is_quoted_function; - retval.resize (count); + user_accept_line_fcn user_accept_line_function; - return retval; - } + static std::string s_completer_quote_characters; +}; + +std::string gnu_readline::s_completer_quote_characters = ""; - std::string - gnu_readline::do_get_line_buffer (void) const - { - return ::octave_rl_line_buffer (); - } +gnu_readline::gnu_readline () + : command_editor (), m_previous_startup_hook (nullptr), + m_previous_pre_input_hook (nullptr), + m_previous_event_hook (nullptr), m_completion_function (nullptr), + m_quoting_function (nullptr), m_dequoting_function (nullptr), + m_char_is_quoted_function (nullptr), user_accept_line_function (nullptr) +{ + // FIXME: need interface to rl_add_defun, rl_initialize, and + // a function to set rl_terminal_name + + std::string term = sys::env::getenv ("TERM"); + + octave_rl_set_terminal_name (term.c_str ()); + + octave_rl_initialize (); + + do_blink_matching_paren (true); + + // Bind operate-and-get-next. - std::string - gnu_readline::do_get_current_line (void) const - { - std::string retval; - char *buf = ::octave_rl_copy_line (); - retval = buf; - free (buf); - return retval; - } + octave_rl_add_defun ("operate-and-get-next", + gnu_readline::operate_and_get_next, + octave_rl_ctrl ('O')); +} + +void +gnu_readline::do_set_name (const std::string& nm) +{ + ::octave_rl_set_name (nm.c_str ()); +} + +std::string +gnu_readline::do_readline (const std::string& prompt, bool& eof) +{ + std::string retval; + + eof = false; + + const char *p = prompt.c_str (); + + char *line = ::octave_rl_readline (p); + + if (line) + { + retval = line; - // Return the character (offset+1) to the left of the cursor, - // or '\0' if the cursor is at the start of the line. - char - gnu_readline::do_get_prev_char (int offset) const - { - const char *buf = ::octave_rl_line_buffer (); - int p = ::octave_rl_point (); + free (line); + } + else + eof = true; + + return retval; +} - return p > offset ? buf[p - offset - 1] : '\0'; - } +void +gnu_readline::do_set_input_stream (FILE *f) +{ + ::octave_rl_set_input_stream (f); +} + +FILE * +gnu_readline::do_get_input_stream (void) +{ + return ::octave_rl_get_input_stream (); +} + +void +gnu_readline::do_set_output_stream (FILE *f) +{ + ::octave_rl_set_output_stream (f); +} - void - gnu_readline::do_replace_line (const std::string& text, bool clear_undo) - { - ::octave_rl_replace_line (text.c_str (), clear_undo); - } +FILE * +gnu_readline::do_get_output_stream (void) +{ + return ::octave_rl_get_output_stream (); +} + +void +gnu_readline::do_redisplay (void) +{ + ::octave_rl_redisplay (); +} - void - gnu_readline::do_kill_full_line (void) - { - ::octave_rl_kill_full_line (); - } +// GNU readline handles SIGWINCH, so these values have a good chance +// of being correct even if the window changes size (they may be +// wrong if, for example, the luser changes the window size while the +// pager is running, and the signal is handled by the pager instead of +// us. + +int +gnu_readline::do_terminal_rows (void) +{ + int sh = ::octave_rl_screen_height (); + + return sh > 0 ? sh : 24; +} - void - gnu_readline::do_insert_text (const std::string& text) - { - ::octave_rl_insert_text (text.c_str ()); - } +int +gnu_readline::do_terminal_cols (void) +{ + int sw = ::octave_rl_screen_width (); + + return sw > 0 ? sw : 80; +} + +void +gnu_readline::do_clear_screen (bool skip_redisplay) +{ + ::octave_rl_clear_screen (skip_redisplay); +} + +void +gnu_readline::do_resize_terminal (void) +{ + ::octave_rl_resize_terminal (); +} - void - gnu_readline::do_newline (void) - { - ::octave_rl_newline (1, '\n'); - } +void +gnu_readline::do_set_screen_size (int ht, int wd) +{ + ::octave_rl_set_screen_size (ht, wd); +} + +std::string +gnu_readline::newline_chars (void) +{ + return "\r\n"; +} - void - gnu_readline::do_accept_line (void) - { - command_accept_line (1, '\n'); - } +void +gnu_readline::do_restore_terminal_state (void) +{ + ::octave_rl_restore_terminal_state (); +} + +void +gnu_readline::do_blink_matching_paren (bool flag) +{ + ::octave_rl_enable_paren_matching (flag ? 1 : 0); +} - bool - gnu_readline::do_undo (void) - { - return ::octave_rl_do_undo (); - } +bool +gnu_readline::do_erase_empty_line (bool flag) +{ + return ::octave_rl_erase_empty_line (flag ? 1 : 0); +} + +void +gnu_readline::do_set_basic_word_break_characters (const std::string& s) +{ + ::octave_rl_set_basic_word_break_characters (s.c_str ()); +} + +void +gnu_readline::do_set_completer_word_break_characters (const std::string& s) +{ + ::octave_rl_set_completer_word_break_characters (s.c_str ()); + + ::octave_rl_set_completion_word_break_hook + (gnu_readline::do_completer_word_break_hook); + +} - void - gnu_readline::do_clear_undo_list () - { - ::octave_rl_clear_undo_list (); - } +void +gnu_readline::do_set_basic_quote_characters (const std::string& s) +{ + ::octave_rl_set_basic_quote_characters (s.c_str ()); +} + +void +gnu_readline::do_set_filename_quote_characters (const std::string& s) +{ + ::octave_rl_set_filename_quote_characters (s.c_str ()); +} - void - gnu_readline::set_startup_hook (startup_hook_fcn f) - { - m_previous_startup_hook = ::octave_rl_get_startup_hook (); +void +gnu_readline::do_set_completer_quote_characters (const std::string& s) +{ + s_completer_quote_characters = s; +} - if (f != m_previous_startup_hook) - ::octave_rl_set_startup_hook (f); - } +void +gnu_readline::do_set_completion_append_character (char c) +{ + ::octave_rl_set_completion_append_character (c); +} + +void +gnu_readline::do_set_completion_function (completion_fcn f) +{ + m_completion_function = f; + + rl_attempted_completion_fcn_ptr fp + = (f ? gnu_readline::command_completer : nullptr); - void - gnu_readline::restore_startup_hook (void) - { - ::octave_rl_set_startup_hook (m_previous_startup_hook); - } + ::octave_rl_set_completion_function (fp); +} + +void +gnu_readline::do_set_quoting_function (quoting_fcn f) +{ + m_quoting_function = f; + + rl_quoting_fcn_ptr fp + = (f ? gnu_readline::command_quoter : nullptr); + + ::octave_rl_set_quoting_function (fp); +} + +void +gnu_readline::do_set_dequoting_function (dequoting_fcn f) +{ + m_dequoting_function = f; + + rl_dequoting_fcn_ptr fp + = (f ? gnu_readline::command_dequoter : nullptr); - void - gnu_readline::set_pre_input_hook (pre_input_hook_fcn f) - { - m_previous_pre_input_hook = ::octave_rl_get_pre_input_hook (); + ::octave_rl_set_dequoting_function (fp); +} + +void +gnu_readline::do_set_char_is_quoted_function (char_is_quoted_fcn f) +{ + m_char_is_quoted_function = f; + + rl_char_is_quoted_fcn_ptr fp + = (f ? gnu_readline::command_char_is_quoted : nullptr); - if (f != m_previous_pre_input_hook) - ::octave_rl_set_pre_input_hook (f); - } + ::octave_rl_set_char_is_quoted_function (fp); +} + +void +gnu_readline::do_set_user_accept_line_function (user_accept_line_fcn f) +{ + user_accept_line_function = f; - void - gnu_readline::restore_pre_input_hook (void) - { - ::octave_rl_set_pre_input_hook (m_previous_pre_input_hook); - } + if (f) + octave_rl_add_defun ("accept-line", gnu_readline::command_accept_line, + ::octave_rl_ctrl ('M')); + else + octave_rl_add_defun ("accept-line", ::octave_rl_newline, + ::octave_rl_ctrl ('M')); +} - void - gnu_readline::set_event_hook (event_hook_fcn f) - { - m_previous_event_hook = octave_rl_get_event_hook (); +gnu_readline::completion_fcn +gnu_readline::do_get_completion_function (void) const +{ + return m_completion_function; +} + +gnu_readline::quoting_fcn +gnu_readline::do_get_quoting_function (void) const +{ + return m_quoting_function; +} - ::octave_rl_set_event_hook (f); - } +gnu_readline::dequoting_fcn +gnu_readline::do_get_dequoting_function (void) const +{ + return m_dequoting_function; +} + +gnu_readline::char_is_quoted_fcn +gnu_readline::do_get_char_is_quoted_function (void) const +{ + return m_char_is_quoted_function; +} - void - gnu_readline::restore_event_hook (void) - { - ::octave_rl_set_event_hook (m_previous_event_hook); - } +gnu_readline::user_accept_line_fcn +gnu_readline::do_get_user_accept_line_function (void) const +{ + return user_accept_line_function; +} + +// True if the last "word" of the string line (delimited by delim) is +// an existing directory. Used by do_completer_word_break_hook. - void - gnu_readline::do_read_init_file (const std::string& file) - { - ::octave_rl_read_init_file (file.c_str ()); - } +static bool +looks_like_filename (const char *line, char delim) +{ + bool retval = false; + + const char *s = strrchr (line, delim); - void - gnu_readline::do_re_read_init_file (void) - { - ::octave_rl_re_read_init_file (); - } + if (s) + { + // Remove incomplete component. + const char *f = strrchr (line, sys::file_ops::dir_sep_char ()); + + if (f && (s[1] == '~' || f != s)) + { + // For something like "A /b", f==s; don't assume a file. - bool - gnu_readline::do_filename_completion_desired (bool arg) - { - return ::octave_rl_filename_completion_desired (arg); - } + std::string candidate_filename = s+1; + + candidate_filename = candidate_filename.substr (0, f - s); + + // Handles any complete ~, but doesn't expand usernames. + + if (candidate_filename[0] == '~') + candidate_filename + = sys::file_ops::tilde_expand (candidate_filename); + + sys::file_stat fs (candidate_filename); + + retval = fs.is_dir (); + } + } + + return retval; +} + +// Decide whether to interpret partial commands like "abc/def" as a +// filename or division. Return the set of delimiters appropriate for +// the decision. - bool - gnu_readline::do_filename_quoting_desired (bool arg) - { - return ::octave_rl_filename_quoting_desired (arg); - } +char * +gnu_readline::do_completer_word_break_hook () +{ + static char *dir_sep = octave_strdup_wrapper (R"( '")"); + + std::string word; + std::string line = get_line_buffer (); + + // For now, assume space or quote delimiter for file names. + const char *l = line.c_str (); - bool - gnu_readline::do_prefer_env_winsize (bool arg) - { - return ::octave_rl_prefer_env_winsize (arg); - } + if (looks_like_filename (l, ' ') || looks_like_filename (l, '\'') + || looks_like_filename (l, '"')) + { + ::octave_rl_set_completer_quote_characters + (s_completer_quote_characters.c_str ()); + + return dir_sep; + } + else + { + static char *word_break_chars = nullptr; - void - gnu_readline::do_interrupt (bool arg) - { - ::octave_rl_done (arg); - } + ::octave_rl_set_completer_quote_characters (""); + + free (word_break_chars); + + word_break_chars + = octave_strdup_wrapper (octave_rl_get_completer_word_break_characters ()); + + return word_break_chars; + } +} + +string_vector +gnu_readline::do_generate_filename_completions (const std::string& text) +{ + string_vector retval; + + int n = 0; + int count = 0; + + char *fn = nullptr; - void - gnu_readline::do_handle_interrupt_signal (void) - { - octave_signal_caught = 0; - octave_interrupt_state = 0; - - ::octave_rl_recover_from_interrupt (); + while (1) + { + fn = ::octave_rl_filename_completion_function (text.c_str (), count); - throw interrupt_exception (); - } + if (fn) + { + if (count == n) + { + // Famous last words: Most large directories will not + // have more than a few hundred files, so we should not + // resize too many times even if the growth is linear... + n += 100; + retval.resize (n); + } - int - gnu_readline::operate_and_get_next (int /* count */, int /* c */) - { - // Accept the current line. + retval[count++] = fn; + + free (fn); + } + else + break; + } + + retval.resize (count); + + return retval; +} - command_editor::accept_line (); - - // Find the current line, and find the next line to use. +std::string +gnu_readline::do_get_line_buffer (void) const +{ + return ::octave_rl_line_buffer (); +} - int x_where = command_history::where (); - - int x_length = command_history::length (); +std::string +gnu_readline::do_get_current_line (void) const +{ + std::string retval; + char *buf = ::octave_rl_copy_line (); + retval = buf; + free (buf); + return retval; +} - if ((command_history::is_stifled () - && (x_length >= command_history::max_input_history ())) - || (x_where >= x_length - 1)) - command_history::set_mark (x_where); - else - command_history::set_mark (x_where + 1); +// Return the character (offset+1) to the left of the cursor, +// or '\0' if the cursor is at the start of the line. +char +gnu_readline::do_get_prev_char (int offset) const +{ + const char *buf = ::octave_rl_line_buffer (); + int p = ::octave_rl_point (); + + return p > offset ? buf[p - offset - 1] : '\0'; +} - command_editor::add_startup_hook (command_history::goto_mark); +void +gnu_readline::do_replace_line (const std::string& text, bool clear_undo) +{ + ::octave_rl_replace_line (text.c_str (), clear_undo); +} - return 0; - } +void +gnu_readline::do_kill_full_line (void) +{ + ::octave_rl_kill_full_line (); +} + +void +gnu_readline::do_insert_text (const std::string& text) +{ + ::octave_rl_insert_text (text.c_str ()); +} - int - gnu_readline::history_search_backward (int count, int c) - { - return octave_rl_history_search_backward (count, c); - } +void +gnu_readline::do_newline (void) +{ + ::octave_rl_newline (1, '\n'); +} + +void +gnu_readline::do_accept_line (void) +{ + command_accept_line (1, '\n'); +} + +bool +gnu_readline::do_undo (void) +{ + return ::octave_rl_do_undo (); +} + +void +gnu_readline::do_clear_undo_list () +{ + ::octave_rl_clear_undo_list (); +} - int - gnu_readline::history_search_forward (int count, int c) - { - return octave_rl_history_search_forward (count, c); - } +void +gnu_readline::set_startup_hook (startup_hook_fcn f) +{ + m_previous_startup_hook = ::octave_rl_get_startup_hook (); + + if (f != m_previous_startup_hook) + ::octave_rl_set_startup_hook (f); +} + +void +gnu_readline::restore_startup_hook (void) +{ + ::octave_rl_set_startup_hook (m_previous_startup_hook); +} - char * - gnu_readline::command_generator (const char *text, int state) - { - char *retval = nullptr; +void +gnu_readline::set_pre_input_hook (pre_input_hook_fcn f) +{ + m_previous_pre_input_hook = ::octave_rl_get_pre_input_hook (); - completion_fcn f = command_editor::get_completion_function (); + if (f != m_previous_pre_input_hook) + ::octave_rl_set_pre_input_hook (f); +} - std::string tmp = f (text, state); - - std::size_t len = tmp.length (); +void +gnu_readline::restore_pre_input_hook (void) +{ + ::octave_rl_set_pre_input_hook (m_previous_pre_input_hook); +} - if (len > 0) - { - retval = static_cast (std::malloc (len+1)); +void +gnu_readline::set_event_hook (event_hook_fcn f) +{ + m_previous_event_hook = octave_rl_get_event_hook (); + + ::octave_rl_set_event_hook (f); +} - if (retval) - strcpy (retval, tmp.c_str ()); - } +void +gnu_readline::restore_event_hook (void) +{ + ::octave_rl_set_event_hook (m_previous_event_hook); +} + +void +gnu_readline::do_read_init_file (const std::string& file) +{ + ::octave_rl_read_init_file (file.c_str ()); +} - return retval; - } +void +gnu_readline::do_re_read_init_file (void) +{ + ::octave_rl_re_read_init_file (); +} + +bool +gnu_readline::do_filename_completion_desired (bool arg) +{ + return ::octave_rl_filename_completion_desired (arg); +} - char * - gnu_readline::command_quoter (char *text, int matches, char *qcp) - { - char *retval = nullptr; +bool +gnu_readline::do_filename_quoting_desired (bool arg) +{ + return ::octave_rl_filename_quoting_desired (arg); +} - quoting_fcn f = command_editor::get_quoting_function (); - - std::string tmp = f (text, matches, *qcp); +bool +gnu_readline::do_prefer_env_winsize (bool arg) +{ + return ::octave_rl_prefer_env_winsize (arg); +} - std::size_t len = tmp.length (); +void +gnu_readline::do_interrupt (bool arg) +{ + ::octave_rl_done (arg); +} + +void +gnu_readline::do_handle_interrupt_signal (void) +{ + octave_signal_caught = 0; + octave_interrupt_state = 0; - if (len > 0) - { - retval = static_cast (std::malloc (len+1)); + ::octave_rl_recover_from_interrupt (); + + throw interrupt_exception (); +} - if (retval) - strcpy (retval, tmp.c_str ()); - } +int +gnu_readline::operate_and_get_next (int /* count */, int /* c */) +{ + // Accept the current line. + + command_editor::accept_line (); - return retval; - } + // Find the current line, and find the next line to use. + + int x_where = command_history::where (); + + int x_length = command_history::length (); - char * - gnu_readline::command_dequoter (char *text, int quote) - { - char *retval = nullptr; + if ((command_history::is_stifled () + && (x_length >= command_history::max_input_history ())) + || (x_where >= x_length - 1)) + command_history::set_mark (x_where); + else + command_history::set_mark (x_where + 1); + + command_editor::add_startup_hook (command_history::goto_mark); - dequoting_fcn f = command_editor::get_dequoting_function (); + return 0; +} - std::string tmp = f (text, quote); +int +gnu_readline::history_search_backward (int count, int c) +{ + return octave_rl_history_search_backward (count, c); +} - std::size_t len = tmp.length (); +int +gnu_readline::history_search_forward (int count, int c) +{ + return octave_rl_history_search_forward (count, c); +} + +char * +gnu_readline::command_generator (const char *text, int state) +{ + char *retval = nullptr; - if (len > 0) - { - retval = static_cast (std::malloc (len+1)); + completion_fcn f = command_editor::get_completion_function (); + + std::string tmp = f (text, state); + + std::size_t len = tmp.length (); - if (retval) - strcpy (retval, tmp.c_str ()); - } + if (len > 0) + { + retval = static_cast (std::malloc (len+1)); + + if (retval) + strcpy (retval, tmp.c_str ()); + } - return retval; - } + return retval; +} + +char * +gnu_readline::command_quoter (char *text, int matches, char *qcp) +{ + char *retval = nullptr; + + quoting_fcn f = command_editor::get_quoting_function (); + + std::string tmp = f (text, matches, *qcp); - int - gnu_readline::command_char_is_quoted (char *text, int quote) - { - char_is_quoted_fcn f = command_editor::get_char_is_quoted_function (); + std::size_t len = tmp.length (); + + if (len > 0) + { + retval = static_cast (std::malloc (len+1)); - return f (text, quote); - } + if (retval) + strcpy (retval, tmp.c_str ()); + } + + return retval; +} - int - gnu_readline::command_accept_line (int count, int key) - { - user_accept_line_fcn f = command_editor::get_user_accept_line_function (); +char * +gnu_readline::command_dequoter (char *text, int quote) +{ + char *retval = nullptr; + + dequoting_fcn f = command_editor::get_dequoting_function (); + + std::string tmp = f (text, quote); + + std::size_t len = tmp.length (); - if (f) - f (::octave_rl_line_buffer ()); + if (len > 0) + { + retval = static_cast (std::malloc (len+1)); - ::octave_rl_redisplay (); + if (retval) + strcpy (retval, tmp.c_str ()); + } + + return retval; +} - return ::octave_rl_newline (count, key); - } +int +gnu_readline::command_char_is_quoted (char *text, int quote) +{ + char_is_quoted_fcn f = command_editor::get_char_is_quoted_function (); + + return f (text, quote); +} + +int +gnu_readline::command_accept_line (int count, int key) +{ + user_accept_line_fcn f = command_editor::get_user_accept_line_function (); - char ** - gnu_readline::command_completer (const char *text, int, int) - { - char **matches - = ::octave_rl_completion_matches (text, gnu_readline::command_generator); + if (f) + f (::octave_rl_line_buffer ()); + + ::octave_rl_redisplay (); + + return ::octave_rl_newline (count, key); +} - return matches; - } +char ** +gnu_readline::command_completer (const char *text, int, int) +{ + char **matches + = ::octave_rl_completion_matches (text, gnu_readline::command_generator); + + return matches; +} #endif - class - default_command_editor : public command_editor - { - public: +class +default_command_editor : public command_editor +{ +public: - default_command_editor (void) - : command_editor (), m_input_stream (stdin), m_output_stream (stdout) { } + default_command_editor (void) + : command_editor (), m_input_stream (stdin), m_output_stream (stdout) { } - // No copying! + // No copying! - default_command_editor (const default_command_editor&) = delete; + default_command_editor (const default_command_editor&) = delete; - default_command_editor& operator = (const default_command_editor&) = delete; + default_command_editor& operator = (const default_command_editor&) = delete; - ~default_command_editor (void) = default; + ~default_command_editor (void) = default; - std::string do_readline (const std::string& prompt, bool& eof); + std::string do_readline (const std::string& prompt, bool& eof); - void do_set_input_stream (FILE *f); + void do_set_input_stream (FILE *f); - FILE * do_get_input_stream (void); + FILE * do_get_input_stream (void); - void do_set_output_stream (FILE *f); + void do_set_output_stream (FILE *f); - FILE * do_get_output_stream (void); + FILE * do_get_output_stream (void); - string_vector do_generate_filename_completions (const std::string& text); + string_vector do_generate_filename_completions (const std::string& text); - std::string do_get_line_buffer (void) const; + std::string do_get_line_buffer (void) const; - std::string do_get_current_line (void) const; + std::string do_get_current_line (void) const; - char do_get_prev_char (int) const; + char do_get_prev_char (int) const; - void do_replace_line (const std::string& text, bool clear_undo); + void do_replace_line (const std::string& text, bool clear_undo); - void do_kill_full_line (void); + void do_kill_full_line (void); - void do_insert_text (const std::string& text); + void do_insert_text (const std::string& text); - void do_newline (void); + void do_newline (void); - void do_accept_line (void); + void do_accept_line (void); - private: +private: - FILE *m_input_stream; + FILE *m_input_stream; - FILE *m_output_stream; - }; + FILE *m_output_stream; +}; - std::string - default_command_editor::do_readline (const std::string& prompt, bool& eof) - { - std::fputs (prompt.c_str (), m_output_stream); - std::fflush (m_output_stream); +std::string +default_command_editor::do_readline (const std::string& prompt, bool& eof) +{ + std::fputs (prompt.c_str (), m_output_stream); + std::fflush (m_output_stream); - return fgetl (m_input_stream, eof); - } + return fgetl (m_input_stream, eof); +} - void - default_command_editor::do_set_input_stream (FILE *f) - { - m_input_stream = f; - } +void +default_command_editor::do_set_input_stream (FILE *f) +{ + m_input_stream = f; +} - FILE * - default_command_editor::do_get_input_stream (void) - { - return m_input_stream; - } +FILE * +default_command_editor::do_get_input_stream (void) +{ + return m_input_stream; +} - void - default_command_editor::do_set_output_stream (FILE *f) - { - m_output_stream = f; - } +void +default_command_editor::do_set_output_stream (FILE *f) +{ + m_output_stream = f; +} - FILE * - default_command_editor::do_get_output_stream (void) - { - return m_output_stream; - } +FILE * +default_command_editor::do_get_output_stream (void) +{ + return m_output_stream; +} - string_vector - default_command_editor::do_generate_filename_completions (const std::string&) - { - // FIXME - return string_vector (); - } +string_vector +default_command_editor::do_generate_filename_completions (const std::string&) +{ + // FIXME + return string_vector (); +} - std::string - default_command_editor::do_get_line_buffer (void) const - { - return ""; - } +std::string +default_command_editor::do_get_line_buffer (void) const +{ + return ""; +} - std::string - default_command_editor::do_get_current_line (void) const - { - // FIXME - return ""; - } +std::string +default_command_editor::do_get_current_line (void) const +{ + // FIXME + return ""; +} - char - default_command_editor::do_get_prev_char (int) const - { - return '\0'; - } +char +default_command_editor::do_get_prev_char (int) const +{ + return '\0'; +} - void - default_command_editor::do_replace_line (const std::string&, bool) - { - // FIXME - } +void +default_command_editor::do_replace_line (const std::string&, bool) +{ + // FIXME +} - void - default_command_editor::do_kill_full_line (void) - { - // FIXME - } +void +default_command_editor::do_kill_full_line (void) +{ + // FIXME +} - void - default_command_editor::do_insert_text (const std::string&) - { - // FIXME - } +void +default_command_editor::do_insert_text (const std::string&) +{ + // FIXME +} - void - default_command_editor::do_newline (void) - { - // FIXME - } +void +default_command_editor::do_newline (void) +{ + // FIXME +} - void - default_command_editor::do_accept_line (void) - { - // FIXME - } +void +default_command_editor::do_accept_line (void) +{ + // FIXME +} - bool - command_editor::instance_ok (void) - { - bool retval = true; +bool +command_editor::instance_ok (void) +{ + bool retval = true; - if (! s_instance) - { - make_command_editor (); + if (! s_instance) + { + make_command_editor (); - if (s_instance) - { - s_instance->set_event_hook (event_handler); + if (s_instance) + { + s_instance->set_event_hook (event_handler); - singleton_cleanup_list::add (cleanup_instance); - } - } + singleton_cleanup_list::add (cleanup_instance); + } + } - if (! s_instance) - (*current_liboctave_error_handler) - ("unable to create command history object!"); + if (! s_instance) + (*current_liboctave_error_handler) + ("unable to create command history object!"); - return retval; - } + return retval; +} - void - command_editor::make_command_editor (void) - { +void +command_editor::make_command_editor (void) +{ #if defined (USE_READLINE) - s_instance = new gnu_readline (); + s_instance = new gnu_readline (); #else - s_instance = new default_command_editor (); + s_instance = new default_command_editor (); #endif - } +} - void - command_editor::force_default_editor (void) - { - delete s_instance; - s_instance = new default_command_editor (); - } +void +command_editor::force_default_editor (void) +{ + delete s_instance; + s_instance = new default_command_editor (); +} - void - command_editor::set_initial_input (const std::string& text) - { - if (instance_ok ()) - s_instance->m_initial_input = text; - } +void +command_editor::set_initial_input (const std::string& text) +{ + if (instance_ok ()) + s_instance->m_initial_input = text; +} - int - command_editor::insert_initial_input (void) - { - return instance_ok () ? s_instance->do_insert_initial_input () : 0; - } +int +command_editor::insert_initial_input (void) +{ + return instance_ok () ? s_instance->do_insert_initial_input () : 0; +} - int - command_editor::startup_handler (void) - { - // Iterate over a copy of the set to avoid problems if a hook - // function attempts to remove itself from the startup_hook_set. +int +command_editor::startup_handler (void) +{ + // Iterate over a copy of the set to avoid problems if a hook + // function attempts to remove itself from the startup_hook_set. - std::set hook_set = m_startup_hook_set; + std::set hook_set = m_startup_hook_set; - for (startup_hook_fcn f : hook_set) - { - if (f) - f (); - } + for (startup_hook_fcn f : hook_set) + { + if (f) + f (); + } - return 0; - } + return 0; +} - int - command_editor::pre_input_handler (void) - { - // Iterate over copy of the set to avoid problems if a hook function - // attempts to remove itself from the pre_input_hook_set. +int +command_editor::pre_input_handler (void) +{ + // Iterate over copy of the set to avoid problems if a hook function + // attempts to remove itself from the pre_input_hook_set. - std::set hook_set = m_pre_input_hook_set; + std::set hook_set = m_pre_input_hook_set; - for (pre_input_hook_fcn f : hook_set) - { - if (f) - f (); - } + for (pre_input_hook_fcn f : hook_set) + { + if (f) + f (); + } - return 0; - } + return 0; +} - int - command_editor::event_handler (void) - { - if (octave_interrupt_state) - handle_interrupt_signal (); +int +command_editor::event_handler (void) +{ + if (octave_interrupt_state) + handle_interrupt_signal (); - event_hook_lock.lock (); + event_hook_lock.lock (); - std::set hook_set (m_event_hook_set); + std::set hook_set (m_event_hook_set); - event_hook_lock.unlock (); + event_hook_lock.unlock (); - for (event_hook_fcn f : hook_set) - { - if (f) - f (); - } + for (event_hook_fcn f : hook_set) + { + if (f) + f (); + } - return 0; - } + return 0; +} - void - command_editor::set_name (const std::string& n) - { - if (instance_ok ()) - s_instance->do_set_name (n); - } +void +command_editor::set_name (const std::string& n) +{ + if (instance_ok ()) + s_instance->do_set_name (n); +} - std::string - command_editor::readline (const std::string& prompt) - { - bool eof; +std::string +command_editor::readline (const std::string& prompt) +{ + bool eof; - return readline (prompt, eof); - } + return readline (prompt, eof); +} - std::string - command_editor::readline (const std::string& prompt, bool& eof) - { - std::string retval; +std::string +command_editor::readline (const std::string& prompt, bool& eof) +{ + std::string retval; - if (instance_ok ()) - { - if (! s_instance->m_initial_input.empty ()) - add_pre_input_hook (command_editor::insert_initial_input); + if (instance_ok ()) + { + if (! s_instance->m_initial_input.empty ()) + add_pre_input_hook (command_editor::insert_initial_input); - retval = s_instance->do_readline (prompt, eof); - } + retval = s_instance->do_readline (prompt, eof); + } - return retval; - } + return retval; +} - void - command_editor::set_input_stream (FILE *f) - { - if (instance_ok ()) - s_instance->do_set_input_stream (f); - } +void +command_editor::set_input_stream (FILE *f) +{ + if (instance_ok ()) + s_instance->do_set_input_stream (f); +} - FILE * - command_editor::get_input_stream (void) - { - return instance_ok () ? s_instance->do_get_input_stream () : nullptr; - } +FILE * +command_editor::get_input_stream (void) +{ + return instance_ok () ? s_instance->do_get_input_stream () : nullptr; +} - void - command_editor::set_output_stream (FILE *f) - { - if (instance_ok ()) - s_instance->do_set_output_stream (f); - } +void +command_editor::set_output_stream (FILE *f) +{ + if (instance_ok ()) + s_instance->do_set_output_stream (f); +} - FILE * - command_editor::get_output_stream (void) - { - return instance_ok () ? s_instance->do_get_output_stream () : nullptr; - } +FILE * +command_editor::get_output_stream (void) +{ + return instance_ok () ? s_instance->do_get_output_stream () : nullptr; +} - void - command_editor::redisplay (void) - { - if (instance_ok ()) - s_instance->do_redisplay (); - } +void +command_editor::redisplay (void) +{ + if (instance_ok ()) + s_instance->do_redisplay (); +} - int - command_editor::terminal_rows (void) - { - return instance_ok () ? s_instance->do_terminal_rows () : -1; - } +int +command_editor::terminal_rows (void) +{ + return instance_ok () ? s_instance->do_terminal_rows () : -1; +} - int - command_editor::terminal_cols (void) - { - return instance_ok () ? s_instance->do_terminal_cols () : -1; - } +int +command_editor::terminal_cols (void) +{ + return instance_ok () ? s_instance->do_terminal_cols () : -1; +} - void - command_editor::clear_screen (bool skip_redisplay) - { - if (instance_ok ()) - s_instance->do_clear_screen (skip_redisplay); - } +void +command_editor::clear_screen (bool skip_redisplay) +{ + if (instance_ok ()) + s_instance->do_clear_screen (skip_redisplay); +} - void - command_editor::resize_terminal (void) - { - if (instance_ok ()) - s_instance->do_resize_terminal (); - } +void +command_editor::resize_terminal (void) +{ + if (instance_ok ()) + s_instance->do_resize_terminal (); +} - void - command_editor::set_screen_size (int ht, int wd) - { - if (instance_ok ()) - s_instance->do_set_screen_size (ht, wd); - } +void +command_editor::set_screen_size (int ht, int wd) +{ + if (instance_ok ()) + s_instance->do_set_screen_size (ht, wd); +} - std::string - command_editor::decode_prompt_string (const std::string& s) - { - return instance_ok () ? s_instance->do_decode_prompt_string (s) : ""; - } +std::string +command_editor::decode_prompt_string (const std::string& s) +{ + return instance_ok () ? s_instance->do_decode_prompt_string (s) : ""; +} - int - command_editor::current_command_number (void) - { - return instance_ok () ? s_instance->m_command_number : 0; - } +int +command_editor::current_command_number (void) +{ + return instance_ok () ? s_instance->m_command_number : 0; +} - void - command_editor::reset_current_command_number (int n) - { - if (instance_ok ()) - s_instance->m_command_number = n; - } +void +command_editor::reset_current_command_number (int n) +{ + if (instance_ok ()) + s_instance->m_command_number = n; +} - void - command_editor::increment_current_command_number (void) - { - if (instance_ok ()) - s_instance->m_command_number++; - } +void +command_editor::increment_current_command_number (void) +{ + if (instance_ok ()) + s_instance->m_command_number++; +} - void - command_editor::restore_terminal_state (void) - { - if (instance_ok ()) - s_instance->do_restore_terminal_state (); - } +void +command_editor::restore_terminal_state (void) +{ + if (instance_ok ()) + s_instance->do_restore_terminal_state (); +} - void - command_editor::blink_matching_paren (bool flag) - { - if (instance_ok ()) - s_instance->do_blink_matching_paren (flag); - } +void +command_editor::blink_matching_paren (bool flag) +{ + if (instance_ok ()) + s_instance->do_blink_matching_paren (flag); +} - bool - command_editor::erase_empty_line (bool flag) - { - return instance_ok () ? s_instance->do_erase_empty_line (flag) : false; - } +bool +command_editor::erase_empty_line (bool flag) +{ + return instance_ok () ? s_instance->do_erase_empty_line (flag) : false; +} - void - command_editor::set_basic_word_break_characters (const std::string& s) - { - if (instance_ok ()) - s_instance->do_set_basic_word_break_characters (s); - } +void +command_editor::set_basic_word_break_characters (const std::string& s) +{ + if (instance_ok ()) + s_instance->do_set_basic_word_break_characters (s); +} - void - command_editor::set_completer_word_break_characters (const std::string& s) - { - if (instance_ok ()) - s_instance->do_set_completer_word_break_characters (s); - } +void +command_editor::set_completer_word_break_characters (const std::string& s) +{ + if (instance_ok ()) + s_instance->do_set_completer_word_break_characters (s); +} - void - command_editor::set_basic_quote_characters (const std::string& s) - { - if (instance_ok ()) - s_instance->do_set_basic_quote_characters (s); - } +void +command_editor::set_basic_quote_characters (const std::string& s) +{ + if (instance_ok ()) + s_instance->do_set_basic_quote_characters (s); +} - void - command_editor::set_filename_quote_characters (const std::string& s) - { - if (instance_ok ()) - s_instance->do_set_filename_quote_characters (s); - } +void +command_editor::set_filename_quote_characters (const std::string& s) +{ + if (instance_ok ()) + s_instance->do_set_filename_quote_characters (s); +} - void - command_editor::set_completer_quote_characters (const std::string& s) - { - if (instance_ok ()) - s_instance->do_set_completer_quote_characters (s); - } +void +command_editor::set_completer_quote_characters (const std::string& s) +{ + if (instance_ok ()) + s_instance->do_set_completer_quote_characters (s); +} - void - command_editor::set_completion_append_character (char c) - { - if (instance_ok ()) - s_instance->do_set_completion_append_character (c); - } +void +command_editor::set_completion_append_character (char c) +{ + if (instance_ok ()) + s_instance->do_set_completion_append_character (c); +} - void - command_editor::set_completion_function (completion_fcn f) - { - if (instance_ok ()) - s_instance->do_set_completion_function (f); - } +void +command_editor::set_completion_function (completion_fcn f) +{ + if (instance_ok ()) + s_instance->do_set_completion_function (f); +} - void - command_editor::set_quoting_function (quoting_fcn f) - { - if (instance_ok ()) - s_instance->do_set_quoting_function (f); - } +void +command_editor::set_quoting_function (quoting_fcn f) +{ + if (instance_ok ()) + s_instance->do_set_quoting_function (f); +} - void - command_editor::set_dequoting_function (dequoting_fcn f) - { - if (instance_ok ()) - s_instance->do_set_dequoting_function (f); - } +void +command_editor::set_dequoting_function (dequoting_fcn f) +{ + if (instance_ok ()) + s_instance->do_set_dequoting_function (f); +} - void - command_editor::set_char_is_quoted_function (char_is_quoted_fcn f) - { - if (instance_ok ()) - s_instance->do_set_char_is_quoted_function (f); - } +void +command_editor::set_char_is_quoted_function (char_is_quoted_fcn f) +{ + if (instance_ok ()) + s_instance->do_set_char_is_quoted_function (f); +} - void - command_editor::set_user_accept_line_function (user_accept_line_fcn f) - { - if (instance_ok ()) - s_instance->do_set_user_accept_line_function (f); - } +void +command_editor::set_user_accept_line_function (user_accept_line_fcn f) +{ + if (instance_ok ()) + s_instance->do_set_user_accept_line_function (f); +} - command_editor::completion_fcn - command_editor::get_completion_function (void) - { - return instance_ok () ? s_instance->do_get_completion_function () : nullptr; - } +command_editor::completion_fcn +command_editor::get_completion_function (void) +{ + return instance_ok () ? s_instance->do_get_completion_function () : nullptr; +} - command_editor::quoting_fcn - command_editor::get_quoting_function (void) - { - return instance_ok () ? s_instance->do_get_quoting_function () : nullptr; - } +command_editor::quoting_fcn +command_editor::get_quoting_function (void) +{ + return instance_ok () ? s_instance->do_get_quoting_function () : nullptr; +} - command_editor::dequoting_fcn - command_editor::get_dequoting_function (void) - { - return instance_ok () ? s_instance->do_get_dequoting_function () : nullptr; - } +command_editor::dequoting_fcn +command_editor::get_dequoting_function (void) +{ + return instance_ok () ? s_instance->do_get_dequoting_function () : nullptr; +} - command_editor::char_is_quoted_fcn - command_editor::get_char_is_quoted_function (void) - { - return (instance_ok () - ? s_instance->do_get_char_is_quoted_function () : nullptr); - } +command_editor::char_is_quoted_fcn +command_editor::get_char_is_quoted_function (void) +{ + return (instance_ok () + ? s_instance->do_get_char_is_quoted_function () : nullptr); +} - command_editor::user_accept_line_fcn - command_editor::get_user_accept_line_function (void) - { - return (instance_ok () - ? s_instance->do_get_user_accept_line_function () : nullptr); - } +command_editor::user_accept_line_fcn +command_editor::get_user_accept_line_function (void) +{ + return (instance_ok () + ? s_instance->do_get_user_accept_line_function () : nullptr); +} - string_vector - command_editor::generate_filename_completions (const std::string& text) - { - return (instance_ok () - ? s_instance->do_generate_filename_completions (text) - : string_vector ()); - } +string_vector +command_editor::generate_filename_completions (const std::string& text) +{ + return (instance_ok () + ? s_instance->do_generate_filename_completions (text) + : string_vector ()); +} - std::string - command_editor::get_line_buffer (void) - { - return instance_ok () ? s_instance->do_get_line_buffer () : ""; - } +std::string +command_editor::get_line_buffer (void) +{ + return instance_ok () ? s_instance->do_get_line_buffer () : ""; +} - std::string - command_editor::get_current_line (void) - { - return instance_ok () ? s_instance->do_get_current_line () : ""; - } +std::string +command_editor::get_current_line (void) +{ + return instance_ok () ? s_instance->do_get_current_line () : ""; +} - // Return the character (offset+1) to the left of the cursor, - // or '\0' if the cursor is at the start of the line. - char - command_editor::get_prev_char (int offset) - { - return instance_ok () ? s_instance->do_get_prev_char (offset) : '\0'; - } +// Return the character (offset+1) to the left of the cursor, +// or '\0' if the cursor is at the start of the line. +char +command_editor::get_prev_char (int offset) +{ + return instance_ok () ? s_instance->do_get_prev_char (offset) : '\0'; +} - void - command_editor::replace_line (const std::string& text, bool clear_undo) - { - if (instance_ok ()) - s_instance->do_replace_line (text, clear_undo); - } +void +command_editor::replace_line (const std::string& text, bool clear_undo) +{ + if (instance_ok ()) + s_instance->do_replace_line (text, clear_undo); +} - void - command_editor::kill_full_line (void) - { - if (instance_ok ()) - s_instance->do_kill_full_line (); - } +void +command_editor::kill_full_line (void) +{ + if (instance_ok ()) + s_instance->do_kill_full_line (); +} - void - command_editor::insert_text (const std::string& text) - { - if (instance_ok ()) - s_instance->do_insert_text (text); - } +void +command_editor::insert_text (const std::string& text) +{ + if (instance_ok ()) + s_instance->do_insert_text (text); +} - void - command_editor::newline (void) - { - if (instance_ok ()) - s_instance->do_newline (); - } +void +command_editor::newline (void) +{ + if (instance_ok ()) + s_instance->do_newline (); +} - void - command_editor::accept_line (void) - { - if (instance_ok ()) - s_instance->do_accept_line (); - } +void +command_editor::accept_line (void) +{ + if (instance_ok ()) + s_instance->do_accept_line (); +} - bool - command_editor::undo (void) - { - return instance_ok () ? s_instance->do_undo () : false; - } +bool +command_editor::undo (void) +{ + return instance_ok () ? s_instance->do_undo () : false; +} - void - command_editor::clear_undo_list (void) - { - if (instance_ok ()) - s_instance->do_clear_undo_list (); - } +void +command_editor::clear_undo_list (void) +{ + if (instance_ok ()) + s_instance->do_clear_undo_list (); +} - void - command_editor::add_startup_hook (startup_hook_fcn f) - { - if (instance_ok ()) - { - m_startup_hook_set.insert (f); +void +command_editor::add_startup_hook (startup_hook_fcn f) +{ + if (instance_ok ()) + { + m_startup_hook_set.insert (f); - s_instance->set_startup_hook (startup_handler); - } - } + s_instance->set_startup_hook (startup_handler); + } +} - void - command_editor::remove_startup_hook (startup_hook_fcn f) - { - if (instance_ok ()) - { - auto p = m_startup_hook_set.find (f); +void +command_editor::remove_startup_hook (startup_hook_fcn f) +{ + if (instance_ok ()) + { + auto p = m_startup_hook_set.find (f); - if (p != m_startup_hook_set.end ()) - m_startup_hook_set.erase (p); + if (p != m_startup_hook_set.end ()) + m_startup_hook_set.erase (p); - if (m_startup_hook_set.empty ()) - s_instance->restore_startup_hook (); - } - } + if (m_startup_hook_set.empty ()) + s_instance->restore_startup_hook (); + } +} - void - command_editor::add_pre_input_hook (pre_input_hook_fcn f) - { - if (instance_ok ()) - { - m_pre_input_hook_set.insert (f); +void +command_editor::add_pre_input_hook (pre_input_hook_fcn f) +{ + if (instance_ok ()) + { + m_pre_input_hook_set.insert (f); - s_instance->set_pre_input_hook (pre_input_handler); - } - } + s_instance->set_pre_input_hook (pre_input_handler); + } +} - void - command_editor::remove_pre_input_hook (pre_input_hook_fcn f) - { - if (instance_ok ()) - { - auto p = m_pre_input_hook_set.find (f); +void +command_editor::remove_pre_input_hook (pre_input_hook_fcn f) +{ + if (instance_ok ()) + { + auto p = m_pre_input_hook_set.find (f); - if (p != m_pre_input_hook_set.end ()) - m_pre_input_hook_set.erase (p); + if (p != m_pre_input_hook_set.end ()) + m_pre_input_hook_set.erase (p); - if (m_pre_input_hook_set.empty ()) - s_instance->restore_pre_input_hook (); - } - } + if (m_pre_input_hook_set.empty ()) + s_instance->restore_pre_input_hook (); + } +} - void - command_editor::add_event_hook (event_hook_fcn f) - { - autolock guard (event_hook_lock); +void +command_editor::add_event_hook (event_hook_fcn f) +{ + autolock guard (event_hook_lock); - m_event_hook_set.insert (f); - } + m_event_hook_set.insert (f); +} - void - command_editor::remove_event_hook (event_hook_fcn f) - { - autolock guard (event_hook_lock); +void +command_editor::remove_event_hook (event_hook_fcn f) +{ + autolock guard (event_hook_lock); - auto p = m_event_hook_set.find (f); + auto p = m_event_hook_set.find (f); - if (p != m_event_hook_set.end ()) - m_event_hook_set.erase (p); + if (p != m_event_hook_set.end ()) + m_event_hook_set.erase (p); - } +} - void - command_editor::run_event_hooks (void) - { - event_handler (); - } +void +command_editor::run_event_hooks (void) +{ + event_handler (); +} - void - command_editor::read_init_file (const std::string& file_arg) - { - if (instance_ok ()) - { - std::string file = sys::file_ops::tilde_expand (file_arg); +void +command_editor::read_init_file (const std::string& file_arg) +{ + if (instance_ok ()) + { + std::string file = sys::file_ops::tilde_expand (file_arg); - s_instance->do_read_init_file (file); - } - } + s_instance->do_read_init_file (file); + } +} - void - command_editor::re_read_init_file (void) - { - if (instance_ok ()) - s_instance->do_re_read_init_file (); - } +void +command_editor::re_read_init_file (void) +{ + if (instance_ok ()) + s_instance->do_re_read_init_file (); +} - bool - command_editor::filename_completion_desired (bool arg) - { - return (instance_ok () - ? s_instance->do_filename_completion_desired (arg) : false); - } +bool +command_editor::filename_completion_desired (bool arg) +{ + return (instance_ok () + ? s_instance->do_filename_completion_desired (arg) : false); +} - bool - command_editor::filename_quoting_desired (bool arg) - { - return (instance_ok ()) - ? s_instance->do_filename_quoting_desired (arg) : false; - } +bool +command_editor::filename_quoting_desired (bool arg) +{ + return (instance_ok ()) + ? s_instance->do_filename_quoting_desired (arg) : false; +} - bool - command_editor::prefer_env_winsize (bool arg) - { - return instance_ok () ? s_instance->do_prefer_env_winsize (arg) : false; - } +bool +command_editor::prefer_env_winsize (bool arg) +{ + return instance_ok () ? s_instance->do_prefer_env_winsize (arg) : false; +} - bool - command_editor::interrupt (bool arg) - { - bool retval; +bool +command_editor::interrupt (bool arg) +{ + bool retval; - if (instance_ok ()) - { - // Return the current interrupt state. - retval = s_instance->m_interrupted; + if (instance_ok ()) + { + // Return the current interrupt state. + retval = s_instance->m_interrupted; - s_instance->do_interrupt (arg); + s_instance->do_interrupt (arg); - s_instance->m_interrupted = arg; - } - else - retval = false; + s_instance->m_interrupted = arg; + } + else + retval = false; - return retval; - } + return retval; +} - void - command_editor::interrupt_event_loop (bool arg) - { - if (instance_ok ()) - s_instance->do_interrupt_event_loop (arg); - } +void +command_editor::interrupt_event_loop (bool arg) +{ + if (instance_ok ()) + s_instance->do_interrupt_event_loop (arg); +} - bool - command_editor::event_loop_interrupted (void) - { - return instance_ok () ? s_instance->do_event_loop_interrupted () : false; - } +bool +command_editor::event_loop_interrupted (void) +{ + return instance_ok () ? s_instance->do_event_loop_interrupted () : false; +} - void - command_editor::handle_interrupt_signal (void) - { - if (instance_ok ()) - s_instance->do_handle_interrupt_signal (); - } +void +command_editor::handle_interrupt_signal (void) +{ + if (instance_ok ()) + s_instance->do_handle_interrupt_signal (); +} - // Return a string which will be printed as a prompt. The string may - // contain special characters which are decoded as follows: - // - // \a bell (ascii 07) - // \d the date - // \e escape (ascii 033) - // \h the hostname up to the first '.' - // \H the hostname - // \n CRLF - // \r CR - // \s the name of the shell (program) - // \t the time - // \T the time in 12-hour hh:mm:ss format - // \@ the time in 12-hour hh:mm am/pm format - // \A the time in 24-hour hh:mm format - // \u your username - // \w the current working directory - // \W the last element of PWD - // \! the history number of this command - // \# the command number of this command - // \$ a $ or a # if you are root - // \nnn character code nnn in octal - // \\ a backslash - // \[ begin a sequence of non-printing chars - // \] end a sequence of non-printing chars +// Return a string which will be printed as a prompt. The string may +// contain special characters which are decoded as follows: +// +// \a bell (ascii 07) +// \d the date +// \e escape (ascii 033) +// \h the hostname up to the first '.' +// \H the hostname +// \n CRLF +// \r CR +// \s the name of the shell (program) +// \t the time +// \T the time in 12-hour hh:mm:ss format +// \@ the time in 12-hour hh:mm am/pm format +// \A the time in 24-hour hh:mm format +// \u your username +// \w the current working directory +// \W the last element of PWD +// \! the history number of this command +// \# the command number of this command +// \$ a $ or a # if you are root +// \nnn character code nnn in octal +// \\ a backslash +// \[ begin a sequence of non-printing chars +// \] end a sequence of non-printing chars - std::string - command_editor::do_decode_prompt_string (const std::string& s) - { - std::string retval; - std::string tmpstr; - std::size_t i = 0; - std::size_t slen = s.length (); - int c; +std::string +command_editor::do_decode_prompt_string (const std::string& s) +{ + std::string retval; + std::string tmpstr; + std::size_t i = 0; + std::size_t slen = s.length (); + int c; + + while (i < slen) + { + c = s[i]; + + i++; - while (i < slen) - { - c = s[i]; - - i++; + if (c == '\\') + { + c = s[i]; - if (c == '\\') - { - c = s[i]; - - switch (c) + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + // Maybe convert an octal number. { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - // Maybe convert an octal number. - { - int n = read_octal (s.substr (i, 3)); + int n = read_octal (s.substr (i, 3)); + + tmpstr = '\\'; - tmpstr = '\\'; + if (n != -1) + { + tmpstr[0] = n; + i += 2; // i++ makes this += 3 later + } + + break; + } - if (n != -1) - { - tmpstr[0] = n; - i += 2; // i++ makes this += 3 later - } + case 'a': + { + tmpstr = '\a'; - break; - } + break; + } - case 'a': - { - tmpstr = '\a'; - - break; - } - - case 'd': - case 't': - case 'T': - case '@': - case 'A': - // Make the current time/date into a string. - { - sys::localtime now; + case 'd': + case 't': + case 'T': + case '@': + case 'A': + // Make the current time/date into a string. + { + sys::localtime now; - if (c == 'd') - tmpstr = now.strftime ("%a %b %d"); - else if (c == 't') - tmpstr = now.strftime ("%H:%M:%S"); - else if (c == 'T') - tmpstr = now.strftime ("%I:%M:%S"); - else if (c == '@') - tmpstr = now.strftime ("%I:%M %p"); - else // (c == 'A') - tmpstr = now.strftime ("%H:%M"); + if (c == 'd') + tmpstr = now.strftime ("%a %b %d"); + else if (c == 't') + tmpstr = now.strftime ("%H:%M:%S"); + else if (c == 'T') + tmpstr = now.strftime ("%I:%M:%S"); + else if (c == '@') + tmpstr = now.strftime ("%I:%M %p"); + else // (c == 'A') + tmpstr = now.strftime ("%H:%M"); - break; - } + break; + } - case 'e': - { - tmpstr = '\033'; + case 'e': + { + tmpstr = '\033'; - break; - } + break; + } - case 'h': - { - tmpstr = sys::env::get_host_name (); + case 'h': + { + tmpstr = sys::env::get_host_name (); - std::size_t pos = tmpstr.find ('.'); + std::size_t pos = tmpstr.find ('.'); - if (pos != std::string::npos) - tmpstr.resize (pos); + if (pos != std::string::npos) + tmpstr.resize (pos); - break; - } + break; + } - case 'H': - { - tmpstr = sys::env::get_host_name (); + case 'H': + { + tmpstr = sys::env::get_host_name (); - break; - } + break; + } - case 'n': - { - tmpstr = newline_chars (); + case 'n': + { + tmpstr = newline_chars (); - break; - } + break; + } - case 'r': - { - tmpstr = '\r'; + case 'r': + { + tmpstr = '\r'; - break; - } + break; + } - case 's': - { - tmpstr = sys::env::get_program_name (); - tmpstr = sys::env::base_pathname (tmpstr); + case 's': + { + tmpstr = sys::env::get_program_name (); + tmpstr = sys::env::base_pathname (tmpstr); - break; - } + break; + } - case 'u': - { - tmpstr = sys::env::get_user_name (); + case 'u': + { + tmpstr = sys::env::get_user_name (); - break; - } + break; + } - case 'w': - case 'W': - { - try - { - tmpstr = sys::env::get_current_directory (); - } - catch (const execution_exception&) - { - tmpstr = ""; - } + case 'w': + case 'W': + { + try + { + tmpstr = sys::env::get_current_directory (); + } + catch (const execution_exception&) + { + tmpstr = ""; + } - std::string home_dir = sys::env::get_home_directory (); + std::string home_dir = sys::env::get_home_directory (); - if (c == 'W' && (home_dir.empty () || tmpstr != home_dir)) - { - if (tmpstr != "/" && tmpstr != "//") - { - std::size_t pos = tmpstr.rfind ('/'); + if (c == 'W' && (home_dir.empty () || tmpstr != home_dir)) + { + if (tmpstr != "/" && tmpstr != "//") + { + std::size_t pos = tmpstr.rfind ('/'); - if (pos != std::string::npos && pos != 0) - tmpstr = tmpstr.substr (pos + 1); - } - } - else - tmpstr = sys::env::polite_directory_format (tmpstr); + if (pos != std::string::npos && pos != 0) + tmpstr = tmpstr.substr (pos + 1); + } + } + else + tmpstr = sys::env::polite_directory_format (tmpstr); - break; - } + break; + } - case '!': - { - char number_buffer[32]; - int num = command_history::current_number (); - if (num > 0) - sprintf (number_buffer, "%d", num); - else - strcpy (number_buffer, "!"); - tmpstr = number_buffer; + case '!': + { + char number_buffer[32]; + int num = command_history::current_number (); + if (num > 0) + sprintf (number_buffer, "%d", num); + else + strcpy (number_buffer, "!"); + tmpstr = number_buffer; - break; - } + break; + } - case '#': - { - char number_buffer[32]; - sprintf (number_buffer, "%d", m_command_number); - tmpstr = number_buffer; + case '#': + { + char number_buffer[32]; + sprintf (number_buffer, "%d", m_command_number); + tmpstr = number_buffer; - break; - } + break; + } - case '$': - { - tmpstr = (octave_geteuid_wrapper () == 0 ? '#' : '$'); - break; - } + case '$': + { + tmpstr = (octave_geteuid_wrapper () == 0 ? '#' : '$'); + break; + } #if defined (USE_READLINE) - case '[': - case ']': - { - tmpstr.resize (1); + case '[': + case ']': + { + tmpstr.resize (1); - tmpstr[0] = ((c == '[') - ? ::octave_rl_prompt_start_ignore () - : ::octave_rl_prompt_end_ignore ()); + tmpstr[0] = ((c == '[') + ? ::octave_rl_prompt_start_ignore () + : ::octave_rl_prompt_end_ignore ()); - break; - } + break; + } #endif - case '\\': - { - tmpstr = '\\'; - - break; - } + case '\\': + { + tmpstr = '\\'; - default: - { - tmpstr = "\\ "; - tmpstr[1] = c; - - break; - } + break; } - retval.append (tmpstr); - i++; // Move past processed escape character - } - else - retval += c; - } + default: + { + tmpstr = "\\ "; + tmpstr[1] = c; - return retval; - } + break; + } + } + + retval.append (tmpstr); + i++; // Move past processed escape character + } + else + retval += c; + } - int - command_editor::do_insert_initial_input (void) - { - std::string input = m_initial_input; + return retval; +} - m_initial_input = ""; - - do_insert_text (input); +int +command_editor::do_insert_initial_input (void) +{ + std::string input = m_initial_input; - // Is it really right to redisplay here? - do_redisplay (); + m_initial_input = ""; + + do_insert_text (input); - return 0; - } + // Is it really right to redisplay here? + do_redisplay (); - // Return the octal number parsed from STRING, or -1 to indicate that - // the string contained a bad number. + return 0; +} - int - command_editor::read_octal (const std::string& s) - { - int result = 0; - int digits = 0; +// Return the octal number parsed from STRING, or -1 to indicate that +// the string contained a bad number. - std::size_t i = 0; - std::size_t slen = s.length (); +int +command_editor::read_octal (const std::string& s) +{ + int result = 0; + int digits = 0; - while (i < slen && s[i] >= '0' && s[i] < '8') - { - digits++; - result = (result * 8) + s[i] - '0'; - i++; - } + std::size_t i = 0; + std::size_t slen = s.length (); - if (! digits || result > 0777 || i < slen) - result = -1; + while (i < slen && s[i] >= '0' && s[i] < '8') + { + digits++; + result = (result * 8) + s[i] - '0'; + i++; + } - return result; - } + if (! digits || result > 0777 || i < slen) + result = -1; - void - command_editor::error (int err_num) - { - (*current_liboctave_error_handler) ("%s", std::strerror (err_num)); - } + return result; +} - void - command_editor::error (const std::string& s) - { - (*current_liboctave_error_handler) ("%s", s.c_str ()); - } +void +command_editor::error (int err_num) +{ + (*current_liboctave_error_handler) ("%s", std::strerror (err_num)); +} + +void +command_editor::error (const std::string& s) +{ + (*current_liboctave_error_handler) ("%s", s.c_str ()); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/cmd-edit.h --- a/liboctave/util/cmd-edit.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/cmd-edit.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,369 +37,369 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTAVE_API - command_editor - { - protected: +class +OCTAVE_API +command_editor +{ +protected: - command_editor (void) - : m_command_number (1), m_rows (24), m_cols (80), m_interrupted (false), - m_interrupt_event_loop (false), m_initial_input () - { } + command_editor (void) + : m_command_number (1), m_rows (24), m_cols (80), m_interrupted (false), + m_interrupt_event_loop (false), m_initial_input () + { } - public: +public: - typedef int (*startup_hook_fcn) (void); + typedef int (*startup_hook_fcn) (void); - typedef int (*pre_input_hook_fcn) (void); + typedef int (*pre_input_hook_fcn) (void); - typedef int (*event_hook_fcn) (void); + typedef int (*event_hook_fcn) (void); - typedef std::string (*completion_fcn) (const std::string&, int); + typedef std::string (*completion_fcn) (const std::string&, int); - typedef char * (*completion_hook_fcn) (); + typedef char *(*completion_hook_fcn) (); - typedef std::string (*quoting_fcn) (const std::string&, int, char); + typedef std::string (*quoting_fcn) (const std::string&, int, char); - typedef std::string (*dequoting_fcn) (const std::string&, int); + typedef std::string (*dequoting_fcn) (const std::string&, int); - typedef int (*char_is_quoted_fcn) (const std::string&, int); + typedef int (*char_is_quoted_fcn) (const std::string&, int); - typedef void (*user_accept_line_fcn) (const std::string&); + typedef void (*user_accept_line_fcn) (const std::string&); - // No copying! + // No copying! - command_editor (const command_editor&) = delete; + command_editor (const command_editor&) = delete; - command_editor& operator = (const command_editor&) = delete; + command_editor& operator = (const command_editor&) = delete; - virtual ~command_editor (void) = default; + virtual ~command_editor (void) = default; - static void set_name (const std::string& n); + static void set_name (const std::string& n); - static std::string readline (const std::string& prompt); + static std::string readline (const std::string& prompt); - static std::string readline (const std::string& prompt, bool& eof); + static std::string readline (const std::string& prompt, bool& eof); - static void set_input_stream (FILE *f); + static void set_input_stream (FILE *f); - static FILE * get_input_stream (void); + static FILE * get_input_stream (void); - static void set_output_stream (FILE *f); + static void set_output_stream (FILE *f); - static FILE * get_output_stream (void); + static FILE * get_output_stream (void); - static void redisplay (void); + static void redisplay (void); - static int terminal_rows (void); + static int terminal_rows (void); - static int terminal_cols (void); + static int terminal_cols (void); - static void clear_screen (bool skip_redisplay = false); + static void clear_screen (bool skip_redisplay = false); - static void resize_terminal (void); + static void resize_terminal (void); - static void set_screen_size (int ht, int wd); + static void set_screen_size (int ht, int wd); - static std::string decode_prompt_string (const std::string& s); + static std::string decode_prompt_string (const std::string& s); - static void restore_terminal_state (void); + static void restore_terminal_state (void); - static void blink_matching_paren (bool flag); + static void blink_matching_paren (bool flag); - static bool erase_empty_line (bool flag); + static bool erase_empty_line (bool flag); - static void set_basic_word_break_characters (const std::string& s); + static void set_basic_word_break_characters (const std::string& s); - static void set_completer_word_break_characters (const std::string& s); + static void set_completer_word_break_characters (const std::string& s); - static void set_basic_quote_characters (const std::string& s); + static void set_basic_quote_characters (const std::string& s); - static void set_filename_quote_characters (const std::string& s); + static void set_filename_quote_characters (const std::string& s); - static void set_completer_quote_characters (const std::string& s); + static void set_completer_quote_characters (const std::string& s); - static void set_completion_append_character (char c); + static void set_completion_append_character (char c); - static void set_completion_function (completion_fcn f); + static void set_completion_function (completion_fcn f); - static void set_quoting_function (quoting_fcn f); + static void set_quoting_function (quoting_fcn f); - static void set_dequoting_function (dequoting_fcn f); + static void set_dequoting_function (dequoting_fcn f); - static void set_char_is_quoted_function (char_is_quoted_fcn f); + static void set_char_is_quoted_function (char_is_quoted_fcn f); - static void set_user_accept_line_function (user_accept_line_fcn f); + static void set_user_accept_line_function (user_accept_line_fcn f); - static completion_fcn get_completion_function (void); + static completion_fcn get_completion_function (void); - static quoting_fcn get_quoting_function (void); + static quoting_fcn get_quoting_function (void); - static dequoting_fcn get_dequoting_function (void); + static dequoting_fcn get_dequoting_function (void); - static char_is_quoted_fcn get_char_is_quoted_function (void); + static char_is_quoted_fcn get_char_is_quoted_function (void); - static user_accept_line_fcn get_user_accept_line_function (void); + static user_accept_line_fcn get_user_accept_line_function (void); - static string_vector - generate_filename_completions (const std::string& text); + static string_vector + generate_filename_completions (const std::string& text); - static std::string get_line_buffer (void); + static std::string get_line_buffer (void); - static std::string get_current_line (void); + static std::string get_current_line (void); - static char get_prev_char (int); + static char get_prev_char (int); - static void replace_line (const std::string& text, bool clear_undo = true); + static void replace_line (const std::string& text, bool clear_undo = true); - static void kill_full_line (void); + static void kill_full_line (void); - static void insert_text (const std::string& text); + static void insert_text (const std::string& text); - static void newline (void); + static void newline (void); - static void accept_line (void); + static void accept_line (void); - static bool undo (void); + static bool undo (void); - static void clear_undo_list (void); + static void clear_undo_list (void); - static void add_startup_hook (startup_hook_fcn f); + static void add_startup_hook (startup_hook_fcn f); - static void remove_startup_hook (startup_hook_fcn f); + static void remove_startup_hook (startup_hook_fcn f); - static void add_pre_input_hook (pre_input_hook_fcn f); + static void add_pre_input_hook (pre_input_hook_fcn f); - static void remove_pre_input_hook (pre_input_hook_fcn f); + static void remove_pre_input_hook (pre_input_hook_fcn f); - static void add_event_hook (event_hook_fcn f); + static void add_event_hook (event_hook_fcn f); - static void remove_event_hook (event_hook_fcn f); + static void remove_event_hook (event_hook_fcn f); - static void run_event_hooks (void); + static void run_event_hooks (void); - static void read_init_file (const std::string& file = ""); + static void read_init_file (const std::string& file = ""); - static void re_read_init_file (void); + static void re_read_init_file (void); - static bool filename_completion_desired (bool); + static bool filename_completion_desired (bool); - static bool filename_quoting_desired (bool); + static bool filename_quoting_desired (bool); - static bool prefer_env_winsize (bool); + static bool prefer_env_winsize (bool); - static bool interrupt (bool = true); + static bool interrupt (bool = true); - static void interrupt_event_loop (bool flag = true); + static void interrupt_event_loop (bool flag = true); - static bool event_loop_interrupted (void); + static bool event_loop_interrupted (void); - static int current_command_number (void); + static int current_command_number (void); - static void reset_current_command_number (int n); + static void reset_current_command_number (int n); - static void increment_current_command_number (void); + static void increment_current_command_number (void); - static void force_default_editor (void); + static void force_default_editor (void); - static void set_initial_input (const std::string& text); + static void set_initial_input (const std::string& text); - static int insert_initial_input (void); + static int insert_initial_input (void); - private: +private: - static bool instance_ok (void); + static bool instance_ok (void); - static void make_command_editor (void); + static void make_command_editor (void); - static int startup_handler (void); + static int startup_handler (void); - static int pre_input_handler (void); + static int pre_input_handler (void); - static int event_handler (void); + static int event_handler (void); - static void cleanup_instance (void) - { - delete s_instance; - s_instance = nullptr; - } + static void cleanup_instance (void) + { + delete s_instance; + s_instance = nullptr; + } - static void handle_interrupt_signal (void); + static void handle_interrupt_signal (void); - //-------- + //-------- - static command_editor *s_instance; // the real thing. + static command_editor *s_instance; // the real thing. - static std::set m_startup_hook_set; - static std::set m_pre_input_hook_set; - static std::set m_event_hook_set; + static std::set m_startup_hook_set; + static std::set m_pre_input_hook_set; + static std::set m_event_hook_set; - protected: +protected: - // To use something other than the GNU readline library, derive a new - // class from command_editor, overload these functions as - // necessary, and make instance point to the new class. + // To use something other than the GNU readline library, derive a new + // class from command_editor, overload these functions as + // necessary, and make instance point to the new class. - virtual void do_set_name (const std::string&) { } + virtual void do_set_name (const std::string&) { } - std::string do_readline (const std::string& prompt) - { - bool eof; + std::string do_readline (const std::string& prompt) + { + bool eof; - return do_readline (prompt, eof); - } + return do_readline (prompt, eof); + } - virtual std::string do_readline (const std::string&, bool&) = 0; + virtual std::string do_readline (const std::string&, bool&) = 0; - virtual void do_set_input_stream (FILE *) = 0; + virtual void do_set_input_stream (FILE *) = 0; - virtual FILE * do_get_input_stream (void) = 0; + virtual FILE * do_get_input_stream (void) = 0; - virtual void do_set_output_stream (FILE *) = 0; + virtual void do_set_output_stream (FILE *) = 0; - virtual FILE * do_get_output_stream (void) = 0; + virtual FILE * do_get_output_stream (void) = 0; - virtual void do_redisplay (void) { } + virtual void do_redisplay (void) { } - virtual int do_terminal_rows (void) { return m_rows; } + virtual int do_terminal_rows (void) { return m_rows; } - virtual int do_terminal_cols (void) { return m_cols; } + virtual int do_terminal_cols (void) { return m_cols; } - virtual void do_clear_screen (bool) { } + virtual void do_clear_screen (bool) { } - virtual void do_resize_terminal (void) { } + virtual void do_resize_terminal (void) { } - virtual void do_set_screen_size (int ht, int wd) - { - m_rows = ht; - m_cols = wd; - } + virtual void do_set_screen_size (int ht, int wd) + { + m_rows = ht; + m_cols = wd; + } - virtual std::string do_decode_prompt_string (const std::string&); + virtual std::string do_decode_prompt_string (const std::string&); - virtual std::string newline_chars (void) { return "\n"; } + virtual std::string newline_chars (void) { return "\n"; } - virtual void do_restore_terminal_state (void) { } + virtual void do_restore_terminal_state (void) { } - virtual void do_blink_matching_paren (bool) { } + virtual void do_blink_matching_paren (bool) { } - virtual bool do_erase_empty_line (bool) { return false; } + virtual bool do_erase_empty_line (bool) { return false; } - virtual void do_set_basic_word_break_characters (const std::string&) { } + virtual void do_set_basic_word_break_characters (const std::string&) { } - virtual void do_set_completer_word_break_characters (const std::string&) { } + virtual void do_set_completer_word_break_characters (const std::string&) { } - virtual void do_set_completer_word_break_hook (completion_hook_fcn) { } + virtual void do_set_completer_word_break_hook (completion_hook_fcn) { } - virtual void do_set_basic_quote_characters (const std::string&) { } + virtual void do_set_basic_quote_characters (const std::string&) { } - virtual void do_set_filename_quote_characters (const std::string&) { } + virtual void do_set_filename_quote_characters (const std::string&) { } - virtual void do_set_completer_quote_characters (const std::string&) { } + virtual void do_set_completer_quote_characters (const std::string&) { } - virtual void do_set_completion_append_character (char) { } + virtual void do_set_completion_append_character (char) { } - virtual void do_set_completion_function (completion_fcn) { } + virtual void do_set_completion_function (completion_fcn) { } - virtual void do_set_quoting_function (quoting_fcn) { } + virtual void do_set_quoting_function (quoting_fcn) { } - virtual void do_set_dequoting_function (dequoting_fcn) { } + virtual void do_set_dequoting_function (dequoting_fcn) { } - virtual void do_set_char_is_quoted_function (char_is_quoted_fcn) { } + virtual void do_set_char_is_quoted_function (char_is_quoted_fcn) { } - virtual void do_set_user_accept_line_function (user_accept_line_fcn) { } + virtual void do_set_user_accept_line_function (user_accept_line_fcn) { } - virtual completion_fcn do_get_completion_function (void) const - { return nullptr; } + virtual completion_fcn do_get_completion_function (void) const + { return nullptr; } - virtual quoting_fcn do_get_quoting_function (void) const - { return nullptr; } + virtual quoting_fcn do_get_quoting_function (void) const + { return nullptr; } - virtual dequoting_fcn do_get_dequoting_function (void) const - { return nullptr; } + virtual dequoting_fcn do_get_dequoting_function (void) const + { return nullptr; } - virtual char_is_quoted_fcn do_get_char_is_quoted_function (void) const - { return nullptr; } + virtual char_is_quoted_fcn do_get_char_is_quoted_function (void) const + { return nullptr; } - virtual user_accept_line_fcn do_get_user_accept_line_function (void) const - { return nullptr; } + virtual user_accept_line_fcn do_get_user_accept_line_function (void) const + { return nullptr; } - virtual string_vector - do_generate_filename_completions (const std::string& text) = 0; + virtual string_vector + do_generate_filename_completions (const std::string& text) = 0; - virtual std::string do_get_line_buffer (void) const = 0; + virtual std::string do_get_line_buffer (void) const = 0; - virtual std::string do_get_current_line (void) const = 0; + virtual std::string do_get_current_line (void) const = 0; - virtual char do_get_prev_char (int) const = 0; + virtual char do_get_prev_char (int) const = 0; - virtual void - do_replace_line (const std::string& text, bool clear_undo) = 0; + virtual void + do_replace_line (const std::string& text, bool clear_undo) = 0; - virtual void do_kill_full_line (void) = 0; + virtual void do_kill_full_line (void) = 0; - virtual void do_insert_text (const std::string& text) = 0; + virtual void do_insert_text (const std::string& text) = 0; - virtual void do_newline (void) = 0; + virtual void do_newline (void) = 0; - virtual void do_accept_line (void) = 0; + virtual void do_accept_line (void) = 0; - virtual bool do_undo (void) { return false; } + virtual bool do_undo (void) { return false; } - virtual void do_clear_undo_list (void) { } + virtual void do_clear_undo_list (void) { } - virtual void set_startup_hook (startup_hook_fcn) { } + virtual void set_startup_hook (startup_hook_fcn) { } - virtual void restore_startup_hook (void) { } + virtual void restore_startup_hook (void) { } - virtual void set_pre_input_hook (pre_input_hook_fcn) { } + virtual void set_pre_input_hook (pre_input_hook_fcn) { } - virtual void restore_pre_input_hook (void) { } + virtual void restore_pre_input_hook (void) { } - virtual void set_event_hook (event_hook_fcn) { } + virtual void set_event_hook (event_hook_fcn) { } - virtual void restore_event_hook (void) { } + virtual void restore_event_hook (void) { } - virtual void do_read_init_file (const std::string&) { } + virtual void do_read_init_file (const std::string&) { } - virtual void do_re_read_init_file (void) { } + virtual void do_re_read_init_file (void) { } - virtual bool do_filename_completion_desired (bool) { return false; } + virtual bool do_filename_completion_desired (bool) { return false; } - virtual bool do_filename_quoting_desired (bool) { return false; } + virtual bool do_filename_quoting_desired (bool) { return false; } - virtual bool do_prefer_env_winsize (bool) { return false; } + virtual bool do_prefer_env_winsize (bool) { return false; } - virtual void do_interrupt (bool) { } + virtual void do_interrupt (bool) { } - virtual void do_handle_interrupt_signal (void) { } + virtual void do_handle_interrupt_signal (void) { } - void do_interrupt_event_loop (bool arg) { m_interrupt_event_loop = arg; } + void do_interrupt_event_loop (bool arg) { m_interrupt_event_loop = arg; } - bool do_event_loop_interrupted (void) const - { return m_interrupt_event_loop; } + bool do_event_loop_interrupted (void) const + { return m_interrupt_event_loop; } - int do_insert_initial_input (void); + int do_insert_initial_input (void); - int read_octal (const std::string& s); + int read_octal (const std::string& s); - void error (int); + void error (int); - void error (const std::string&); + void error (const std::string&); - // The current command number. - int m_command_number; + // The current command number. + int m_command_number; - int m_rows; - int m_cols; + int m_rows; + int m_cols; - bool m_interrupted; + bool m_interrupted; - bool m_interrupt_event_loop; + bool m_interrupt_event_loop; - std::string m_initial_input; - }; + std::string m_initial_input; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/cmd-hist.cc --- a/liboctave/util/cmd-hist.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/cmd-hist.cc Thu Dec 01 20:05:44 2022 -0800 @@ -52,970 +52,970 @@ OCTAVE_BEGIN_NAMESPACE(octave) - command_history *command_history::s_instance = nullptr; +command_history *command_history::s_instance = nullptr; #if defined (USE_READLINE) - class - gnu_history : public command_history - { - public: +class +gnu_history : public command_history +{ +public: - gnu_history (void) - : command_history (), mark (0) { } + gnu_history (void) + : command_history (), mark (0) { } - ~gnu_history (void) = default; + ~gnu_history (void) = default; - void do_process_histcontrol (const std::string&); + void do_process_histcontrol (const std::string&); - std::string do_histcontrol (void) const; + std::string do_histcontrol (void) const; - bool do_add (const std::string&); + bool do_add (const std::string&); - void do_remove (int); + void do_remove (int); - void do_clear (void); + void do_clear (void); - int do_where (void) const; + int do_where (void) const; - int do_length (void) const; + int do_length (void) const; - int do_max_input_history (void) const; + int do_max_input_history (void) const; - int do_base (void) const; + int do_base (void) const; - int do_current_number (void) const; + int do_current_number (void) const; - void do_stifle (int); + void do_stifle (int); - int do_unstifle (void); + int do_unstifle (void); - int do_is_stifled (void) const; + int do_is_stifled (void) const; - void do_set_mark (int); + void do_set_mark (int); - int do_goto_mark (void); + int do_goto_mark (void); - void do_read (const std::string&, bool); + void do_read (const std::string&, bool); - void do_read_range (const std::string&, int, int, bool); + void do_read_range (const std::string&, int, int, bool); - void do_write (const std::string&) const; + void do_write (const std::string&) const; - void do_append (const std::string&); + void do_append (const std::string&); - void do_truncate_file (const std::string&, int) const; + void do_truncate_file (const std::string&, int) const; - string_vector do_list (int, bool) const; + string_vector do_list (int, bool) const; - std::string do_get_entry (int) const; + std::string do_get_entry (int) const; - void do_replace_entry (int, const std::string&); + void do_replace_entry (int, const std::string&); - void do_clean_up_and_save (const std::string&, int); + void do_clean_up_and_save (const std::string&, int); - private: +private: - int mark; - }; + int mark; +}; - void - gnu_history::do_process_histcontrol (const std::string& control_arg) - { - m_history_control = 0; +void +gnu_history::do_process_histcontrol (const std::string& control_arg) +{ + m_history_control = 0; - std::size_t len = control_arg.length (); - std::size_t beg = 0; + std::size_t len = control_arg.length (); + std::size_t beg = 0; - while (beg < len) - { - if (control_arg[beg] == ':') - beg++; - else - { - std::size_t end = control_arg.find (':', beg); + while (beg < len) + { + if (control_arg[beg] == ':') + beg++; + else + { + std::size_t end = control_arg.find (':', beg); - if (end == std::string::npos) - end = len; + if (end == std::string::npos) + end = len; - std::string tmp = control_arg.substr (beg, end-beg); + std::string tmp = control_arg.substr (beg, end-beg); - if (tmp == "erasedups") - m_history_control |= HC_ERASEDUPS; - else if (tmp == "ignoreboth") - m_history_control |= (HC_IGNDUPS | HC_IGNSPACE); - else if (tmp == "ignoredups") - m_history_control |= HC_IGNDUPS; - else if (tmp == "ignorespace") - m_history_control |= HC_IGNSPACE; - else - (*current_liboctave_warning_with_id_handler) - ("Octave:history-control", - "unknown histcontrol directive %s", tmp.c_str ()); + if (tmp == "erasedups") + m_history_control |= HC_ERASEDUPS; + else if (tmp == "ignoreboth") + m_history_control |= (HC_IGNDUPS | HC_IGNSPACE); + else if (tmp == "ignoredups") + m_history_control |= HC_IGNDUPS; + else if (tmp == "ignorespace") + m_history_control |= HC_IGNSPACE; + else + (*current_liboctave_warning_with_id_handler) + ("Octave:history-control", + "unknown histcontrol directive %s", tmp.c_str ()); - if (end != std::string::npos) - beg = end + 1; - } - } - } + if (end != std::string::npos) + beg = end + 1; + } + } +} - std::string - gnu_history::do_histcontrol (void) const - { - // FIXME: instead of reconstructing this value, should we just save - // the string we were given when constructing the command_history object? +std::string +gnu_history::do_histcontrol (void) const +{ + // FIXME: instead of reconstructing this value, should we just save + // the string we were given when constructing the command_history object? - std::string retval; + std::string retval; - if (m_history_control & HC_IGNSPACE) - retval.append ("ignorespace"); + if (m_history_control & HC_IGNSPACE) + retval.append ("ignorespace"); - if (m_history_control & HC_IGNDUPS) - { - if (retval.length () > 0) - retval += ':'; + if (m_history_control & HC_IGNDUPS) + { + if (retval.length () > 0) + retval += ':'; - retval.append ("ignoredups"); - } + retval.append ("ignoredups"); + } - if (m_history_control & HC_ERASEDUPS) - { - if (retval.length () > 0) - retval += ':'; + if (m_history_control & HC_ERASEDUPS) + { + if (retval.length () > 0) + retval += ':'; - retval.append ("erasedups"); - } + retval.append ("erasedups"); + } - return retval; - } + return retval; +} - bool - gnu_history::do_add (const std::string& s) - { - if (! do_ignoring_entries ()) - { - if (s.empty () - || (s.length () == 1 && (s[0] == '\r' || s[0] == '\n'))) - return false; +bool +gnu_history::do_add (const std::string& s) +{ + if (! do_ignoring_entries ()) + { + if (s.empty () + || (s.length () == 1 && (s[0] == '\r' || s[0] == '\n'))) + return false; - // Strip newline before adding to list - std::string stmp = s; - if (stmp.back () == '\n') - stmp.pop_back (); + // Strip newline before adding to list + std::string stmp = s; + if (stmp.back () == '\n') + stmp.pop_back (); - int added = ::octave_add_history (stmp.c_str (), m_history_control); - m_lines_this_session += added; - return added > 0 ? true : false; - } - return false; - } + int added = ::octave_add_history (stmp.c_str (), m_history_control); + m_lines_this_session += added; + return added > 0 ? true : false; + } + return false; +} - void - gnu_history::do_remove (int n) - { - ::octave_remove_history (n); - } +void +gnu_history::do_remove (int n) +{ + ::octave_remove_history (n); +} - void - gnu_history::do_clear (void) - { - ::octave_clear_history (); - } +void +gnu_history::do_clear (void) +{ + ::octave_clear_history (); +} - int - gnu_history::do_where (void) const - { - return ::octave_where_history (); - } +int +gnu_history::do_where (void) const +{ + return ::octave_where_history (); +} - int - gnu_history::do_length (void) const - { - return ::octave_history_length (); - } +int +gnu_history::do_length (void) const +{ + return ::octave_history_length (); +} - int - gnu_history::do_max_input_history (void) const - { - return ::octave_max_input_history (); - } +int +gnu_history::do_max_input_history (void) const +{ + return ::octave_max_input_history (); +} - int - gnu_history::do_base (void) const - { - return ::octave_history_base (); - } +int +gnu_history::do_base (void) const +{ + return ::octave_history_base (); +} - int - gnu_history::do_current_number (void) const - { - return m_size > 0 ? do_base () + do_where () : -1; - } +int +gnu_history::do_current_number (void) const +{ + return m_size > 0 ? do_base () + do_where () : -1; +} - void - gnu_history::do_stifle (int n) - { - ::octave_stifle_history (n); - } +void +gnu_history::do_stifle (int n) +{ + ::octave_stifle_history (n); +} - int - gnu_history::do_unstifle (void) - { - return ::octave_unstifle_history (); - } +int +gnu_history::do_unstifle (void) +{ + return ::octave_unstifle_history (); +} - int - gnu_history::do_is_stifled (void) const - { - return ::octave_history_is_stifled (); - } +int +gnu_history::do_is_stifled (void) const +{ + return ::octave_history_is_stifled (); +} - void - gnu_history::do_set_mark (int n) - { - mark = n; - } +void +gnu_history::do_set_mark (int n) +{ + mark = n; +} - int - gnu_history::do_goto_mark (void) - { - if (mark) - { - char *line = ::octave_history_goto_mark (mark); +int +gnu_history::do_goto_mark (void) +{ + if (mark) + { + char *line = ::octave_history_goto_mark (mark); - if (line) - { - command_editor::insert_text (line); + if (line) + { + command_editor::insert_text (line); - command_editor::clear_undo_list (); - } - } + command_editor::clear_undo_list (); + } + } - mark = 0; + mark = 0; - // FIXME: for operate_and_get_next. - command_editor::remove_startup_hook (command_history::goto_mark); + // FIXME: for operate_and_get_next. + command_editor::remove_startup_hook (command_history::goto_mark); - return 0; - } + return 0; +} - void - gnu_history::do_read (const std::string& f, bool must_exist) - { - if (! f.empty ()) - { - int status = ::octave_read_history (f.c_str ()); +void +gnu_history::do_read (const std::string& f, bool must_exist) +{ + if (! f.empty ()) + { + int status = ::octave_read_history (f.c_str ()); - if (status != 0 && must_exist) - { - std::string msg = "reading file '" + f + "'"; + if (status != 0 && must_exist) + { + std::string msg = "reading file '" + f + "'"; - error (status, msg); - } - else - { - m_lines_in_file = do_where (); + error (status, msg); + } + else + { + m_lines_in_file = do_where (); - ::octave_using_history (); - } - } - else - error ("gnu_history::read: missing filename"); - } + ::octave_using_history (); + } + } + else + error ("gnu_history::read: missing filename"); +} - void - gnu_history::do_read_range (const std::string& f, int from, int to, - bool must_exist) - { - if (from < 0) - from = m_lines_in_file; +void +gnu_history::do_read_range (const std::string& f, int from, int to, + bool must_exist) +{ + if (from < 0) + from = m_lines_in_file; - if (! f.empty ()) - { - int status = ::octave_read_history_range (f.c_str (), from, to); + if (! f.empty ()) + { + int status = ::octave_read_history_range (f.c_str (), from, to); - if (status != 0 && must_exist) - { - std::ostringstream buf; - buf << "reading lines " << from << " to " << to - << " from file '" << f << "'"; + if (status != 0 && must_exist) + { + std::ostringstream buf; + buf << "reading lines " << from << " to " << to + << " from file '" << f << "'"; - error (status, buf.str ()); - } - else - { - m_lines_in_file = do_where (); + error (status, buf.str ()); + } + else + { + m_lines_in_file = do_where (); - ::octave_using_history (); - } - } - else - error ("gnu_history::read_range: missing filename"); - } + ::octave_using_history (); + } + } + else + error ("gnu_history::read_range: missing filename"); +} - void - gnu_history::do_write (const std::string& f_arg) const - { - if (m_initialized) - { - std::string f = f_arg; +void +gnu_history::do_write (const std::string& f_arg) const +{ + if (m_initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (! f.empty ()) - { - // Try to create the folder if it does not exist - std::string hist_dir = sys::file_ops::dirname (f); - if (! hist_dir.empty ()) - { - sys::file_stat fs (hist_dir); - if (! fs.is_dir () - && (sys::recursive_mkdir (hist_dir, 0777) < 0)) - (*current_liboctave_error_handler) - ("%s: Could not create directory \"%s\" for history", - "gnu_history::do_write", hist_dir.c_str ()); - } + if (! f.empty ()) + { + // Try to create the folder if it does not exist + std::string hist_dir = sys::file_ops::dirname (f); + if (! hist_dir.empty ()) + { + sys::file_stat fs (hist_dir); + if (! fs.is_dir () + && (sys::recursive_mkdir (hist_dir, 0777) < 0)) + (*current_liboctave_error_handler) + ("%s: Could not create directory \"%s\" for history", + "gnu_history::do_write", hist_dir.c_str ()); + } - int status = ::octave_write_history (f.c_str ()); + int status = ::octave_write_history (f.c_str ()); - if (status != 0) - { - std::string msg = "writing file '" + f + "'"; + if (status != 0) + { + std::string msg = "writing file '" + f + "'"; - error (status, msg); - } - } - else - error ("gnu_history::write: missing filename"); - } - } + error (status, msg); + } + } + else + error ("gnu_history::write: missing filename"); + } +} - void - gnu_history::do_append (const std::string& f_arg) - { - if (m_initialized) - { - if (m_lines_this_session) - { - if (m_lines_this_session < do_where ()) - { - // Create file if it doesn't already exist. +void +gnu_history::do_append (const std::string& f_arg) +{ + if (m_initialized) + { + if (m_lines_this_session) + { + if (m_lines_this_session < do_where ()) + { + // Create file if it doesn't already exist. - std::string f = f_arg; + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (! f.empty ()) - { - sys::file_stat fs (f); + if (! f.empty ()) + { + sys::file_stat fs (f); - if (! fs) - { - std::ofstream tmp = sys::ofstream (f, std::ios::out); - tmp.close (); - } + if (! fs) + { + std::ofstream tmp = sys::ofstream (f, std::ios::out); + tmp.close (); + } - int status - = ::octave_append_history (m_lines_this_session, f.c_str ()); + int status + = ::octave_append_history (m_lines_this_session, f.c_str ()); - if (status != 0) - { - std::string msg = "appending to file '" + f_arg + "'"; + if (status != 0) + { + std::string msg = "appending to file '" + f_arg + "'"; - error (status, msg); - } - else - m_lines_in_file += m_lines_this_session; + error (status, msg); + } + else + m_lines_in_file += m_lines_this_session; - m_lines_this_session = 0; - } - else - error ("gnu_history::append: missing filename"); - } - } - } - } + m_lines_this_session = 0; + } + else + error ("gnu_history::append: missing filename"); + } + } + } +} - void - gnu_history::do_truncate_file (const std::string& f_arg, int n) const - { - if (m_initialized) - { - std::string f = f_arg; +void +gnu_history::do_truncate_file (const std::string& f_arg, int n) const +{ + if (m_initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (! f.empty ()) - ::octave_history_truncate_file (f.c_str (), n); - else - error ("gnu_history::truncate_file: missing filename"); - } - } + if (! f.empty ()) + ::octave_history_truncate_file (f.c_str (), n); + else + error ("gnu_history::truncate_file: missing filename"); + } +} - string_vector - gnu_history::do_list (int limit, bool number_lines) const - { - string_vector retval; +string_vector +gnu_history::do_list (int limit, bool number_lines) const +{ + string_vector retval; - if (limit) - retval = ::octave_history_list (limit, number_lines); + if (limit) + retval = ::octave_history_list (limit, number_lines); - return retval; - } + return retval; +} - std::string - gnu_history::do_get_entry (int n) const - { - std::string retval; +std::string +gnu_history::do_get_entry (int n) const +{ + std::string retval; - char *line = ::octave_history_get (do_base () + n); + char *line = ::octave_history_get (do_base () + n); - if (line) - retval = line; + if (line) + retval = line; - return retval; - } + return retval; +} - void - gnu_history::do_replace_entry (int which, const std::string& line) - { - ::octave_replace_history_entry (which, line.c_str ()); - } +void +gnu_history::do_replace_entry (int which, const std::string& line) +{ + ::octave_replace_history_entry (which, line.c_str ()); +} - void - gnu_history::do_clean_up_and_save (const std::string& f_arg, int n) - { - if (m_initialized) - { - std::string f = f_arg; +void +gnu_history::do_clean_up_and_save (const std::string& f_arg, int n) +{ + if (m_initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (! f.empty ()) - { - if (n < 0) - n = m_size; + if (! f.empty ()) + { + if (n < 0) + n = m_size; - stifle (n); + stifle (n); - do_write (f.c_str ()); - } - else - error ("gnu_history::clean_up_and_save: missing filename"); - } - } + do_write (f.c_str ()); + } + else + error ("gnu_history::clean_up_and_save: missing filename"); + } +} #endif - bool - command_history::instance_ok (void) - { - bool retval = true; +bool +command_history::instance_ok (void) +{ + bool retval = true; - if (! s_instance) - { - make_command_history (); + if (! s_instance) + { + make_command_history (); - if (s_instance) - singleton_cleanup_list::add (cleanup_instance); - } + if (s_instance) + singleton_cleanup_list::add (cleanup_instance); + } - if (! s_instance) - (*current_liboctave_error_handler) - ("unable to create command history object!"); + if (! s_instance) + (*current_liboctave_error_handler) + ("unable to create command history object!"); - return retval; - } + return retval; +} - void - command_history::make_command_history (void) - { +void +command_history::make_command_history (void) +{ #if defined (USE_READLINE) - s_instance = new gnu_history (); + s_instance = new gnu_history (); #else - s_instance = new command_history (); + s_instance = new command_history (); #endif - } +} - void - command_history::initialize (bool read_history_file, - const std::string& f_arg, int sz, - const std::string & control_arg) - { - if (instance_ok ()) - s_instance->do_initialize (read_history_file, f_arg, sz, control_arg); - } +void +command_history::initialize (bool read_history_file, + const std::string& f_arg, int sz, + const std::string& control_arg) +{ + if (instance_ok ()) + s_instance->do_initialize (read_history_file, f_arg, sz, control_arg); +} - bool - command_history::is_initialized (void) - { - // We just want to check the status of an existing instance, not - // create one. - return s_instance && s_instance->do_is_initialized (); - } +bool +command_history::is_initialized (void) +{ + // We just want to check the status of an existing instance, not + // create one. + return s_instance && s_instance->do_is_initialized (); +} - void - command_history::set_file (const std::string& f_arg) - { - if (instance_ok ()) - { - std::string f = sys::file_ops::tilde_expand (f_arg); +void +command_history::set_file (const std::string& f_arg) +{ + if (instance_ok ()) + { + std::string f = sys::file_ops::tilde_expand (f_arg); - s_instance->do_set_file (f); - } - } + s_instance->do_set_file (f); + } +} - std::string - command_history::file (void) - { - return instance_ok () ? s_instance->do_file () : ""; - } +std::string +command_history::file (void) +{ + return instance_ok () ? s_instance->do_file () : ""; +} - void - command_history::process_histcontrol (const std::string& control_arg) - { - if (instance_ok ()) - s_instance->do_process_histcontrol (control_arg); - } +void +command_history::process_histcontrol (const std::string& control_arg) +{ + if (instance_ok ()) + s_instance->do_process_histcontrol (control_arg); +} - std::string - command_history::histcontrol (void) - { - return instance_ok () ? s_instance->do_histcontrol () : ""; - } +std::string +command_history::histcontrol (void) +{ + return instance_ok () ? s_instance->do_histcontrol () : ""; +} - void - command_history::set_size (int n) - { - if (instance_ok ()) - s_instance->do_set_size (n); - } +void +command_history::set_size (int n) +{ + if (instance_ok ()) + s_instance->do_set_size (n); +} - int - command_history::size (void) - { - return instance_ok () ? s_instance->do_size () : 0; - } +int +command_history::size (void) +{ + return instance_ok () ? s_instance->do_size () : 0; +} - void - command_history::ignore_entries (bool flag) - { - if (instance_ok ()) - s_instance->do_ignore_entries (flag); - } +void +command_history::ignore_entries (bool flag) +{ + if (instance_ok ()) + s_instance->do_ignore_entries (flag); +} - bool - command_history::ignoring_entries (void) - { - return instance_ok () ? s_instance->do_ignoring_entries () : false; - } +bool +command_history::ignoring_entries (void) +{ + return instance_ok () ? s_instance->do_ignoring_entries () : false; +} - bool - command_history::add (const std::string& s) - { - if (instance_ok ()) - return s_instance->do_add (s); - return false; - } +bool +command_history::add (const std::string& s) +{ + if (instance_ok ()) + return s_instance->do_add (s); + return false; +} - void - command_history::remove (int n) - { - if (instance_ok ()) - s_instance->do_remove (n); - } +void +command_history::remove (int n) +{ + if (instance_ok ()) + s_instance->do_remove (n); +} - void - command_history::clear (void) - { - if (instance_ok ()) - s_instance->do_clear (); - } +void +command_history::clear (void) +{ + if (instance_ok ()) + s_instance->do_clear (); +} - int - command_history::where (void) - { - return instance_ok () ? s_instance->do_where () : 0; - } +int +command_history::where (void) +{ + return instance_ok () ? s_instance->do_where () : 0; +} - int - command_history::length (void) - { - return instance_ok () ? s_instance->do_length () : 0; - } +int +command_history::length (void) +{ + return instance_ok () ? s_instance->do_length () : 0; +} - int - command_history::max_input_history (void) - { - return instance_ok () ? s_instance->do_max_input_history () : 0; - } +int +command_history::max_input_history (void) +{ + return instance_ok () ? s_instance->do_max_input_history () : 0; +} - int - command_history::base (void) - { - return instance_ok () ? s_instance->do_base () : 0; - } +int +command_history::base (void) +{ + return instance_ok () ? s_instance->do_base () : 0; +} - int - command_history::current_number (void) - { - return instance_ok () ? s_instance->do_current_number () : 0; - } +int +command_history::current_number (void) +{ + return instance_ok () ? s_instance->do_current_number () : 0; +} - void - command_history::stifle (int n) - { - if (instance_ok ()) - s_instance->do_stifle (n); - } +void +command_history::stifle (int n) +{ + if (instance_ok ()) + s_instance->do_stifle (n); +} - int - command_history::unstifle (void) - { - return instance_ok () ? s_instance->do_unstifle () : 0; - } +int +command_history::unstifle (void) +{ + return instance_ok () ? s_instance->do_unstifle () : 0; +} - int - command_history::is_stifled (void) - { - return instance_ok () ? s_instance->do_is_stifled () : 0; - } +int +command_history::is_stifled (void) +{ + return instance_ok () ? s_instance->do_is_stifled () : 0; +} - void - command_history::set_mark (int n) - { - if (instance_ok ()) - s_instance->do_set_mark (n); - } +void +command_history::set_mark (int n) +{ + if (instance_ok ()) + s_instance->do_set_mark (n); +} - int - command_history::goto_mark (void) - { - return instance_ok () ? s_instance->do_goto_mark () : 0; - } +int +command_history::goto_mark (void) +{ + return instance_ok () ? s_instance->do_goto_mark () : 0; +} - void - command_history::read (bool must_exist) - { - read (file (), must_exist); - } +void +command_history::read (bool must_exist) +{ + read (file (), must_exist); +} - void - command_history::read (const std::string& f, bool must_exist) - { - if (instance_ok ()) - s_instance->do_read (f, must_exist); - } +void +command_history::read (const std::string& f, bool must_exist) +{ + if (instance_ok ()) + s_instance->do_read (f, must_exist); +} - void - command_history::read_range (int from, int to, bool must_exist) - { - read_range (file (), from, to, must_exist); - } +void +command_history::read_range (int from, int to, bool must_exist) +{ + read_range (file (), from, to, must_exist); +} - void - command_history::read_range (const std::string& f, int from, int to, - bool must_exist) - { - if (instance_ok ()) - s_instance->do_read_range (f, from, to, must_exist); - } +void +command_history::read_range (const std::string& f, int from, int to, + bool must_exist) +{ + if (instance_ok ()) + s_instance->do_read_range (f, from, to, must_exist); +} - void - command_history::write (const std::string& f) - { - if (instance_ok ()) - s_instance->do_write (f); - } +void +command_history::write (const std::string& f) +{ + if (instance_ok ()) + s_instance->do_write (f); +} - void - command_history::append (const std::string& f) - { - if (instance_ok ()) - s_instance->do_append (f); - } +void +command_history::append (const std::string& f) +{ + if (instance_ok ()) + s_instance->do_append (f); +} - void - command_history::truncate_file (const std::string& f, int n) - { - if (instance_ok ()) - s_instance->do_truncate_file (f, n); - } +void +command_history::truncate_file (const std::string& f, int n) +{ + if (instance_ok ()) + s_instance->do_truncate_file (f, n); +} - string_vector - command_history::list (int limit, bool number_lines) - { - return (instance_ok () - ? s_instance->do_list (limit, number_lines) : string_vector ()); - } +string_vector +command_history::list (int limit, bool number_lines) +{ + return (instance_ok () + ? s_instance->do_list (limit, number_lines) : string_vector ()); +} - std::string - command_history::get_entry (int n) - { - return instance_ok () ? s_instance->do_get_entry (n) : ""; - } +std::string +command_history::get_entry (int n) +{ + return instance_ok () ? s_instance->do_get_entry (n) : ""; +} - void - command_history::replace_entry (int which, const std::string& line) - { - if (instance_ok ()) - s_instance->do_replace_entry (which, line); - } +void +command_history::replace_entry (int which, const std::string& line) +{ + if (instance_ok ()) + s_instance->do_replace_entry (which, line); +} - void - command_history::clean_up_and_save (const std::string& f, int n) - { - if (instance_ok ()) - s_instance->do_clean_up_and_save (f, n); - } +void +command_history::clean_up_and_save (const std::string& f, int n) +{ + if (instance_ok ()) + s_instance->do_clean_up_and_save (f, n); +} - void - command_history::do_process_histcontrol (const std::string&) - { } +void +command_history::do_process_histcontrol (const std::string&) +{ } - void - command_history::do_initialize (bool read_history_file, - const std::string& f_arg, int sz, - const std::string & control_arg) - { - command_history::set_file (f_arg); - command_history::set_size (sz); - command_history::process_histcontrol (control_arg); +void +command_history::do_initialize (bool read_history_file, + const std::string& f_arg, int sz, + const std::string& control_arg) +{ + command_history::set_file (f_arg); + command_history::set_size (sz); + command_history::process_histcontrol (control_arg); - if (read_history_file) - command_history::read (false); + if (read_history_file) + command_history::read (false); - m_initialized = true; - } + m_initialized = true; +} - bool - command_history::do_is_initialized (void) const - { - return m_initialized; - } +bool +command_history::do_is_initialized (void) const +{ + return m_initialized; +} - void - command_history::do_set_file (const std::string& f) - { - m_file = f; - } +void +command_history::do_set_file (const std::string& f) +{ + m_file = f; +} - std::string - command_history::do_file (void) - { - return m_file; - } +std::string +command_history::do_file (void) +{ + return m_file; +} - void - command_history::do_set_size (int n) - { - m_size = n; - } +void +command_history::do_set_size (int n) +{ + m_size = n; +} - int - command_history::do_size (void) const - { - return m_size; - } +int +command_history::do_size (void) const +{ + return m_size; +} - void - command_history::do_ignore_entries (bool flag) - { - m_ignoring_additions = flag; - } +void +command_history::do_ignore_entries (bool flag) +{ + m_ignoring_additions = flag; +} - bool - command_history::do_ignoring_entries (void) const - { - return m_ignoring_additions; - } +bool +command_history::do_ignoring_entries (void) const +{ + return m_ignoring_additions; +} - bool - command_history::do_add (const std::string&) - { - return false; - } +bool +command_history::do_add (const std::string&) +{ + return false; +} - void - command_history::do_remove (int) - { } +void +command_history::do_remove (int) +{ } - void - command_history::do_clear (void) - { } +void +command_history::do_clear (void) +{ } - int - command_history::do_where (void) const - { - return 0; - } +int +command_history::do_where (void) const +{ + return 0; +} - int - command_history::do_length (void) const - { - return 0; - } +int +command_history::do_length (void) const +{ + return 0; +} - int - command_history::do_max_input_history (void) const - { - return 0; - } +int +command_history::do_max_input_history (void) const +{ + return 0; +} - int - command_history::do_base (void) const - { - return 0; - } +int +command_history::do_base (void) const +{ + return 0; +} - int - command_history::do_current_number (void) const - { - return m_size > 0 ? do_base () + do_where () : -1; - } +int +command_history::do_current_number (void) const +{ + return m_size > 0 ? do_base () + do_where () : -1; +} - void - command_history::do_stifle (int) - { } +void +command_history::do_stifle (int) +{ } - int - command_history::do_unstifle (void) - { - return -1; - } +int +command_history::do_unstifle (void) +{ + return -1; +} - int - command_history::do_is_stifled (void) const - { - return 0; - } +int +command_history::do_is_stifled (void) const +{ + return 0; +} - void - command_history::do_set_mark (int) - { } +void +command_history::do_set_mark (int) +{ } - int - command_history::do_goto_mark (void) - { - return 0; - } +int +command_history::do_goto_mark (void) +{ + return 0; +} - void - command_history::do_read (const std::string& f, bool) - { - if (f.empty ()) - error ("command_history::read: missing filename"); - } +void +command_history::do_read (const std::string& f, bool) +{ + if (f.empty ()) + error ("command_history::read: missing filename"); +} - void - command_history::do_read_range (const std::string& f, int, int, bool) - { - if (f.empty ()) - error ("command_history::read_range: missing filename"); - } +void +command_history::do_read_range (const std::string& f, int, int, bool) +{ + if (f.empty ()) + error ("command_history::read_range: missing filename"); +} - void - command_history::do_write (const std::string& f_arg) const - { - if (m_initialized) - { - std::string f = f_arg; +void +command_history::do_write (const std::string& f_arg) const +{ + if (m_initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (f.empty ()) - error ("command_history::write: missing filename"); - } - } + if (f.empty ()) + error ("command_history::write: missing filename"); + } +} - void - command_history::do_append (const std::string& f_arg) - { - if (m_initialized) - { - if (m_lines_this_session) - { - if (m_lines_this_session < do_where ()) - { - // Create file if it doesn't already exist. +void +command_history::do_append (const std::string& f_arg) +{ + if (m_initialized) + { + if (m_lines_this_session) + { + if (m_lines_this_session < do_where ()) + { + // Create file if it doesn't already exist. - std::string f = f_arg; + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (f.empty ()) - error ("command_history::append: missing filename"); - } - } - } - } + if (f.empty ()) + error ("command_history::append: missing filename"); + } + } + } +} - void - command_history::do_truncate_file (const std::string& f_arg, int) const - { - if (m_initialized) - { - std::string f = f_arg; +void +command_history::do_truncate_file (const std::string& f_arg, int) const +{ + if (m_initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (f.empty ()) - error ("command_history::truncate_file: missing filename"); - } - } + if (f.empty ()) + error ("command_history::truncate_file: missing filename"); + } +} - string_vector - command_history::do_list (int, bool) const - { - return string_vector (); - } +string_vector +command_history::do_list (int, bool) const +{ + return string_vector (); +} - std::string - command_history::do_get_entry (int) const - { - return ""; - } +std::string +command_history::do_get_entry (int) const +{ + return ""; +} - void - command_history::do_replace_entry (int, const std::string&) - { } +void +command_history::do_replace_entry (int, const std::string&) +{ } - void - command_history::do_clean_up_and_save (const std::string& f_arg, int) - { - if (m_initialized) - { - std::string f = f_arg; +void +command_history::do_clean_up_and_save (const std::string& f_arg, int) +{ + if (m_initialized) + { + std::string f = f_arg; - if (f.empty ()) - f = m_file; + if (f.empty ()) + f = m_file; - if (f.empty ()) - error ("command_history::clean_up_and_save: missing filename"); - } - } + if (f.empty ()) + error ("command_history::clean_up_and_save: missing filename"); + } +} - void - command_history::error (int err_num, const std::string& msg) const - { - if (msg.empty ()) - (*current_liboctave_error_handler) ("%s", std::strerror (err_num)); - else - (*current_liboctave_error_handler) ("%s: %s", msg.c_str (), - std::strerror (err_num)); - } +void +command_history::error (int err_num, const std::string& msg) const +{ + if (msg.empty ()) + (*current_liboctave_error_handler) ("%s", std::strerror (err_num)); + else + (*current_liboctave_error_handler) ("%s: %s", msg.c_str (), + std::strerror (err_num)); +} - void - command_history::error (const std::string& s) const - { - (*current_liboctave_error_handler) ("%s", s.c_str ()); - } +void +command_history::error (const std::string& s) const +{ + (*current_liboctave_error_handler) ("%s", s.c_str ()); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/cmd-hist.h --- a/liboctave/util/cmd-hist.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/cmd-hist.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,212 +34,212 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTAVE_API - command_history - { - protected: +class +OCTAVE_API +command_history +{ +protected: - command_history (void) - : m_initialized (false), m_ignoring_additions (false), - m_history_control (0), m_lines_in_file (0), - m_lines_this_session (0), m_file (), m_size (-1) - { } + command_history (void) + : m_initialized (false), m_ignoring_additions (false), + m_history_control (0), m_lines_in_file (0), + m_lines_this_session (0), m_file (), m_size (-1) + { } - public: +public: - // No copying! + // No copying! - command_history (const command_history&) = delete; + command_history (const command_history&) = delete; - command_history& operator = (const command_history&) = delete; + command_history& operator = (const command_history&) = delete; - virtual ~command_history (void) = default; + virtual ~command_history (void) = default; - static void initialize (bool, const std::string&, int, const std::string&); + static void initialize (bool, const std::string&, int, const std::string&); - static bool is_initialized (void); + static bool is_initialized (void); - static void set_file (const std::string&); + static void set_file (const std::string&); - static std::string file (void); + static std::string file (void); - static void process_histcontrol (const std::string&); + static void process_histcontrol (const std::string&); - static std::string histcontrol (void); + static std::string histcontrol (void); - static void set_size (int); + static void set_size (int); - static int size (void); + static int size (void); - static void ignore_entries (bool = true); + static void ignore_entries (bool = true); - static bool ignoring_entries (void); + static bool ignoring_entries (void); - static bool add (const std::string&); + static bool add (const std::string&); - static void remove (int); + static void remove (int); - static void clear (void); + static void clear (void); - static int where (void); + static int where (void); - static int length (void); + static int length (void); - static int max_input_history (void); + static int max_input_history (void); - static int base (void); + static int base (void); - static int current_number (void); + static int current_number (void); - static void stifle (int); + static void stifle (int); - static int unstifle (void); + static int unstifle (void); - static int is_stifled (void); + static int is_stifled (void); - static void set_mark (int n); + static void set_mark (int n); - // Gag. This declaration has to match the Function typedef in - // readline.h. + // Gag. This declaration has to match the Function typedef in + // readline.h. - static int goto_mark (void); + static int goto_mark (void); - static void read (bool = true); + static void read (bool = true); - static void read (const std::string&, bool = true); + static void read (const std::string&, bool = true); - static void read_range (int = -1, int = -1, bool = true); + static void read_range (int = -1, int = -1, bool = true); - static void read_range (const std::string&, int = -1, int = -1, - bool = true); + static void read_range (const std::string&, int = -1, int = -1, + bool = true); - static void write (const std::string& = ""); + static void write (const std::string& = ""); - static void append (const std::string& = ""); + static void append (const std::string& = ""); - static void truncate_file (const std::string& = "", int = -1); + static void truncate_file (const std::string& = "", int = -1); - static string_vector list (int = -1, bool = false); + static string_vector list (int = -1, bool = false); - static std::string get_entry (int); + static std::string get_entry (int); - static void replace_entry (int, const std::string&); + static void replace_entry (int, const std::string&); - static void clean_up_and_save (const std::string& = "", int = -1); + static void clean_up_and_save (const std::string& = "", int = -1); - private: +private: - static bool instance_ok (void); + static bool instance_ok (void); - static void make_command_history (void); + static void make_command_history (void); - // The real thing. - static command_history *s_instance; + // The real thing. + static command_history *s_instance; - static void cleanup_instance (void) - { - delete s_instance; - s_instance = nullptr; - } + static void cleanup_instance (void) + { + delete s_instance; + s_instance = nullptr; + } - protected: +protected: - // To use something other than the GNU history library, derive a new - // class from command_history, overload these functions as - // necessary, and make instance point to the new class. + // To use something other than the GNU history library, derive a new + // class from command_history, overload these functions as + // necessary, and make instance point to the new class. - virtual void do_set_file (const std::string&); + virtual void do_set_file (const std::string&); - virtual std::string do_file (void); + virtual std::string do_file (void); - virtual void do_process_histcontrol (const std::string&); + virtual void do_process_histcontrol (const std::string&); - virtual std::string do_histcontrol (void) const { return ""; } + virtual std::string do_histcontrol (void) const { return ""; } - virtual void do_initialize (bool, const std::string&, int, - const std::string&); + virtual void do_initialize (bool, const std::string&, int, + const std::string&); - virtual bool do_is_initialized (void) const; + virtual bool do_is_initialized (void) const; - virtual void do_set_size (int); + virtual void do_set_size (int); - virtual int do_size (void) const; + virtual int do_size (void) const; - virtual void do_ignore_entries (bool); + virtual void do_ignore_entries (bool); - virtual bool do_ignoring_entries (void) const; + virtual bool do_ignoring_entries (void) const; - virtual bool do_add (const std::string&); + virtual bool do_add (const std::string&); - virtual void do_remove (int); + virtual void do_remove (int); - virtual void do_clear (void); + virtual void do_clear (void); - virtual int do_where (void) const; + virtual int do_where (void) const; - virtual int do_length (void) const; + virtual int do_length (void) const; - virtual int do_max_input_history (void) const; + virtual int do_max_input_history (void) const; - virtual int do_base (void) const; + virtual int do_base (void) const; - virtual int do_current_number (void) const; + virtual int do_current_number (void) const; - virtual void do_stifle (int); + virtual void do_stifle (int); - virtual int do_unstifle (void); + virtual int do_unstifle (void); - virtual int do_is_stifled (void) const; + virtual int do_is_stifled (void) const; - virtual void do_set_mark (int); + virtual void do_set_mark (int); - virtual int do_goto_mark (void); + virtual int do_goto_mark (void); - virtual void do_read (const std::string&, bool); + virtual void do_read (const std::string&, bool); - virtual void do_read_range (const std::string&, int, int, bool); + virtual void do_read_range (const std::string&, int, int, bool); - virtual void do_write (const std::string&) const; + virtual void do_write (const std::string&) const; - virtual void do_append (const std::string&); + virtual void do_append (const std::string&); - virtual void do_truncate_file (const std::string&, int) const; + virtual void do_truncate_file (const std::string&, int) const; - virtual string_vector do_list (int, bool) const; + virtual string_vector do_list (int, bool) const; - virtual std::string do_get_entry (int) const; + virtual std::string do_get_entry (int) const; - virtual void do_replace_entry (int, const std::string&); + virtual void do_replace_entry (int, const std::string&); - virtual void do_clean_up_and_save (const std::string&, int); + virtual void do_clean_up_and_save (const std::string&, int); - void error (int, const std::string& msg = "") const; + void error (int, const std::string& msg = "") const; - void error (const std::string&) const; + void error (const std::string&) const; - // TRUE means we have initialized the history filename and number of - // lines to save. - bool m_initialized; + // TRUE means we have initialized the history filename and number of + // lines to save. + bool m_initialized; - // TRUE means we are ignoring new additions. - bool m_ignoring_additions; + // TRUE means we are ignoring new additions. + bool m_ignoring_additions; - // Bitmask for history control options. See oct-rl-hist.h. - int m_history_control; + // Bitmask for history control options. See oct-rl-hist.h. + int m_history_control; - // The number of history lines we read from the history file. - int m_lines_in_file; + // The number of history lines we read from the history file. + int m_lines_in_file; - // The number of history lines we've saved so far. - int m_lines_this_session; + // The number of history lines we've saved so far. + int m_lines_this_session; - // The default history file. - std::string m_file; + // The default history file. + std::string m_file; - // The number of lines of history to save. - int m_size; - }; + // The number of lines of history to save. + int m_size; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/f77-fcn.h --- a/liboctave/util/f77-fcn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/f77-fcn.h Thu Dec 01 20:05:44 2022 -0800 @@ -338,16 +338,16 @@ OCTAVE_BEGIN_NAMESPACE(octave) - inline F77_INT - to_f77_int (octave_idx_type x) - { - if (x < std::numeric_limits::min () - || x > std::numeric_limits::max ()) - (*current_liboctave_error_handler) - ("integer dimension or index out of range for Fortran INTEGER type"); +inline F77_INT +to_f77_int (octave_idx_type x) +{ + if (x < std::numeric_limits::min () + || x > std::numeric_limits::max ()) + (*current_liboctave_error_handler) + ("integer dimension or index out of range for Fortran INTEGER type"); - return static_cast (x); - } + return static_cast (x); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/file-info.cc --- a/liboctave/util/file-info.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/file-info.cc Thu Dec 01 20:05:44 2022 -0800 @@ -37,107 +37,107 @@ OCTAVE_BEGIN_NAMESPACE(octave) - std::string file_info::get_line (std::size_t line) const - { - std::string retval; +std::string file_info::get_line (std::size_t line) const +{ + std::string retval; - if (line == 0) - return retval; + if (line == 0) + return retval; - if (line < m_offsets.size ()) - { - std::size_t bol = m_offsets[line-1]; - std::size_t eol = m_offsets[line]; + if (line < m_offsets.size ()) + { + std::size_t bol = m_offsets[line-1]; + std::size_t eol = m_offsets[line]; - while (eol > 0 && eol > bol - && (m_file_buf[eol-1] == '\n' || m_file_buf[eol-1] == '\r')) - eol--; + while (eol > 0 && eol > bol + && (m_file_buf[eol-1] == '\n' || m_file_buf[eol-1] == '\r')) + eol--; - retval = m_file_buf.substr (bol, eol - bol); - } + retval = m_file_buf.substr (bol, eol - bol); + } - return retval; - } + return retval; +} - std::deque - file_info::get_lines (std::size_t line, std::size_t num_lines) const - { - std::deque retval; +std::deque +file_info::get_lines (std::size_t line, std::size_t num_lines) const +{ + std::deque retval; - for (std::size_t i = line; i < line+num_lines; i++) - retval.push_back (get_line (i)); + for (std::size_t i = line; i < line+num_lines; i++) + retval.push_back (get_line (i)); - return retval; - } + return retval; +} - // Read entire file called fname and return the contents as a string +// Read entire file called fname and return the contents as a string - std::string file_info::snarf_file (const std::string& fname) - { - std::string retval; +std::string file_info::snarf_file (const std::string& fname) +{ + std::string retval; - sys::file_stat fs (fname); + sys::file_stat fs (fname); - if (! fs) - (*current_liboctave_error_handler) ("no such file, '%s'", fname.c_str ()); + if (! fs) + (*current_liboctave_error_handler) ("no such file, '%s'", fname.c_str ()); - std::size_t sz = fs.size (); + std::size_t sz = fs.size (); - std::ifstream file = sys::ifstream (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) - { - std::string buf (sz+1, 0); + if (file) + { + std::string buf (sz+1, 0); - file.read (&buf[0], sz+1); + file.read (&buf[0], sz+1); - if (! file.eof ()) - (*current_liboctave_error_handler) - ("error reading file %s", fname.c_str ()); + if (! file.eof ()) + (*current_liboctave_error_handler) + ("error reading file %s", fname.c_str ()); - // Expected to read the entire file. - retval = buf; - } + // Expected to read the entire file. + retval = buf; + } - return retval; - } + return retval; +} - std::vector file_info::get_line_offsets (const std::string& buf) - { - std::deque tmp_offsets; +std::vector file_info::get_line_offsets (const std::string& buf) +{ + std::deque tmp_offsets; - tmp_offsets.push_back (0); + tmp_offsets.push_back (0); - std::size_t len = buf.length (); + std::size_t len = buf.length (); - for (std::size_t i = 0; i < len; i++) - { - char c = buf[i]; + for (std::size_t i = 0; i < len; i++) + { + char c = buf[i]; - if (c == '\r' && ++i < len) - { - c = buf[i]; + if (c == '\r' && ++i < len) + { + c = buf[i]; - if (c == '\n') - tmp_offsets.push_back (i+1); - else - tmp_offsets.push_back (i); - } - else if (c == '\n') - tmp_offsets.push_back (i+1); - } + if (c == '\n') + tmp_offsets.push_back (i+1); + else + tmp_offsets.push_back (i); + } + else if (c == '\n') + tmp_offsets.push_back (i+1); + } - tmp_offsets.push_back (len-1); + tmp_offsets.push_back (len-1); - std::size_t n = tmp_offsets.size (); + std::size_t n = tmp_offsets.size (); - std::vector retval (n); - std::size_t i = 0; - for (auto& elt : tmp_offsets) - retval[i++] = elt; + std::vector retval (n); + std::size_t i = 0; + for (auto& elt : tmp_offsets) + retval[i++] = elt; - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/file-info.h --- a/liboctave/util/file-info.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/file-info.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,62 +37,62 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class file_info - { - public: +class file_info +{ +public: - file_info (void) - : m_file_buf (), m_offsets (), m_timestamp (static_cast (0)) - { } + file_info (void) + : m_file_buf (), m_offsets (), m_timestamp (static_cast (0)) + { } - file_info (const std::string& text, const sys::time& timestamp) - : m_file_buf (text), m_offsets (get_line_offsets (m_file_buf)), - m_timestamp (timestamp) - { } + file_info (const std::string& text, const sys::time& timestamp) + : m_file_buf (text), m_offsets (get_line_offsets (m_file_buf)), + m_timestamp (timestamp) + { } - file_info (const std::string& fname) - : m_file_buf (snarf_file (fname)), - m_offsets (get_line_offsets (m_file_buf)), - m_timestamp () - { } + file_info (const std::string& fname) + : m_file_buf (snarf_file (fname)), + m_offsets (get_line_offsets (m_file_buf)), + m_timestamp () + { } - file_info (const file_info&) = default; + file_info (const file_info&) = default; - file_info& operator = (const file_info&) = default; + file_info& operator = (const file_info&) = default; - ~file_info (void) = default; + ~file_info (void) = default; - OCTAVE_API std::string get_line (std::size_t line) const; + OCTAVE_API std::string get_line (std::size_t line) const; - OCTAVE_API std::deque - get_lines (std::size_t line, std::size_t num_lines) const; + OCTAVE_API std::deque + get_lines (std::size_t line, std::size_t num_lines) const; - std::size_t num_lines (void) const { return m_offsets.size (); } + std::size_t num_lines (void) const { return m_offsets.size (); } - std::string text (void) const { return m_file_buf; } + std::string text (void) const { return m_file_buf; } - std::vector line_offsets (void) const { return m_offsets; } + std::vector line_offsets (void) const { return m_offsets; } - sys::time timestamp (void) const { return m_timestamp; } + sys::time timestamp (void) const { return m_timestamp; } - std::size_t size (void) const { return m_file_buf.length (); } + std::size_t size (void) const { return m_file_buf.length (); } - private: +private: - // File contents as a string. - std::string m_file_buf; + // File contents as a string. + std::string m_file_buf; - // Offsets to line beginnings. - std::vector m_offsets; + // Offsets to line beginnings. + std::vector m_offsets; - sys::time m_timestamp; + sys::time m_timestamp; - // Read entire file called fname and return the contents as a string - static OCTAVE_API std::string snarf_file (const std::string& fname); + // Read entire file called fname and return the contents as a string + static OCTAVE_API std::string snarf_file (const std::string& fname); - static OCTAVE_API std::vector - get_line_offsets (const std::string& buf); - }; + static OCTAVE_API std::vector + get_line_offsets (const std::string& buf); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-array-errwarn.cc --- a/liboctave/util/lo-array-errwarn.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-array-errwarn.cc Thu Dec 01 20:05:44 2022 -0800 @@ -38,269 +38,269 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Text constants used to shorten code below. +// Text constants used to shorten code below. - static const char *error_id_nonconformant_args - = "Octave:nonconformant-args"; +static const char *error_id_nonconformant_args + = "Octave:nonconformant-args"; - static const char *error_id_index_out_of_bounds - = "Octave:index-out-of-bounds"; +static const char *error_id_index_out_of_bounds + = "Octave:index-out-of-bounds"; - static const char *error_id_invalid_index = "Octave:invalid-index"; +static const char *error_id_invalid_index = "Octave:invalid-index"; - static const char *warning_id_nearly_singular_matrix - = "Octave:nearly-singular-matrix"; +static const char *warning_id_nearly_singular_matrix + = "Octave:nearly-singular-matrix"; - static const char *warning_id_singular_matrix = "Octave:singular-matrix"; +static const char *warning_id_singular_matrix = "Octave:singular-matrix"; - void - err_nan_to_logical_conversion (void) - { - (*current_liboctave_error_handler) - ("invalid conversion from NaN to logical"); - } +void +err_nan_to_logical_conversion (void) +{ + (*current_liboctave_error_handler) + ("invalid conversion from NaN to logical"); +} - void - err_nan_to_character_conversion (void) - { - (*current_liboctave_error_handler) - ("invalid conversion from NaN to character"); - } +void +err_nan_to_character_conversion (void) +{ + (*current_liboctave_error_handler) + ("invalid conversion from NaN to character"); +} - void - err_nonconformant (const char *op, - octave_idx_type op1_len, octave_idx_type op2_len) - { - const char *err_id = error_id_nonconformant_args; +void +err_nonconformant (const char *op, + octave_idx_type op1_len, octave_idx_type op2_len) +{ + const char *err_id = error_id_nonconformant_args; - (*current_liboctave_error_with_id_handler) - (err_id, "%s: nonconformant arguments (op1 len: %" OCTAVE_IDX_TYPE_FORMAT - ", op2 len: % " OCTAVE_IDX_TYPE_FORMAT ")", - op, op1_len, op2_len); - } + (*current_liboctave_error_with_id_handler) + (err_id, "%s: nonconformant arguments (op1 len: %" OCTAVE_IDX_TYPE_FORMAT + ", op2 len: % " OCTAVE_IDX_TYPE_FORMAT ")", + op, op1_len, op2_len); +} + +void +err_nonconformant (const char *op, + octave_idx_type op1_nr, octave_idx_type op1_nc, + octave_idx_type op2_nr, octave_idx_type op2_nc) +{ + const char *err_id = error_id_nonconformant_args; - void - err_nonconformant (const char *op, - octave_idx_type op1_nr, octave_idx_type op1_nc, - octave_idx_type op2_nr, octave_idx_type op2_nc) - { - const char *err_id = error_id_nonconformant_args; + (*current_liboctave_error_with_id_handler) + (err_id, "%s: nonconformant arguments " + "(op1 is %" OCTAVE_IDX_TYPE_FORMAT "x%" OCTAVE_IDX_TYPE_FORMAT ", " + "op2 is %" OCTAVE_IDX_TYPE_FORMAT"x%" OCTAVE_IDX_TYPE_FORMAT ")", + op, op1_nr, op1_nc, op2_nr, op2_nc); +} - (*current_liboctave_error_with_id_handler) - (err_id, "%s: nonconformant arguments " - "(op1 is %" OCTAVE_IDX_TYPE_FORMAT "x%" OCTAVE_IDX_TYPE_FORMAT ", " - "op2 is %" OCTAVE_IDX_TYPE_FORMAT"x%" OCTAVE_IDX_TYPE_FORMAT ")", - op, op1_nr, op1_nc, op2_nr, op2_nc); - } +void +err_nonconformant (const char *op, + const dim_vector& op1_dims, const dim_vector& op2_dims) +{ + const char *err_id = error_id_nonconformant_args; - void - err_nonconformant (const char *op, - const dim_vector& op1_dims, const dim_vector& op2_dims) - { - const char *err_id = error_id_nonconformant_args; + std::string op1_dims_str = op1_dims.str (); + std::string op2_dims_str = op2_dims.str (); - std::string op1_dims_str = op1_dims.str (); - std::string op2_dims_str = op2_dims.str (); + (*current_liboctave_error_with_id_handler) + (err_id, "%s: nonconformant arguments (op1 is %s, op2 is %s)", + op, op1_dims_str.c_str (), op2_dims_str.c_str ()); +} - (*current_liboctave_error_with_id_handler) - (err_id, "%s: nonconformant arguments (op1 is %s, op2 is %s)", - op, op1_dims_str.c_str (), op2_dims_str.c_str ()); - } +void +err_del_index_out_of_range (bool is1d, octave_idx_type idx, + octave_idx_type ext) +{ + const char *err_id = error_id_index_out_of_bounds; - void - err_del_index_out_of_range (bool is1d, octave_idx_type idx, - octave_idx_type ext) - { - const char *err_id = error_id_index_out_of_bounds; + (*current_liboctave_error_with_id_handler) + (err_id, "A(%s) = []: index out of bounds: value %" OCTAVE_IDX_TYPE_FORMAT + " out of bound %" OCTAVE_IDX_TYPE_FORMAT, + is1d ? "I" : "..,I,..", idx, ext); +} + +// Show the expression that caused the error, e.g., "A(-1,_)", +// "A(0+1i)", "A(_,3)". Show how many indices come before/after the +// offending one, e.g., (), (,_), or (_,,...[x5]...) - (*current_liboctave_error_with_id_handler) - (err_id, "A(%s) = []: index out of bounds: value %" OCTAVE_IDX_TYPE_FORMAT - " out of bound %" OCTAVE_IDX_TYPE_FORMAT, - is1d ? "I" : "..,I,..", idx, ext); - } - - // Show the expression that caused the error, e.g., "A(-1,_)", - // "A(0+1i)", "A(_,3)". Show how many indices come before/after the - // offending one, e.g., (), (,_), or (_,,...[x5]...) +std::string +index_exception::expression (void) const +{ + std::ostringstream buf; - std::string - index_exception::expression (void) const - { - std::ostringstream buf; + if (m_var.empty () || m_var == "") + buf << "index "; + else + buf << m_var; - if (m_var.empty () || m_var == "") - buf << "index "; - else - buf << m_var; + bool show_parens = m_dim > 0; + + if (show_parens) + { + if (m_dim < 5) + { + buf << '('; - bool show_parens = m_dim > 0; + for (octave_idx_type i = 1; i < m_dim; i++) + buf << "_,"; + } + else + buf << "(...[x" << m_dim - 1 << "]..."; + } - if (show_parens) - { - if (m_dim < 5) - { - buf << '('; + buf << m_index; - for (octave_idx_type i = 1; i < m_dim; i++) - buf << "_,"; - } - else - buf << "(...[x" << m_dim - 1 << "]..."; - } + if (show_parens) + { + if (m_nd - m_dim < 5) + { + for (octave_idx_type i = 0; i < m_nd - m_dim; i++) + buf << ",_"; - buf << m_index; + if (m_nd >= m_dim) + buf << ')'; + } + else + buf << "...[x" << m_nd - m_dim << "]...)"; + } - if (show_parens) - { - if (m_nd - m_dim < 5) - { - for (octave_idx_type i = 0; i < m_nd - m_dim; i++) - buf << ",_"; + return buf.str (); +} - if (m_nd >= m_dim) - buf << ')'; - } - else - buf << "...[x" << m_nd - m_dim << "]...)"; - } +class invalid_index : public index_exception +{ +public: - return buf.str (); + invalid_index (const std::string& value, octave_idx_type ndim, + octave_idx_type dimen) + : index_exception (value, ndim, dimen) + { + // Virtual, but the one we want to call is defined in this class. + update_message (); } - class invalid_index : public index_exception + void update_message (void) { - public: - - invalid_index (const std::string& value, octave_idx_type ndim, - octave_idx_type dimen) - : index_exception (value, ndim, dimen) - { - // Virtual, but the one we want to call is defined in this class. - update_message (); - } - - void update_message (void) - { - static std::string exp - = std::to_string (std::numeric_limits::digits); - - set_message (expression () - + ": subscripts must be either integers 1 to (2^" + exp - + ")-1 or logicals"); - } - - // ID of error to throw - const char * err_id (void) const - { - return error_id_invalid_index; - } - }; - - // Complain if an index is negative, fractional, or too big. + static std::string exp + = std::to_string (std::numeric_limits::digits); - void - err_invalid_index (const std::string& idx, octave_idx_type nd, - octave_idx_type dim, const std::string&) - { - invalid_index e (idx, nd, dim); - - throw e; - } - - void - err_invalid_index (octave_idx_type n, octave_idx_type nd, - octave_idx_type dim, const std::string& var) - { - err_invalid_index (std::to_string (n + 1), nd, dim, var); - } - - void - err_invalid_index (double n, octave_idx_type nd, octave_idx_type dim, - const std::string& var) - { - std::ostringstream buf; - buf << n + 1; - - if (! std::isnan (n)) - { - // if n not an integer, but would be printed as one, show diff - double nearest = std::floor (n + 1.5); - if (n + 1 != nearest && (buf.str ().find ('.') == std::string::npos)) - buf << std::showpos << (n + 1 - nearest); - } - - err_invalid_index (buf.str (), nd, dim, var); + set_message (expression () + + ": subscripts must be either integers 1 to (2^" + exp + + ")-1 or logicals"); } - // Complain for read access beyond the bounds of an array. - - class out_of_range : public index_exception + // ID of error to throw + const char * err_id (void) const { - public: + return error_id_invalid_index; + } +}; + +// Complain if an index is negative, fractional, or too big. + +void +err_invalid_index (const std::string& idx, octave_idx_type nd, + octave_idx_type dim, const std::string&) +{ + invalid_index e (idx, nd, dim); + + throw e; +} - out_of_range (const std::string& value, octave_idx_type nd, - octave_idx_type dim, octave_idx_type ext, - const dim_vector& size) - : index_exception (value, nd, dim), m_size (size), m_extent (ext) +void +err_invalid_index (octave_idx_type n, octave_idx_type nd, + octave_idx_type dim, const std::string& var) +{ + err_invalid_index (std::to_string (n + 1), nd, dim, var); +} + +void +err_invalid_index (double n, octave_idx_type nd, octave_idx_type dim, + const std::string& var) +{ + std::ostringstream buf; + buf << n + 1; + + if (! std::isnan (n)) { - // Virtual, but the one we want to call is defined in this class. - update_message (); - } - - void update_message (void) - { - set_message (expression () + ": out of bound " - + std::to_string (m_extent) - + " (dimensions are " + m_size.str ('x') + ")"); - } - - // ID of error to throw. - const char * err_id (void) const - { - return error_id_index_out_of_bounds; + // if n not an integer, but would be printed as one, show diff + double nearest = std::floor (n + 1.5); + if (n + 1 != nearest && (buf.str ().find ('.') == std::string::npos)) + buf << std::showpos << (n + 1 - nearest); } - private: + err_invalid_index (buf.str (), nd, dim, var); +} - // Dimension of object being accessed. - dim_vector m_size; +// Complain for read access beyond the bounds of an array. + +class out_of_range : public index_exception +{ +public: - // Length of dimension being accessed. - octave_idx_type m_extent; - }; + out_of_range (const std::string& value, octave_idx_type nd, + octave_idx_type dim, octave_idx_type ext, + const dim_vector& size) + : index_exception (value, nd, dim), m_size (size), m_extent (ext) + { + // Virtual, but the one we want to call is defined in this class. + update_message (); + } - // Complain of an index that is out of range - void - err_index_out_of_range (int nd, int dim, octave_idx_type idx, - octave_idx_type ext, const dim_vector& dv) + void update_message (void) { - throw out_of_range (std::to_string (idx), nd, dim, ext, dv); + set_message (expression () + ": out of bound " + + std::to_string (m_extent) + + " (dimensions are " + m_size.str ('x') + ")"); + } + + // ID of error to throw. + const char * err_id (void) const + { + return error_id_index_out_of_bounds; } - void - err_invalid_resize (void) - { - (*current_liboctave_error_with_id_handler) - ("Octave:invalid-resize", - "Invalid resizing operation or ambiguous assignment to an out-of-bounds array element"); - } +private: + + // Dimension of object being accessed. + dim_vector m_size; + + // Length of dimension being accessed. + octave_idx_type m_extent; +}; + +// Complain of an index that is out of range +void +err_index_out_of_range (int nd, int dim, octave_idx_type idx, + octave_idx_type ext, const dim_vector& dv) +{ + throw out_of_range (std::to_string (idx), nd, dim, ext, dv); +} - void - warn_singular_matrix (double rcond) - { - if (rcond == 0.0) - { - (*current_liboctave_warning_with_id_handler) - (warning_id_singular_matrix, - "matrix singular to machine precision"); - } - else - { - (*current_liboctave_warning_with_id_handler) - (warning_id_nearly_singular_matrix, - "matrix singular to machine precision, rcond = %g", rcond); - } - } +void +err_invalid_resize (void) +{ + (*current_liboctave_error_with_id_handler) + ("Octave:invalid-resize", + "Invalid resizing operation or ambiguous assignment to an out-of-bounds array element"); +} + +void +warn_singular_matrix (double rcond) +{ + if (rcond == 0.0) + { + (*current_liboctave_warning_with_id_handler) + (warning_id_singular_matrix, + "matrix singular to machine precision"); + } + else + { + (*current_liboctave_warning_with_id_handler) + (warning_id_nearly_singular_matrix, + "matrix singular to machine precision, rcond = %g", rcond); + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-array-errwarn.h --- a/liboctave/util/lo-array-errwarn.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-array-errwarn.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,128 +33,128 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Exception thrown by err_invalid_index - // This is thrown when the invalid index is detected, at which point nd and dim - // are usually not known. It is caught at the place they are known, where a - // new err_invalid_index is called. - // - // Typically, this should be caught after any call to - // octave_value_list::index_vector() +// Exception thrown by err_invalid_index +// This is thrown when the invalid index is detected, at which point nd and dim +// are usually not known. It is caught at the place they are known, where a +// new err_invalid_index is called. +// +// Typically, this should be caught after any call to +// octave_value_list::index_vector() - class OCTAVE_EXCEPTION_API index_exception : public execution_exception - { - public: +class OCTAVE_EXCEPTION_API index_exception : public execution_exception +{ +public: - index_exception (const std::string& index, octave_idx_type nd = 0, - octave_idx_type dim = -1, const char *var = "") - : m_index (index), m_nd (nd), m_dim (dim), m_var (var) - { - set_message (expression ()); - } + index_exception (const std::string& index, octave_idx_type nd = 0, + octave_idx_type dim = -1, const char *var = "") + : m_index (index), m_nd (nd), m_dim (dim), m_var (var) + { + set_message (expression ()); + } - ~index_exception (void) = default; + ~index_exception (void) = default; - // ID of error to throw. - virtual const char * err_id (void) const = 0; + // ID of error to throw. + virtual const char * err_id (void) const = 0; - // By default, update message to show the erroneous index expression. - virtual void update_message (void) { set_message (expression ()); } + // By default, update message to show the erroneous index expression. + virtual void update_message (void) { set_message (expression ()); } - // Position of error: dimension in error, and number of dimensions. - void set_pos (octave_idx_type nd_arg, octave_idx_type dim_arg) - { - m_nd = nd_arg; - m_dim = dim_arg; + // Position of error: dimension in error, and number of dimensions. + void set_pos (octave_idx_type nd_arg, octave_idx_type dim_arg) + { + m_nd = nd_arg; + m_dim = dim_arg; - update_message (); - } + update_message (); + } - void set_pos_if_unset (octave_idx_type nd_arg, octave_idx_type dim_arg) - { - if (m_nd == 0) - { - m_nd = nd_arg; - m_dim = dim_arg; + void set_pos_if_unset (octave_idx_type nd_arg, octave_idx_type dim_arg) + { + if (m_nd == 0) + { + m_nd = nd_arg; + m_dim = dim_arg; - update_message (); - } - } + update_message (); + } + } - // Name of variable being indexed. eye(2)(1,1) gives "". - void set_var (const std::string& var_arg = "") - { - m_var = var_arg; + // Name of variable being indexed. eye(2)(1,1) gives "". + void set_var (const std::string& var_arg = "") + { + m_var = var_arg; - update_message (); - } + update_message (); + } - private: +private: - // Value of invalid index. - std::string m_index; + // Value of invalid index. + std::string m_index; - protected: +protected: - // Show what's wrong, e.g., A(-1,_), A(0+1i). - OCTAVE_API std::string expression (void) const; + // Show what's wrong, e.g., A(-1,_), A(0+1i). + OCTAVE_API std::string expression (void) const; - // Number of dimensions of indexed object. - octave_idx_type m_nd; + // Number of dimensions of indexed object. + octave_idx_type m_nd; - // Dimension number in which invalid index occurred. - octave_idx_type m_dim; + // Dimension number in which invalid index occurred. + octave_idx_type m_dim; - // Name of variable being indexed. - std::string m_var; - }; + // Name of variable being indexed. + std::string m_var; +}; - OCTAVE_NORETURN extern OCTAVE_API void - err_nan_to_logical_conversion (void); +OCTAVE_NORETURN extern OCTAVE_API void +err_nan_to_logical_conversion (void); - OCTAVE_NORETURN extern OCTAVE_API void - err_nan_to_character_conversion (void); +OCTAVE_NORETURN extern OCTAVE_API void +err_nan_to_character_conversion (void); - OCTAVE_NORETURN extern OCTAVE_API void - err_nonconformant (const char *op, octave_idx_type op1_len, - octave_idx_type op2_len); +OCTAVE_NORETURN extern OCTAVE_API void +err_nonconformant (const char *op, octave_idx_type op1_len, + octave_idx_type op2_len); - OCTAVE_NORETURN extern OCTAVE_API void - err_nonconformant (const char *op, - octave_idx_type op1_nr, octave_idx_type op1_nc, - octave_idx_type op2_nr, octave_idx_type op2_nc); +OCTAVE_NORETURN extern OCTAVE_API void +err_nonconformant (const char *op, + octave_idx_type op1_nr, octave_idx_type op1_nc, + octave_idx_type op2_nr, octave_idx_type op2_nc); - OCTAVE_NORETURN extern OCTAVE_API void - err_nonconformant (const char *op, - const dim_vector& op1_dims, const dim_vector& op2_dims); +OCTAVE_NORETURN extern OCTAVE_API void +err_nonconformant (const char *op, + const dim_vector& op1_dims, const dim_vector& op2_dims); - OCTAVE_NORETURN extern OCTAVE_API void - err_index_out_of_range (int ndims, int dim, octave_idx_type idx, - octave_idx_type ext, const dim_vector& dv); +OCTAVE_NORETURN extern OCTAVE_API void +err_index_out_of_range (int ndims, int dim, octave_idx_type idx, + octave_idx_type ext, const dim_vector& dv); - OCTAVE_NORETURN extern OCTAVE_API void - err_del_index_out_of_range (bool is1d, octave_idx_type iext, - octave_idx_type ext); +OCTAVE_NORETURN extern OCTAVE_API void +err_del_index_out_of_range (bool is1d, octave_idx_type iext, + octave_idx_type ext); - OCTAVE_NORETURN extern OCTAVE_API void - err_invalid_index (double n, octave_idx_type nd = 0, - octave_idx_type dim = 0, - const std::string& var = ""); +OCTAVE_NORETURN extern OCTAVE_API void +err_invalid_index (double n, octave_idx_type nd = 0, + octave_idx_type dim = 0, + const std::string& var = ""); - OCTAVE_NORETURN extern OCTAVE_API void - err_invalid_index (octave_idx_type n, octave_idx_type nd = 0, - octave_idx_type dim = 0, - const std::string& var = ""); +OCTAVE_NORETURN extern OCTAVE_API void +err_invalid_index (octave_idx_type n, octave_idx_type nd = 0, + octave_idx_type dim = 0, + const std::string& var = ""); - OCTAVE_NORETURN extern OCTAVE_API void - err_invalid_index (const std::string& idx, octave_idx_type nd = 0, - octave_idx_type dim = 0, - const std::string& var = ""); +OCTAVE_NORETURN extern OCTAVE_API void +err_invalid_index (const std::string& idx, octave_idx_type nd = 0, + octave_idx_type dim = 0, + const std::string& var = ""); - OCTAVE_NORETURN extern OCTAVE_API void - err_invalid_resize (void); +OCTAVE_NORETURN extern OCTAVE_API void +err_invalid_resize (void); - extern OCTAVE_API void - warn_singular_matrix (double rcond = 0.0); +extern OCTAVE_API void +warn_singular_matrix (double rcond = 0.0); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-hash.cc --- a/liboctave/util/lo-hash.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-hash.cc Thu Dec 01 20:05:44 2022 -0800 @@ -41,106 +41,106 @@ OCTAVE_BEGIN_NAMESPACE(crypto) - std::string - hash (hash_fptr hash_fcn, const std::string& str, int result_buf_len) - { - OCTAVE_LOCAL_BUFFER (unsigned char, result_buf, result_buf_len); +std::string +hash (hash_fptr hash_fcn, const std::string& str, int result_buf_len) +{ + OCTAVE_LOCAL_BUFFER (unsigned char, result_buf, result_buf_len); - hash_fcn (str.data (), str.length (), result_buf); + hash_fcn (str.data (), str.length (), result_buf); - std::ostringstream buf; + std::ostringstream buf; - for (int i = 0; i < result_buf_len; i++) - buf << std::hex << std::setw (2) << std::setfill ('0') - << (result_buf[i] & 0xFF); + for (int i = 0; i < result_buf_len; i++) + buf << std::hex << std::setw (2) << std::setfill ('0') + << (result_buf[i] & 0xFF); - return buf.str (); - } + return buf.str (); +} - int md2_digest_size (void) { return octave_md2_digest_size (); } - int md4_digest_size (void) { return octave_md4_digest_size (); } - int md5_digest_size (void) { return octave_md5_digest_size (); } - int sha1_digest_size (void) { return octave_sha1_digest_size (); } - int sha224_digest_size (void) { return octave_sha224_digest_size (); } - int sha256_digest_size (void) { return octave_sha256_digest_size (); } - int sha384_digest_size (void) { return octave_sha384_digest_size (); } - int sha512_digest_size (void) { return octave_sha512_digest_size (); } +int md2_digest_size (void) { return octave_md2_digest_size (); } +int md4_digest_size (void) { return octave_md4_digest_size (); } +int md5_digest_size (void) { return octave_md5_digest_size (); } +int sha1_digest_size (void) { return octave_sha1_digest_size (); } +int sha224_digest_size (void) { return octave_sha224_digest_size (); } +int sha256_digest_size (void) { return octave_sha256_digest_size (); } +int sha384_digest_size (void) { return octave_sha384_digest_size (); } +int sha512_digest_size (void) { return octave_sha512_digest_size (); } - std::string - md2_hash (const std::string& str) - { - return hash (octave_md2_buffer_wrapper, str, md2_digest_size ()); - } +std::string +md2_hash (const std::string& str) +{ + return hash (octave_md2_buffer_wrapper, str, md2_digest_size ()); +} - std::string - md4_hash (const std::string& str) - { - return hash (octave_md4_buffer_wrapper, str, md4_digest_size ()); - } +std::string +md4_hash (const std::string& str) +{ + return hash (octave_md4_buffer_wrapper, str, md4_digest_size ()); +} - std::string - md5_hash (const std::string& str) - { - return hash (octave_md5_buffer_wrapper, str, md5_digest_size ()); - } +std::string +md5_hash (const std::string& str) +{ + return hash (octave_md5_buffer_wrapper, str, md5_digest_size ()); +} - std::string - sha1_hash (const std::string& str) - { - return hash (octave_sha1_buffer_wrapper, str, sha1_digest_size ()); - } +std::string +sha1_hash (const std::string& str) +{ + return hash (octave_sha1_buffer_wrapper, str, sha1_digest_size ()); +} - std::string - sha224_hash (const std::string& str) - { - return hash (octave_sha224_buffer_wrapper, str, sha224_digest_size ()); - } +std::string +sha224_hash (const std::string& str) +{ + return hash (octave_sha224_buffer_wrapper, str, sha224_digest_size ()); +} - std::string - sha256_hash (const std::string& str) - { - return hash (octave_sha256_buffer_wrapper, str, sha256_digest_size ()); - } +std::string +sha256_hash (const std::string& str) +{ + return hash (octave_sha256_buffer_wrapper, str, sha256_digest_size ()); +} - std::string - sha384_hash (const std::string& str) - { - return hash (octave_sha384_buffer_wrapper, str, sha384_digest_size ()); - } +std::string +sha384_hash (const std::string& str) +{ + return hash (octave_sha384_buffer_wrapper, str, sha384_digest_size ()); +} - std::string - sha512_hash (const std::string& str) - { - return hash (octave_sha512_buffer_wrapper, str, sha512_digest_size ()); - } +std::string +sha512_hash (const std::string& str) +{ + return hash (octave_sha512_buffer_wrapper, str, sha512_digest_size ()); +} - std::string - hash (const std::string& hash_type, const std::string& str) - { - std::string ht = hash_type; +std::string +hash (const std::string& hash_type, const std::string& str) +{ + std::string ht = hash_type; - std::transform (ht.begin (), ht.end (), ht.begin (), ::toupper); + std::transform (ht.begin (), ht.end (), ht.begin (), ::toupper); - if (ht == "MD2") - return md2_hash (str); - else if (ht == "MD4") - return md4_hash (str); - else if (ht == "MD5") - return md5_hash (str); - else if (ht == "SHA1") - return sha1_hash (str); - else if (ht == "SHA224") - return sha224_hash (str); - else if (ht == "SHA256") - return sha256_hash (str); - else if (ht == "SHA384") - return sha384_hash (str); - else if (ht == "SHA512") - return sha512_hash (str); - else - (*current_liboctave_error_handler) - ("hash function '%s' not supported", hash_type.c_str ()); - } + if (ht == "MD2") + return md2_hash (str); + else if (ht == "MD4") + return md4_hash (str); + else if (ht == "MD5") + return md5_hash (str); + else if (ht == "SHA1") + return sha1_hash (str); + else if (ht == "SHA224") + return sha224_hash (str); + else if (ht == "SHA256") + return sha256_hash (str); + else if (ht == "SHA384") + return sha384_hash (str); + else if (ht == "SHA512") + return sha512_hash (str); + else + (*current_liboctave_error_handler) + ("hash function '%s' not supported", hash_type.c_str ()); +} OCTAVE_END_NAMESPACE(crypto) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-hash.h --- a/liboctave/util/lo-hash.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-hash.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,31 +34,31 @@ OCTAVE_BEGIN_NAMESPACE(crypto) - typedef void * (hash_fptr) (const char *buffer, std::size_t len, void *res); +typedef void *(hash_fptr) (const char *buffer, std::size_t len, void *res); - OCTAVE_API std::string - hash (hash_fptr hash_fcn, const std::string& str, int result_buf_len); +OCTAVE_API std::string +hash (hash_fptr hash_fcn, const std::string& str, int result_buf_len); - OCTAVE_API int md2_digest_size (void); - OCTAVE_API int md4_digest_size (void); - OCTAVE_API int md5_digest_size (void); - OCTAVE_API int sha1_digest_size (void); - OCTAVE_API int sha224_digest_size (void); - OCTAVE_API int sha256_digest_size (void); - OCTAVE_API int sha384_digest_size (void); - OCTAVE_API int sha512_digest_size (void); +OCTAVE_API int md2_digest_size (void); +OCTAVE_API int md4_digest_size (void); +OCTAVE_API int md5_digest_size (void); +OCTAVE_API int sha1_digest_size (void); +OCTAVE_API int sha224_digest_size (void); +OCTAVE_API int sha256_digest_size (void); +OCTAVE_API int sha384_digest_size (void); +OCTAVE_API int sha512_digest_size (void); - OCTAVE_API std::string md2_hash (const std::string& str); - OCTAVE_API std::string md4_hash (const std::string& str); - OCTAVE_API std::string md5_hash (const std::string& str); - OCTAVE_API std::string sha1_hash (const std::string& str); - OCTAVE_API std::string sha224_hash (const std::string& str); - OCTAVE_API std::string sha256_hash (const std::string& str); - OCTAVE_API std::string sha384_hash (const std::string& str); - OCTAVE_API std::string sha512_hash (const std::string& str); +OCTAVE_API std::string md2_hash (const std::string& str); +OCTAVE_API std::string md4_hash (const std::string& str); +OCTAVE_API std::string md5_hash (const std::string& str); +OCTAVE_API std::string sha1_hash (const std::string& str); +OCTAVE_API std::string sha224_hash (const std::string& str); +OCTAVE_API std::string sha256_hash (const std::string& str); +OCTAVE_API std::string sha384_hash (const std::string& str); +OCTAVE_API std::string sha512_hash (const std::string& str); - OCTAVE_API std::string - hash (const std::string& hash_type, const std::string& str); +OCTAVE_API std::string +hash (const std::string& hash_type, const std::string& str); OCTAVE_END_NAMESPACE(crypto) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-ieee.h --- a/liboctave/util/lo-ieee.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-ieee.h Thu Dec 01 20:05:44 2022 -0800 @@ -125,32 +125,32 @@ OCTAVE_BEGIN_NAMESPACE(octave) - template - struct numeric_limits - { - public: - static T NA (void) { return static_cast (0); } - static T NaN (void) { return static_cast (0); } - static T Inf (void) { return static_cast (0); } - }; +template +struct numeric_limits +{ +public: + static T NA (void) { return static_cast (0); } + static T NaN (void) { return static_cast (0); } + static T Inf (void) { return static_cast (0); } +}; - template <> - struct numeric_limits - { - public: - static double NA (void) { return octave_NA; } - static double NaN (void) { return octave_NaN; } - static double Inf (void) { return octave_Inf; } - }; +template <> +struct numeric_limits +{ +public: + static double NA (void) { return octave_NA; } + static double NaN (void) { return octave_NaN; } + static double Inf (void) { return octave_Inf; } +}; - template <> - struct numeric_limits - { - public: - static float NA (void) { return octave_Float_NA; } - static float NaN (void) { return octave_Float_NaN; } - static float Inf (void) { return octave_Float_Inf; } - }; +template <> +struct numeric_limits +{ +public: + static float NA (void) { return octave_Float_NA; } + static float NaN (void) { return octave_Float_NaN; } + static float Inf (void) { return octave_Float_Inf; } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-regexp.cc --- a/liboctave/util/lo-regexp.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-regexp.cc Thu Dec 01 20:05:44 2022 -0800 @@ -99,682 +99,682 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Define the maximum number of retries for a pattern - // that possibly results in an infinite recursion. +// Define the maximum number of retries for a pattern +// that possibly results in an infinite recursion. #define PCRE_MATCHLIMIT_MAX 10 - // FIXME: should this be configurable? +// FIXME: should this be configurable? #define MAXLOOKBEHIND 10 - static bool lookbehind_warned = false; +static bool lookbehind_warned = false; - // FIXME: don't bother collecting and composing return values - // the user doesn't want. +// FIXME: don't bother collecting and composing return values +// the user doesn't want. - void - regexp::free (void) - { - octave_pcre_code_free (static_cast (m_code)); - } +void +regexp::free (void) +{ + octave_pcre_code_free (static_cast (m_code)); +} - void - regexp::compile_internal (void) - { - // If we had a previously compiled pattern, release it. - free (); +void +regexp::compile_internal (void) +{ + // If we had a previously compiled pattern, release it. + free (); - std::size_t max_length = MAXLOOKBEHIND; + std::size_t max_length = MAXLOOKBEHIND; - std::size_t pos = 0; - std::size_t new_pos; - int inames = 0; - std::ostringstream buf; + std::size_t pos = 0; + std::size_t new_pos; + int inames = 0; + std::ostringstream buf; - while ((new_pos = m_pattern.find ("(?", pos)) != std::string::npos) - { - std::size_t tmp_pos; - if (m_pattern.size () > new_pos + 2 - && m_pattern.at (new_pos + 2) == '<' - && ! (m_pattern.size () > new_pos + 3 - && (m_pattern.at (new_pos + 3) == '=' - || m_pattern.at (new_pos + 3) == '!')) - && (tmp_pos = m_pattern.find_first_of ('>', new_pos)) - != std::string::npos - && m_pattern.find_first_of (')', tmp_pos) != std::string::npos) - { - // The syntax of named tokens in pcre is "(?P...)" while - // we need a syntax "(?...)", so fix that here. Also an - // expression like - // "(?\w+)\s+(?\w+)|(?\w+),\s+(?\w+)" - // should be perfectly legal, while pcre does not allow the same - // named token name on both sides of the alternative. Also fix - // that here by replacing name tokens by dummy names, and dealing - // with the dummy names later. + while ((new_pos = m_pattern.find ("(?", pos)) != std::string::npos) + { + std::size_t tmp_pos; + if (m_pattern.size () > new_pos + 2 + && m_pattern.at (new_pos + 2) == '<' + && ! (m_pattern.size () > new_pos + 3 + && (m_pattern.at (new_pos + 3) == '=' + || m_pattern.at (new_pos + 3) == '!')) + && (tmp_pos = m_pattern.find_first_of ('>', new_pos)) + != std::string::npos + && m_pattern.find_first_of (')', tmp_pos) != std::string::npos) + { + // The syntax of named tokens in pcre is "(?P...)" while + // we need a syntax "(?...)", so fix that here. Also an + // expression like + // "(?\w+)\s+(?\w+)|(?\w+),\s+(?\w+)" + // should be perfectly legal, while pcre does not allow the same + // named token name on both sides of the alternative. Also fix + // that here by replacing name tokens by dummy names, and dealing + // with the dummy names later. - std::string tmp_name - = m_pattern.substr (new_pos+3, tmp_pos-new_pos-3); + std::string tmp_name + = m_pattern.substr (new_pos+3, tmp_pos-new_pos-3); - bool found = false; + bool found = false; - for (int i = 0; i < m_names; i++) - { - if (m_named_pats(i) == tmp_name) - { - m_named_idx.resize (dim_vector (inames+1, 1)); - m_named_idx(inames) = i; - found = true; - break; - } - } + for (int i = 0; i < m_names; i++) + { + if (m_named_pats(i) == tmp_name) + { + m_named_idx.resize (dim_vector (inames+1, 1)); + m_named_idx(inames) = i; + found = true; + break; + } + } - if (! found) - { - m_named_idx.resize (dim_vector (inames+1, 1)); - m_named_idx(inames) = m_names; - m_named_pats.append (tmp_name); - m_names++; - } + if (! found) + { + m_named_idx.resize (dim_vector (inames+1, 1)); + m_named_idx(inames) = m_names; + m_named_pats.append (tmp_name); + m_names++; + } - if (new_pos - pos > 0) - buf << m_pattern.substr (pos, new_pos-pos); - if (inames < 10) - buf << "(?P 0) + buf << m_pattern.substr (pos, new_pos-pos); + if (inames < 10) + buf << "(?P new_pos + 2 - && m_pattern.at (new_pos + 2) == '<') - { - // Find lookbehind operators of arbitrary length (ie like - // "(?<=[a-z]*)") and replace with a maximum length operator - // as PCRE can not yet handle arbitrary length lookahead - // operators. Use the string length as the maximum length to - // avoid issues. + pos = tmp_pos; + } + else if (m_pattern.size () > new_pos + 2 + && m_pattern.at (new_pos + 2) == '<') + { + // Find lookbehind operators of arbitrary length (ie like + // "(?<=[a-z]*)") and replace with a maximum length operator + // as PCRE can not yet handle arbitrary length lookahead + // operators. Use the string length as the maximum length to + // avoid issues. - int brackets = 1; - std::size_t tmp_pos1 = new_pos + 2; - std::size_t tmp_pos2 = tmp_pos1; + int brackets = 1; + std::size_t tmp_pos1 = new_pos + 2; + std::size_t tmp_pos2 = tmp_pos1; - while (tmp_pos1 < m_pattern.length () && brackets > 0) - { - char ch = m_pattern.at (tmp_pos1); + while (tmp_pos1 < m_pattern.length () && brackets > 0) + { + char ch = m_pattern.at (tmp_pos1); - if (ch == '(') - brackets++; - else if (ch == ')') - { - if (brackets > 1) - tmp_pos2 = tmp_pos1; + if (ch == '(') + brackets++; + else if (ch == ')') + { + if (brackets > 1) + tmp_pos2 = tmp_pos1; - brackets--; - } + brackets--; + } - tmp_pos1++; - } + tmp_pos1++; + } - if (brackets != 0) - { - buf << m_pattern.substr (pos, new_pos - pos) << "(?"; - pos = new_pos + 2; - } - else - { - std::size_t tmp_pos3 = m_pattern.find_first_of ("*+", tmp_pos2); + if (brackets != 0) + { + buf << m_pattern.substr (pos, new_pos - pos) << "(?"; + pos = new_pos + 2; + } + else + { + std::size_t tmp_pos3 = m_pattern.find_first_of ("*+", tmp_pos2); - if (tmp_pos3 != std::string::npos && tmp_pos3 < tmp_pos1) - { - if (! lookbehind_warned) - { - lookbehind_warned = true; - (*current_liboctave_warning_with_id_handler) - ("Octave:regexp-lookbehind-limit", - "%s: arbitrary length lookbehind patterns are only supported up to length %d", - m_who.c_str (), MAXLOOKBEHIND); - } + if (tmp_pos3 != std::string::npos && tmp_pos3 < tmp_pos1) + { + if (! lookbehind_warned) + { + lookbehind_warned = true; + (*current_liboctave_warning_with_id_handler) + ("Octave:regexp-lookbehind-limit", + "%s: arbitrary length lookbehind patterns are only supported up to length %d", + m_who.c_str (), MAXLOOKBEHIND); + } - buf << m_pattern.substr (pos, new_pos - pos) << '('; + buf << m_pattern.substr (pos, new_pos - pos) << '('; - std::size_t i; + std::size_t i; - if (m_pattern.at (tmp_pos3) == '*') - i = 0; - else - i = 1; + if (m_pattern.at (tmp_pos3) == '*') + i = 0; + else + i = 1; - for (; i < max_length + 1; i++) - { - buf << m_pattern.substr (new_pos, tmp_pos3 - new_pos) - << '{' << i << '}'; - buf << m_pattern.substr (tmp_pos3 + 1, - tmp_pos1 - tmp_pos3 - 1); - if (i != max_length) - buf << '|'; - } - buf << ')'; - } - else - buf << m_pattern.substr (pos, tmp_pos1 - pos); + for (; i < max_length + 1; i++) + { + buf << m_pattern.substr (new_pos, tmp_pos3 - new_pos) + << '{' << i << '}'; + buf << m_pattern.substr (tmp_pos3 + 1, + tmp_pos1 - tmp_pos3 - 1); + if (i != max_length) + buf << '|'; + } + buf << ')'; + } + else + buf << m_pattern.substr (pos, tmp_pos1 - pos); - pos = tmp_pos1; - } - } - else - { - buf << m_pattern.substr (pos, new_pos - pos) << "(?"; - pos = new_pos + 2; - } + pos = tmp_pos1; + } + } + else + { + buf << m_pattern.substr (pos, new_pos - pos) << "(?"; + pos = new_pos + 2; + } - } + } - buf << m_pattern.substr (pos); + buf << m_pattern.substr (pos); - // Replace NULLs with escape sequence because conversion function c_str() - // will terminate string early at embedded NULLs. - std::string buf_str = buf.str (); - while ((pos = buf_str.find ('\0')) != std::string::npos) - buf_str.replace (pos, 1, "\\000"); + // Replace NULLs with escape sequence because conversion function c_str() + // will terminate string early at embedded NULLs. + std::string buf_str = buf.str (); + while ((pos = buf_str.find ('\0')) != std::string::npos) + buf_str.replace (pos, 1, "\\000"); - int pcre_options - = ( (m_options.case_insensitive () ? OCTAVE_PCRE_CASELESS : 0) + int pcre_options + = ( (m_options.case_insensitive () ? OCTAVE_PCRE_CASELESS : 0) | (m_options.dotexceptnewline () ? 0 : OCTAVE_PCRE_DOTALL) | (m_options.lineanchors () ? OCTAVE_PCRE_MULTILINE : 0) | (m_options.freespacing () ? OCTAVE_PCRE_EXTENDED : 0) | OCTAVE_PCRE_UTF); #if defined (HAVE_PCRE2) - PCRE2_SIZE erroffset; - int errnumber; + PCRE2_SIZE erroffset; + int errnumber; - m_code = pcre2_compile (reinterpret_cast (buf_str.c_str ()), - PCRE2_ZERO_TERMINATED, pcre_options, - &errnumber, &erroffset, nullptr); + m_code = pcre2_compile (reinterpret_cast (buf_str.c_str ()), + PCRE2_ZERO_TERMINATED, pcre_options, + &errnumber, &erroffset, nullptr); - if (! m_code) - { - // PCRE docs say: - // - // If the buffer is too small, the message is truncated (but - // still with a trailing zero), and the negative error code - // PCRE2_ERROR_NOMEMORY is returned. None of the messages are - // very long; a buffer size of 120 code units is ample. - // - // so we assume that 256 will be large enough to avoid truncated - // messages. + if (! m_code) + { + // PCRE docs say: + // + // If the buffer is too small, the message is truncated (but + // still with a trailing zero), and the negative error code + // PCRE2_ERROR_NOMEMORY is returned. None of the messages are + // very long; a buffer size of 120 code units is ample. + // + // so we assume that 256 will be large enough to avoid truncated + // messages. - PCRE2_UCHAR err [256]; - pcre2_get_error_message (errnumber, err, sizeof (err)); - (*current_liboctave_error_handler) - ("%s: %s at position %zu of expression", m_who.c_str (), err, - erroffset); - } + PCRE2_UCHAR err [256]; + pcre2_get_error_message (errnumber, err, sizeof (err)); + (*current_liboctave_error_handler) + ("%s: %s at position %zu of expression", m_who.c_str (), err, + erroffset); + } #else - const char *err; - int erroffset; + const char *err; + int erroffset; - m_code = pcre_compile (buf_str.c_str (), pcre_options, - &err, &erroffset, nullptr); + m_code = pcre_compile (buf_str.c_str (), pcre_options, + &err, &erroffset, nullptr); - if (! m_code) - (*current_liboctave_error_handler) - ("%s: %s at position %d of expression", m_who.c_str (), err, erroffset); + if (! m_code) + (*current_liboctave_error_handler) + ("%s: %s at position %d of expression", m_who.c_str (), err, erroffset); #endif - } +} - regexp::match_data - regexp::match (const std::string& buffer) const - { - // check if input is valid utf-8 - const uint8_t *buf_str = reinterpret_cast (buffer.c_str ()); - if (octave_u8_check_wrapper (buf_str, buffer.length ())) - (*current_liboctave_error_handler) - ("%s: the input string is invalid UTF-8", m_who.c_str ()); +regexp::match_data +regexp::match (const std::string& buffer) const +{ + // check if input is valid utf-8 + const uint8_t *buf_str = reinterpret_cast (buffer.c_str ()); + if (octave_u8_check_wrapper (buf_str, buffer.length ())) + (*current_liboctave_error_handler) + ("%s: the input string is invalid UTF-8", m_who.c_str ()); - regexp::match_data retval; + regexp::match_data retval; - std::list lst; + std::list lst; - int subpatterns; - int namecount; - int nameentrysize; - char *nametable; - std::size_t idx = 0; + int subpatterns; + int namecount; + int nameentrysize; + char *nametable; + std::size_t idx = 0; - octave_pcre_code *re = static_cast (m_code); + octave_pcre_code *re = static_cast (m_code); - octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_CAPTURECOUNT, &subpatterns); - octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMECOUNT, &namecount); - octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMEENTRYSIZE, &nameentrysize); - octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMETABLE, &nametable); + octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_CAPTURECOUNT, &subpatterns); + octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMECOUNT, &namecount); + octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMEENTRYSIZE, &nameentrysize); + octave_pcre_pattern_info (re, OCTAVE_PCRE_INFO_NAMETABLE, &nametable); #if defined (HAVE_PCRE) - OCTAVE_LOCAL_BUFFER (OCTAVE_PCRE_SIZE, ovector, (subpatterns+1)*3); + OCTAVE_LOCAL_BUFFER (OCTAVE_PCRE_SIZE, ovector, (subpatterns+1)*3); #endif - OCTAVE_LOCAL_BUFFER (int, nidx, namecount); + OCTAVE_LOCAL_BUFFER (int, nidx, namecount); - for (int i = 0; i < namecount; i++) - { - // Index of subpattern in first two bytes of name (MSB first). - // Extract index. - nidx[i] = (static_cast (nametable[i*nameentrysize])) << 8 - | static_cast (nametable[i*nameentrysize+1]); - } + for (int i = 0; i < namecount; i++) + { + // Index of subpattern in first two bytes of name (MSB first). + // Extract index. + nidx[i] = (static_cast (nametable[i*nameentrysize])) << 8 + | static_cast (nametable[i*nameentrysize+1]); + } - while (true) - { - octave_quit (); + while (true) + { + octave_quit (); #if defined (HAVE_PCRE2) - pcre2_match_data *m_data - = pcre2_match_data_create_from_pattern (re, nullptr); - - unwind_action cleanup_match_data - ([=] () { pcre2_match_data_free (m_data); }); - - int matches = pcre2_match (re, reinterpret_cast (buffer.c_str ()), - buffer.length (), idx, - PCRE2_NO_UTF_CHECK | (idx ? PCRE2_NOTBOL : 0), - m_data, nullptr); + pcre2_match_data *m_data + = pcre2_match_data_create_from_pattern (re, nullptr); - if (matches < 0 && matches != PCRE2_ERROR_NOMATCH) - (*current_liboctave_error_handler) - ("%s: internal error calling pcre2_match; " - "error code from pcre2_match is %i", m_who.c_str (), matches); + unwind_action cleanup_match_data + ([=] () { pcre2_match_data_free (m_data); }); - if (matches == PCRE2_ERROR_NOMATCH) - break; - - OCTAVE_PCRE_SIZE *ovector = pcre2_get_ovector_pointer (m_data); -#else - int matches = pcre_exec (re, nullptr, buffer.c_str (), + int matches = pcre2_match (re, reinterpret_cast (buffer.c_str ()), buffer.length (), idx, - PCRE_NO_UTF8_CHECK | (idx ? PCRE_NOTBOL : 0), - ovector, (subpatterns+1)*3); + PCRE2_NO_UTF_CHECK | (idx ? PCRE2_NOTBOL : 0), + m_data, nullptr); + + if (matches < 0 && matches != PCRE2_ERROR_NOMATCH) + (*current_liboctave_error_handler) + ("%s: internal error calling pcre2_match; " + "error code from pcre2_match is %i", m_who.c_str (), matches); - if (matches == PCRE_ERROR_MATCHLIMIT) - { - // Try harder; start with default value for MATCH_LIMIT - // and increase it. - (*current_liboctave_warning_with_id_handler) - ("Octave:regexp-match-limit", - "your pattern caused PCRE to hit its MATCH_LIMIT; trying harder now, but this will be slow"); + if (matches == PCRE2_ERROR_NOMATCH) + break; + + OCTAVE_PCRE_SIZE *ovector = pcre2_get_ovector_pointer (m_data); +#else + int matches = pcre_exec (re, nullptr, buffer.c_str (), + buffer.length (), idx, + PCRE_NO_UTF8_CHECK | (idx ? PCRE_NOTBOL : 0), + ovector, (subpatterns+1)*3); - pcre_extra pe; + if (matches == PCRE_ERROR_MATCHLIMIT) + { + // Try harder; start with default value for MATCH_LIMIT + // and increase it. + (*current_liboctave_warning_with_id_handler) + ("Octave:regexp-match-limit", + "your pattern caused PCRE to hit its MATCH_LIMIT; trying harder now, but this will be slow"); - pcre_config (PCRE_CONFIG_MATCH_LIMIT, - static_cast (&pe.match_limit)); + pcre_extra pe; - pe.flags = PCRE_EXTRA_MATCH_LIMIT; + pcre_config (PCRE_CONFIG_MATCH_LIMIT, + static_cast (&pe.match_limit)); + + pe.flags = PCRE_EXTRA_MATCH_LIMIT; - int i = 0; - while (matches == PCRE_ERROR_MATCHLIMIT - && i++ < PCRE_MATCHLIMIT_MAX) - { - octave_quit (); + int i = 0; + while (matches == PCRE_ERROR_MATCHLIMIT + && i++ < PCRE_MATCHLIMIT_MAX) + { + octave_quit (); - pe.match_limit *= 10; - matches = pcre_exec (re, &pe, buffer.c_str (), - buffer.length (), idx, - PCRE_NO_UTF8_CHECK - | (idx ? PCRE_NOTBOL : 0), - ovector, (subpatterns+1)*3); - } - } + pe.match_limit *= 10; + matches = pcre_exec (re, &pe, buffer.c_str (), + buffer.length (), idx, + PCRE_NO_UTF8_CHECK + | (idx ? PCRE_NOTBOL : 0), + ovector, (subpatterns+1)*3); + } + } - if (matches < 0 && matches != PCRE_ERROR_NOMATCH) - (*current_liboctave_error_handler) - ("%s: internal error calling pcre_exec; " - "error code from pcre_exec is %i", m_who.c_str (), matches); + if (matches < 0 && matches != PCRE_ERROR_NOMATCH) + (*current_liboctave_error_handler) + ("%s: internal error calling pcre_exec; " + "error code from pcre_exec is %i", m_who.c_str (), matches); - if (matches == PCRE_ERROR_NOMATCH) - break; + if (matches == PCRE_ERROR_NOMATCH) + break; #endif - if (ovector[0] >= ovector[1] && ! m_options.emptymatch ()) - { - // Zero length match. Skip to next char. - idx = ovector[0] + 1; - if (idx < buffer.length ()) - continue; - else - break; - } - else - { - int pos_match = 0; - Matrix token_extents (matches-1, 2); + if (ovector[0] >= ovector[1] && ! m_options.emptymatch ()) + { + // Zero length match. Skip to next char. + idx = ovector[0] + 1; + if (idx < buffer.length ()) + continue; + else + break; + } + else + { + int pos_match = 0; + Matrix token_extents (matches-1, 2); - for (int i = 1; i < matches; i++) - { + for (int i = 1; i < matches; i++) + { #if defined (HAVE_PCRE2) - if (ovector[2*i] != PCRE2_SIZE_MAX + if (ovector[2*i] != PCRE2_SIZE_MAX #else - if (ovector[2*i] >= 0 + if (ovector[2*i] >= 0 #endif - && ovector[2*i+1] > 0 - && (i == 1 || ovector[2*i] != ovector[2*i-2] - || ovector[2*i-1] != ovector[2*i+1])) - { - token_extents(pos_match, 0) = double (ovector[2*i]+1); - token_extents(pos_match++, 1) = double (ovector[2*i+1]); - } - } + && ovector[2*i+1] > 0 + && (i == 1 || ovector[2*i] != ovector[2*i-2] + || ovector[2*i-1] != ovector[2*i+1])) + { + token_extents(pos_match, 0) = double (ovector[2*i]+1); + token_extents(pos_match++, 1) = double (ovector[2*i+1]); + } + } - token_extents.resize (pos_match, 2); + token_extents.resize (pos_match, 2); - OCTAVE_PCRE_SIZE start = ovector[0] + 1; - OCTAVE_PCRE_SIZE end = ovector[1]; + OCTAVE_PCRE_SIZE start = ovector[0] + 1; + OCTAVE_PCRE_SIZE end = ovector[1]; #if defined (HAVE_PCRE2) - // Must use explicit length constructor as match can contain '\0'. - std::string match_string = std::string (buffer.c_str() + start - 1, - end - start + 1); + // Must use explicit length constructor as match can contain '\0'. + std::string match_string = std::string (buffer.c_str() + start - 1, + end - start + 1); #else - const char **listptr; - int status = pcre_get_substring_list (buffer.c_str (), ovector, - matches, &listptr); + const char **listptr; + int status = pcre_get_substring_list (buffer.c_str (), ovector, + matches, &listptr); - if (status == PCRE_ERROR_NOMEMORY) - (*current_liboctave_error_handler) - ("%s: cannot allocate memory in pcre_get_substring_list", - m_who.c_str ()); + if (status == PCRE_ERROR_NOMEMORY) + (*current_liboctave_error_handler) + ("%s: cannot allocate memory in pcre_get_substring_list", + m_who.c_str ()); - // Must use explicit length constructor as match can contain '\0'. - std::string match_string = std::string (*listptr, end - start + 1); + // Must use explicit length constructor as match can contain '\0'. + std::string match_string = std::string (*listptr, end - start + 1); #endif - string_vector tokens (pos_match); - string_vector named_tokens (m_names); - int pos_offset = 0; - pos_match = 0; + string_vector tokens (pos_match); + string_vector named_tokens (m_names); + int pos_offset = 0; + pos_match = 0; - for (int i = 1; i < matches; i++) - { + for (int i = 1; i < matches; i++) + { #if defined (HAVE_PCRE2) - if (ovector[2*i] != PCRE2_SIZE_MAX + if (ovector[2*i] != PCRE2_SIZE_MAX #else - if (ovector[2*i] >= 0 + if (ovector[2*i] >= 0 #endif - && ovector[2*i+1] > 0) - { - if (i == 1 || ovector[2*i] != ovector[2*i-2] - || ovector[2*i-1] != ovector[2*i+1]) - { - if (namecount > 0) - { - // FIXME: Should probably do this with a map() - // rather than a linear search. However, - // the number of captured, named expressions - // is usually pretty small (< 4) - for (int j = 0; j < namecount; j++) - { - if (nidx[j] == i) - { - std::size_t len = ovector[2*i+1] - ovector[2*i]; - named_tokens(m_named_idx(j)) + && ovector[2*i+1] > 0) + { + if (i == 1 || ovector[2*i] != ovector[2*i-2] + || ovector[2*i-1] != ovector[2*i+1]) + { + if (namecount > 0) + { + // FIXME: Should probably do this with a map() + // rather than a linear search. However, + // the number of captured, named expressions + // is usually pretty small (< 4) + for (int j = 0; j < namecount; j++) + { + if (nidx[j] == i) + { + std::size_t len = ovector[2*i+1] - ovector[2*i]; + named_tokens(m_named_idx(j)) #if defined (HAVE_PCRE2) - = std::string (buffer.c_str () + ovector[2*i], len); + = std::string (buffer.c_str () + ovector[2*i], len); #else - = std::string (*(listptr+i-pos_offset), len); + = std::string (*(listptr+i-pos_offset), len); #endif - break; - } - } - } + break; + } + } + } - std::size_t len = ovector[2*i+1] - ovector[2*i]; + std::size_t len = ovector[2*i+1] - ovector[2*i]; #if defined (HAVE_PCRE2) - tokens(pos_match++) = std::string (buffer.c_str() + ovector[2*i], len); + tokens(pos_match++) = std::string (buffer.c_str() + ovector[2*i], len); #else - tokens(pos_match++) = std::string (*(listptr+i), len); + tokens(pos_match++) = std::string (*(listptr+i), len); #endif - } - else - pos_offset++; - } - } + } + else + pos_offset++; + } + } #if ! defined (HAVE_PCRE2) - pcre_free_substring_list (listptr); + pcre_free_substring_list (listptr); #endif - // FIXME: MATCH_ELEMENT uses double values for these, - // presumably because that is what the Octave interpreter - // uses. Should we check that the values don't exceed - // flintmax here? It seems unlikely that it would happen, - // but... + // FIXME: MATCH_ELEMENT uses double values for these, + // presumably because that is what the Octave interpreter + // uses. Should we check that the values don't exceed + // flintmax here? It seems unlikely that it would happen, + // but... - double dstart = static_cast (start); - double dend = static_cast (end); + double dstart = static_cast (start); + double dend = static_cast (end); - regexp::match_element new_elem (named_tokens, tokens, match_string, - token_extents, - dstart, dend); + regexp::match_element new_elem (named_tokens, tokens, match_string, + token_extents, + dstart, dend); - lst.push_back (new_elem); + lst.push_back (new_elem); - if (ovector[1] <= ovector[0]) - { - // Zero length match. Skip to next char. - idx = ovector[0] + 1; - if (idx <= buffer.length ()) - continue; - } - else - idx = ovector[1]; + if (ovector[1] <= ovector[0]) + { + // Zero length match. Skip to next char. + idx = ovector[0] + 1; + if (idx <= buffer.length ()) + continue; + } + else + idx = ovector[1]; - if (m_options.once () || idx >= buffer.length ()) - break; - } - } + if (m_options.once () || idx >= buffer.length ()) + break; + } + } - retval = regexp::match_data (lst, m_named_pats); + retval = regexp::match_data (lst, m_named_pats); - return retval; - } + return retval; +} - bool - regexp::is_match (const std::string& buffer) const - { - regexp::match_data rx_lst = match (buffer); +bool +regexp::is_match (const std::string& buffer) const +{ + regexp::match_data rx_lst = match (buffer); - return rx_lst.size () > 0; - } + return rx_lst.size () > 0; +} - Array - regexp::is_match (const string_vector& buffer) const - { - octave_idx_type len = buffer.numel (); +Array +regexp::is_match (const string_vector& buffer) const +{ + octave_idx_type len = buffer.numel (); - Array retval (dim_vector (len, 1)); + Array retval (dim_vector (len, 1)); - for (octave_idx_type i = 0; i < buffer.numel (); i++) - retval(i) = is_match (buffer(i)); + for (octave_idx_type i = 0; i < buffer.numel (); i++) + retval(i) = is_match (buffer(i)); - return retval; - } + return retval; +} - // Declare rep_token_t used in processing replacement string - struct rep_token_t - { - std::size_t pos; - int num; - }; +// Declare rep_token_t used in processing replacement string +struct rep_token_t +{ + std::size_t pos; + int num; +}; - std::string - regexp::replace (const std::string& buffer, - const std::string& replacement) const - { - std::string retval; +std::string +regexp::replace (const std::string& buffer, + const std::string& replacement) const +{ + std::string retval; - const regexp::match_data rx_lst = match (buffer); + const regexp::match_data rx_lst = match (buffer); - std::size_t num_matches = rx_lst.size (); + std::size_t num_matches = rx_lst.size (); - if (num_matches == 0) - { - retval = buffer; - return retval; - } + if (num_matches == 0) + { + retval = buffer; + return retval; + } - // Identify replacement tokens; build a vector of group numbers in - // the replacement string so that we can quickly calculate the size - // of the replacement. + // Identify replacement tokens; build a vector of group numbers in + // the replacement string so that we can quickly calculate the size + // of the replacement. - // FIXME: All code assumes that only 10 tokens ($0-$9) exist. - // $11 represents $1 followed by the character '1' rather than - // the eleventh capture buffer. + // FIXME: All code assumes that only 10 tokens ($0-$9) exist. + // $11 represents $1 followed by the character '1' rather than + // the eleventh capture buffer. - std::string repstr = replacement; - std::vector tokens; - tokens.reserve (5); // Reserve memory for 5 pattern replacements + std::string repstr = replacement; + std::vector tokens; + tokens.reserve (5); // Reserve memory for 5 pattern replacements - for (std::size_t i=0; i < repstr.size (); i++) - { - if (repstr[i] == '\\') - { - if (i < repstr.size () - 1 && repstr[i+1] == '$') - { - repstr.erase (i, 1); // erase backslash - i++; // skip over '$' - continue; - } - if (i < repstr.size () - 1 && repstr[i+1] == '\\') - { - repstr.erase (i, 1); // erase 1st backslash - continue; - } - } - else if (repstr[i] == '$') - { - if (i < repstr.size () - 1 && isdigit (repstr[i+1])) - { - rep_token_t tmp_token; + for (std::size_t i=0; i < repstr.size (); i++) + { + if (repstr[i] == '\\') + { + if (i < repstr.size () - 1 && repstr[i+1] == '$') + { + repstr.erase (i, 1); // erase backslash + i++; // skip over '$' + continue; + } + if (i < repstr.size () - 1 && repstr[i+1] == '\\') + { + repstr.erase (i, 1); // erase 1st backslash + continue; + } + } + else if (repstr[i] == '$') + { + if (i < repstr.size () - 1 && isdigit (repstr[i+1])) + { + rep_token_t tmp_token; - tmp_token.pos = i; - tmp_token.num = repstr[i+1]-'0'; - tokens.push_back (tmp_token); - } - } - } + tmp_token.pos = i; + tmp_token.num = repstr[i+1]-'0'; + tokens.push_back (tmp_token); + } + } + } - std::string rep; - int num_tokens = tokens.size (); + std::string rep; + int num_tokens = tokens.size (); - if (num_tokens > 0) - { - // Determine replacement length - const std::size_t replen = repstr.size () - 2*num_tokens; - int delta = 0; - auto p = rx_lst.begin (); - for (std::size_t i = 0; i < num_matches; i++) - { - octave_quit (); + if (num_tokens > 0) + { + // Determine replacement length + const std::size_t replen = repstr.size () - 2*num_tokens; + int delta = 0; + auto p = rx_lst.begin (); + for (std::size_t i = 0; i < num_matches; i++) + { + octave_quit (); - double start = p->start (); - double end = p->end (); + double start = p->start (); + double end = p->end (); - const Matrix pairs (p->token_extents ()); - std::size_t pairlen = 0; - for (int j = 0; j < num_tokens; j++) - { - if (tokens[j].num == 0) - pairlen += static_cast (end - start + 1); - else if (tokens[j].num <= pairs.rows ()) - pairlen += static_cast (pairs(tokens[j].num-1,1) - - pairs(tokens[j].num-1,0) - + 1); - } - delta += (static_cast (replen + pairlen) - - static_cast (end - start + 1)); - p++; - } + const Matrix pairs (p->token_extents ()); + std::size_t pairlen = 0; + for (int j = 0; j < num_tokens; j++) + { + if (tokens[j].num == 0) + pairlen += static_cast (end - start + 1); + else if (tokens[j].num <= pairs.rows ()) + pairlen += static_cast (pairs(tokens[j].num-1, 1) + - pairs(tokens[j].num-1, 0) + + 1); + } + delta += (static_cast (replen + pairlen) + - static_cast (end - start + 1)); + p++; + } - // Build replacement string - rep.reserve (buffer.size () + delta); - std::size_t from = 0; - p = rx_lst.begin (); - for (std::size_t i = 0; i < num_matches; i++) - { - octave_quit (); + // Build replacement string + rep.reserve (buffer.size () + delta); + std::size_t from = 0; + p = rx_lst.begin (); + for (std::size_t i = 0; i < num_matches; i++) + { + octave_quit (); - double start = p->start (); - double end = p->end (); + double start = p->start (); + double end = p->end (); - const Matrix pairs (p->token_extents ()); - rep.append (&buffer[from], static_cast (start - 1 - from)); - from = static_cast (end); + const Matrix pairs (p->token_extents ()); + rep.append (&buffer[from], static_cast (start - 1 - from)); + from = static_cast (end); - std::size_t cur_pos = 0; + std::size_t cur_pos = 0; - for (int j = 0; j < num_tokens; j++) - { - rep.append (&repstr[cur_pos], (tokens[j].pos) - cur_pos); - cur_pos = tokens[j].pos+2; + for (int j = 0; j < num_tokens; j++) + { + rep.append (&repstr[cur_pos], (tokens[j].pos) - cur_pos); + cur_pos = tokens[j].pos+2; - int k = tokens[j].num; - if (k == 0) - { - // replace with entire match - rep.append (&buffer[static_cast (end - 1)], - static_cast (end - start + 1)); - } - else if (k <= pairs.rows ()) - { - // replace with group capture - rep.append (&buffer[static_cast (pairs(k-1,0)-1)], - static_cast (pairs(k-1,1) - - pairs(k-1,0) + 1)); - } - else - { - // replace with nothing - } - } - if (cur_pos < repstr.size ()) - rep.append (&repstr[cur_pos], repstr.size () - cur_pos); + int k = tokens[j].num; + if (k == 0) + { + // replace with entire match + rep.append (&buffer[static_cast (end - 1)], + static_cast (end - start + 1)); + } + else if (k <= pairs.rows ()) + { + // replace with group capture + rep.append (&buffer[static_cast (pairs(k-1, 0)-1)], + static_cast (pairs(k-1, 1) + - pairs(k-1, 0) + 1)); + } + else + { + // replace with nothing + } + } + if (cur_pos < repstr.size ()) + rep.append (&repstr[cur_pos], repstr.size () - cur_pos); - p++; - } - rep.append (&buffer[from], buffer.size () - from); - } - else - { - // Determine repstr length - const std::size_t replen = repstr.size (); - int delta = 0; - auto p = rx_lst.begin (); - for (std::size_t i = 0; i < num_matches; i++) - { - octave_quit (); + p++; + } + rep.append (&buffer[from], buffer.size () - from); + } + else + { + // Determine repstr length + const std::size_t replen = repstr.size (); + int delta = 0; + auto p = rx_lst.begin (); + for (std::size_t i = 0; i < num_matches; i++) + { + octave_quit (); - delta += static_cast (replen) - - static_cast (p->end () - p->start () + 1); - p++; - } + delta += static_cast (replen) + - static_cast (p->end () - p->start () + 1); + p++; + } - // Build replacement string - rep.reserve (buffer.size () + delta); - std::size_t from = 0; - p = rx_lst.begin (); - for (std::size_t i = 0; i < num_matches; i++) - { - octave_quit (); + // Build replacement string + rep.reserve (buffer.size () + delta); + std::size_t from = 0; + p = rx_lst.begin (); + for (std::size_t i = 0; i < num_matches; i++) + { + octave_quit (); - rep.append (&buffer[from], - static_cast (p->start () - 1 - from)); - from = static_cast (p->end ()); - rep.append (repstr); - p++; - } - rep.append (&buffer[from], buffer.size () - from); - } + rep.append (&buffer[from], + static_cast (p->start () - 1 - from)); + from = static_cast (p->end ()); + rep.append (repstr); + p++; + } + rep.append (&buffer[from], buffer.size () - from); + } - retval = rep; - return retval; - } + retval = rep; + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-regexp.h --- a/liboctave/util/lo-regexp.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-regexp.h Thu Dec 01 20:05:44 2022 -0800 @@ -39,207 +39,207 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTAVE_API - regexp +class +OCTAVE_API +regexp +{ +public: + + class opts; + class match_data; + + regexp (const std::string& pat = "", + const regexp::opts& opt = regexp::opts (), + const std::string& w = "regexp") + : m_pattern (pat), m_options (opt), m_code (nullptr), m_named_pats (), + m_names (0), m_named_idx (), m_who (w) + { + compile_internal (); + } + + regexp (const regexp&) = default; + + regexp& operator = (const regexp& rx) = default; + + ~regexp (void) { free (); } + + void compile (const std::string& pat, + const regexp::opts& opt = regexp::opts ()) + { + m_pattern = pat; + m_options = opt; + compile_internal (); + } + + match_data match (const std::string& buffer) const; + + bool is_match (const std::string& buffer) const; + + Array is_match (const string_vector& buffer) const; + + std::string replace (const std::string& buffer, + const std::string& replacement) const; + + static match_data + match (const std::string& pat, const std::string& buffer, + const regexp::opts& opt = regexp::opts (), + const std::string& who = "regexp") + { + regexp rx (pat, opt, who); + + return rx.match (buffer); + } + + static bool + is_match (const std::string& pat, const std::string& buffer, + const regexp::opts& opt = regexp::opts (), + const std::string& who = "regexp") + { + regexp rx (pat, opt, who); + + return rx.is_match (buffer); + } + + static Array + is_match (const std::string& pat, const string_vector& buffer, + const regexp::opts& opt = regexp::opts (), + const std::string& who = "regexp") + { + regexp rx (pat, opt, who); + + return rx.is_match (buffer); + } + + static std::string + replace (const std::string& pat, const std::string& buffer, + const std::string& replacement, + const regexp::opts& opt = regexp::opts (), + const std::string& who = "regexp") + { + regexp rx (pat, opt, who); + + return rx.replace (buffer, replacement); + } + + class opts { public: - class opts; - class match_data; - - regexp (const std::string& pat = "", - const regexp::opts& opt = regexp::opts (), - const std::string& w = "regexp") - : m_pattern (pat), m_options (opt), m_code (nullptr), m_named_pats (), - m_names (0), m_named_idx (), m_who (w) - { - compile_internal (); - } - - regexp (const regexp&) = default; - - regexp& operator = (const regexp& rx) = default; - - ~regexp (void) { free (); } - - void compile (const std::string& pat, - const regexp::opts& opt = regexp::opts ()) - { - m_pattern = pat; - m_options = opt; - compile_internal (); - } - - match_data match (const std::string& buffer) const; - - bool is_match (const std::string& buffer) const; - - Array is_match (const string_vector& buffer) const; - - std::string replace (const std::string& buffer, - const std::string& replacement) const; - - static match_data - match (const std::string& pat, const std::string& buffer, - const regexp::opts& opt = regexp::opts (), - const std::string& who = "regexp") - { - regexp rx (pat, opt, who); + opts (void) + : m_case_insensitive (false), m_dotexceptnewline (false), + m_emptymatch (false), m_freespacing (false), m_lineanchors (false), + m_once (false) { } - return rx.match (buffer); - } - - static bool - is_match (const std::string& pat, const std::string& buffer, - const regexp::opts& opt = regexp::opts (), - const std::string& who = "regexp") - { - regexp rx (pat, opt, who); - - return rx.is_match (buffer); - } - - static Array - is_match (const std::string& pat, const string_vector& buffer, - const regexp::opts& opt = regexp::opts (), - const std::string& who = "regexp") - { - regexp rx (pat, opt, who); + opts (const opts&) = default; - return rx.is_match (buffer); - } - - static std::string - replace (const std::string& pat, const std::string& buffer, - const std::string& replacement, - const regexp::opts& opt = regexp::opts (), - const std::string& who = "regexp") - { - regexp rx (pat, opt, who); + opts& operator = (const opts&) = default; - return rx.replace (buffer, replacement); - } - - class opts - { - public: - - opts (void) - : m_case_insensitive (false), m_dotexceptnewline (false), - m_emptymatch (false), m_freespacing (false), m_lineanchors (false), - m_once (false) { } - - opts (const opts&) = default; + ~opts (void) = default; - opts& operator = (const opts&) = default; - - ~opts (void) = default; - - void case_insensitive (bool val) { m_case_insensitive = val; } - void dotexceptnewline (bool val) { m_dotexceptnewline = val; } - void emptymatch (bool val) { m_emptymatch = val; } - void freespacing (bool val) { m_freespacing = val; } - void lineanchors (bool val) { m_lineanchors = val; } - void once (bool val) { m_once = val; } - - bool case_insensitive (void) const { return m_case_insensitive; } - bool dotexceptnewline (void) const { return m_dotexceptnewline; } - bool emptymatch (void) const { return m_emptymatch; } - bool freespacing (void) const { return m_freespacing; } - bool lineanchors (void) const { return m_lineanchors; } - bool once (void) const { return m_once; } - - private: - - bool m_case_insensitive; - bool m_dotexceptnewline; - bool m_emptymatch; - bool m_freespacing; - bool m_lineanchors; - bool m_once; - }; - - class match_element - { - public: - - match_element (const string_vector& nt, const string_vector& t, - const std::string& ms, const Matrix& te, - double s, double e) - : m_match_string (ms), m_named_tokens (nt), m_tokens (t), - m_token_extents (te), m_start (s), m_end (e) - { } - - match_element (const match_element&) = default; - - match_element& operator = (const match_element&) = default; + void case_insensitive (bool val) { m_case_insensitive = val; } + void dotexceptnewline (bool val) { m_dotexceptnewline = val; } + void emptymatch (bool val) { m_emptymatch = val; } + void freespacing (bool val) { m_freespacing = val; } + void lineanchors (bool val) { m_lineanchors = val; } + void once (bool val) { m_once = val; } - std::string match_string (void) const { return m_match_string; } - string_vector named_tokens (void) const { return m_named_tokens; } - string_vector tokens (void) const { return m_tokens; } - Matrix token_extents (void) const { return m_token_extents; } - double start (void) const { return m_start; } - double end (void) const { return m_end; } - - private: - - std::string m_match_string; - string_vector m_named_tokens; - string_vector m_tokens; - Matrix m_token_extents; - - // FIXME: Are these values declared as double because that's what - // Octave interpreter functions will store? Should they be int or - // size_t instead? - double m_start; - double m_end; - }; - - class match_data : public base_list - { - public: - - match_data (void) - : base_list (), m_named_pats () - { } - - match_data (const std::list& l, const string_vector& np) - : base_list (l), m_named_pats (np) - { } - - match_data (const match_data&) = default; - - match_data& operator = (const match_data&) = default; - - ~match_data (void) = default; - - string_vector named_patterns (void) const { return m_named_pats; } - - private: - - string_vector m_named_pats; - }; + bool case_insensitive (void) const { return m_case_insensitive; } + bool dotexceptnewline (void) const { return m_dotexceptnewline; } + bool emptymatch (void) const { return m_emptymatch; } + bool freespacing (void) const { return m_freespacing; } + bool lineanchors (void) const { return m_lineanchors; } + bool once (void) const { return m_once; } private: - // The pattern we've been asked to match. - std::string m_pattern; + bool m_case_insensitive; + bool m_dotexceptnewline; + bool m_emptymatch; + bool m_freespacing; + bool m_lineanchors; + bool m_once; + }; + + class match_element + { + public: + + match_element (const string_vector& nt, const string_vector& t, + const std::string& ms, const Matrix& te, + double s, double e) + : m_match_string (ms), m_named_tokens (nt), m_tokens (t), + m_token_extents (te), m_start (s), m_end (e) + { } + + match_element (const match_element&) = default; + + match_element& operator = (const match_element&) = default; + + std::string match_string (void) const { return m_match_string; } + string_vector named_tokens (void) const { return m_named_tokens; } + string_vector tokens (void) const { return m_tokens; } + Matrix token_extents (void) const { return m_token_extents; } + double start (void) const { return m_start; } + double end (void) const { return m_end; } + + private: - opts m_options; + std::string m_match_string; + string_vector m_named_tokens; + string_vector m_tokens; + Matrix m_token_extents; + + // FIXME: Are these values declared as double because that's what + // Octave interpreter functions will store? Should they be int or + // size_t instead? + double m_start; + double m_end; + }; + + class match_data : public base_list + { + public: - // Internal data describing the regular expression. - void *m_code; + match_data (void) + : base_list (), m_named_pats () + { } + + match_data (const std::list& l, const string_vector& np) + : base_list (l), m_named_pats (np) + { } + + match_data (const match_data&) = default; + + match_data& operator = (const match_data&) = default; + + ~match_data (void) = default; + + string_vector named_patterns (void) const { return m_named_pats; } + + private: string_vector m_named_pats; - int m_names; - Array m_named_idx; - std::string m_who; + }; + +private: + + // The pattern we've been asked to match. + std::string m_pattern; + + opts m_options; - void free (void); + // Internal data describing the regular expression. + void *m_code; - void compile_internal (void); - }; + string_vector m_named_pats; + int m_names; + Array m_named_idx; + std::string m_who; + + void free (void); + + void compile_internal (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-utils.cc diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/lo-utils.h --- a/liboctave/util/lo-utils.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/lo-utils.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,100 +38,100 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Generic any/all test functionality with arbitrary predicate. +// Generic any/all test functionality with arbitrary predicate. - template - bool - any_all_test (F fcn, const T *m, octave_idx_type len) - { - octave_idx_type i; +template +bool +any_all_test (F fcn, const T *m, octave_idx_type len) +{ + octave_idx_type i; - for (i = 0; i < len - 3; i += 4) - { - octave_quit (); + for (i = 0; i < len - 3; i += 4) + { + octave_quit (); - if (fcn (m[i]) != zero - || fcn (m[i+1]) != zero - || fcn (m[i+2]) != zero - || fcn (m[i+3]) != zero) - return ! zero; - } + if (fcn (m[i]) != zero + || fcn (m[i+1]) != zero + || fcn (m[i+2]) != zero + || fcn (m[i+3]) != zero) + return ! zero; + } - octave_quit (); + octave_quit (); - for (; i < len; i++) - if (fcn (m[i]) != zero) - return ! zero; + for (; i < len; i++) + if (fcn (m[i]) != zero) + return ! zero; - return zero; - } + return zero; +} - extern OCTAVE_API bool xis_int_or_inf_or_nan (double x); +extern OCTAVE_API bool xis_int_or_inf_or_nan (double x); - template - bool is_one_or_zero (const T& x) - { - return x == T (0) || x == T (1); - } +template +bool is_one_or_zero (const T& x) +{ + return x == T (0) || x == T (1); +} - template - bool is_zero (const T& x) - { - return x == T (0); - } +template +bool is_zero (const T& x) +{ + return x == T (0); +} - extern OCTAVE_API bool too_large_for_float (double x); +extern OCTAVE_API bool too_large_for_float (double x); - extern OCTAVE_API bool too_large_for_float (const Complex& x); +extern OCTAVE_API bool too_large_for_float (const Complex& x); - extern OCTAVE_API bool is_int_or_inf_or_nan (float x); - extern OCTAVE_API bool too_large_for_float (float x); +extern OCTAVE_API bool is_int_or_inf_or_nan (float x); +extern OCTAVE_API bool too_large_for_float (float x); - extern OCTAVE_API char * strsave (const char *); +extern OCTAVE_API char * strsave (const char *); - extern OCTAVE_API std::string fgets (std::FILE *); - extern OCTAVE_API std::string fgetl (std::FILE *); +extern OCTAVE_API std::string fgets (std::FILE *); +extern OCTAVE_API std::string fgetl (std::FILE *); - extern OCTAVE_API std::string fgets (std::FILE *, bool& eof); - extern OCTAVE_API std::string fgetl (std::FILE *, bool& eof); +extern OCTAVE_API std::string fgets (std::FILE *, bool& eof); +extern OCTAVE_API std::string fgetl (std::FILE *, bool& eof); - template OCTAVE_API T read_value (std::istream& is); +template OCTAVE_API T read_value (std::istream& is); - template <> OCTAVE_API double read_value (std::istream& is); - template <> OCTAVE_API Complex read_value (std::istream& is); - template <> OCTAVE_API float read_value (std::istream& is); - template <> OCTAVE_API FloatComplex read_value (std::istream& is); +template <> OCTAVE_API double read_value (std::istream& is); +template <> OCTAVE_API Complex read_value (std::istream& is); +template <> OCTAVE_API float read_value (std::istream& is); +template <> OCTAVE_API FloatComplex read_value (std::istream& is); - template OCTAVE_API void write_value (std::ostream& os, const T& value); +template OCTAVE_API void write_value (std::ostream& os, const T& value); - template <> OCTAVE_API void write_value (std::ostream& os, const double& value); - template <> OCTAVE_API void write_value (std::ostream& os, const Complex& value); - template <> OCTAVE_API void write_value (std::ostream& os, const float& value); - template <> OCTAVE_API void write_value (std::ostream& os, const FloatComplex& value); +template <> OCTAVE_API void write_value (std::ostream& os, const double& value); +template <> OCTAVE_API void write_value (std::ostream& os, const Complex& value); +template <> OCTAVE_API void write_value (std::ostream& os, const float& value); +template <> OCTAVE_API void write_value (std::ostream& os, const FloatComplex& value); OCTAVE_BEGIN_NAMESPACE(math) - extern OCTAVE_API bool int_multiply_overflow (int a, int b, int *r); +extern OCTAVE_API bool int_multiply_overflow (int a, int b, int *r); - extern OCTAVE_API bool - int_multiply_overflow (long int a, long int b, long int *r); +extern OCTAVE_API bool +int_multiply_overflow (long int a, long int b, long int *r); #if defined (OCTAVE_HAVE_LONG_LONG_INT) - extern OCTAVE_API bool - int_multiply_overflow (long long int a, long long int b, long long int *r); +extern OCTAVE_API bool +int_multiply_overflow (long long int a, long long int b, long long int *r); #endif - extern OCTAVE_API bool - int_multiply_overflow (unsigned int a, unsigned int b, unsigned int *r); +extern OCTAVE_API bool +int_multiply_overflow (unsigned int a, unsigned int b, unsigned int *r); - extern OCTAVE_API bool - int_multiply_overflow (unsigned long int a, unsigned long int b, - unsigned long int *r); +extern OCTAVE_API bool +int_multiply_overflow (unsigned long int a, unsigned long int b, + unsigned long int *r); #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT) - extern OCTAVE_API bool - int_multiply_overflow (unsigned long long int a, unsigned long long int b, - unsigned long long int *r); +extern OCTAVE_API bool +int_multiply_overflow (unsigned long long int a, unsigned long long int b, + unsigned long long int *r); #endif OCTAVE_END_NAMESPACE(math) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-base64.cc --- a/liboctave/util/oct-base64.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-base64.cc Thu Dec 01 20:05:44 2022 -0800 @@ -35,91 +35,91 @@ OCTAVE_BEGIN_NAMESPACE(octave) - bool - base64_encode (const char *inc, const std::size_t inlen, char **out) - { - bool ret = false; +bool +base64_encode (const char *inc, const std::size_t inlen, char **out) +{ + bool ret = false; - std::ptrdiff_t outlen = octave_base64_encode_alloc_wrapper (inc, inlen, out); + std::ptrdiff_t outlen = octave_base64_encode_alloc_wrapper (inc, inlen, out); - if (! out) - { - if (outlen == 0 && inlen != 0) - (*current_liboctave_error_handler) - ("base64_encode: input array too large"); - else - (*current_liboctave_error_handler) - ("base64_encode: memory allocation error"); - } - else - ret = true; + if (! out) + { + if (outlen == 0 && inlen != 0) + (*current_liboctave_error_handler) + ("base64_encode: input array too large"); + else + (*current_liboctave_error_handler) + ("base64_encode: memory allocation error"); + } + else + ret = true; - return ret; - } + return ret; +} - Array - base64_decode (const std::string& str) - { - Array retval; +Array +base64_decode (const std::string& str) +{ + Array retval; - double *out; - std::ptrdiff_t outlen; + double *out; + std::ptrdiff_t outlen; - bool ok - = octave_base64_decode_alloc_wrapper (str.data (), str.length (), - reinterpret_cast (&out), - &outlen); + bool ok + = octave_base64_decode_alloc_wrapper (str.data (), str.length (), + reinterpret_cast (&out), + &outlen); - if (! ok) - (*current_liboctave_error_handler) - ("base64_decode: input was not valid base64"); + if (! ok) + (*current_liboctave_error_handler) + ("base64_decode: input was not valid base64"); - if (! out) - (*current_liboctave_error_handler) - ("base64_decode: memory allocation error"); + if (! out) + (*current_liboctave_error_handler) + ("base64_decode: memory allocation error"); - if ((outlen % (sizeof (double) / sizeof (char))) != 0) - { - ::free (out); - (*current_liboctave_error_handler) - ("base64_decode: incorrect input size"); - } - else - { - octave_idx_type len = (outlen * sizeof (char)) / sizeof (double); - retval.resize (dim_vector (1, len)); - std::copy (out, out + len, retval.fortran_vec ()); - ::free (out); - } + if ((outlen % (sizeof (double) / sizeof (char))) != 0) + { + ::free (out); + (*current_liboctave_error_handler) + ("base64_decode: incorrect input size"); + } + else + { + octave_idx_type len = (outlen * sizeof (char)) / sizeof (double); + retval.resize (dim_vector (1, len)); + std::copy (out, out + len, retval.fortran_vec ()); + ::free (out); + } - return retval; - } + return retval; +} - intNDArray - base64_decode_bytes (const std::string& str) - { - intNDArray retval; +intNDArray +base64_decode_bytes (const std::string& str) +{ + intNDArray retval; - char *out; - std::ptrdiff_t outlen; + char *out; + std::ptrdiff_t outlen; - bool ok - = octave_base64_decode_alloc_wrapper (str.data (), str.length (), - &out, &outlen); + bool ok + = octave_base64_decode_alloc_wrapper (str.data (), str.length (), + &out, &outlen); - if (! ok) - (*current_liboctave_error_handler) - ("base64_decode: input was not valid base64"); + if (! ok) + (*current_liboctave_error_handler) + ("base64_decode: input was not valid base64"); - if (! out) - (*current_liboctave_error_handler) - ("base64_decode: memory allocation error"); + if (! out) + (*current_liboctave_error_handler) + ("base64_decode: memory allocation error"); - retval.resize (dim_vector (1, outlen)); - std::copy (out, out + outlen, retval.fortran_vec ()); - ::free (out); + retval.resize (dim_vector (1, outlen)); + std::copy (out, out + outlen, retval.fortran_vec ()); + ::free (out); - return retval; - } + return retval; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-base64.h --- a/liboctave/util/oct-base64.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-base64.h Thu Dec 01 20:05:44 2022 -0800 @@ -35,14 +35,14 @@ OCTAVE_BEGIN_NAMESPACE(octave) - extern OCTAVE_API bool - base64_encode (const char *inc, const std::size_t inlen, char **out); +extern OCTAVE_API bool +base64_encode (const char *inc, const std::size_t inlen, char **out); - extern OCTAVE_API Array - base64_decode (const std::string& str); +extern OCTAVE_API Array +base64_decode (const std::string& str); - extern OCTAVE_API intNDArray - base64_decode_bytes (const std::string& str); +extern OCTAVE_API intNDArray +base64_decode_bytes (const std::string& str); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-glob.cc --- a/liboctave/util/oct-glob.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-glob.cc Thu Dec 01 20:05:44 2022 -0800 @@ -53,116 +53,170 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static bool - single_match_exists (const std::string& file) - { - sys::file_stat s (file); +static bool +single_match_exists (const std::string& file) +{ + sys::file_stat s (file); - return s.exists (); - } + return s.exists (); +} OCTAVE_BEGIN_NAMESPACE(sys) - bool - fnmatch (const string_vector& pat, const std::string& str, int fnm_flags) - { - int npat = pat.numel (); +bool +fnmatch (const string_vector& pat, const std::string& str, int fnm_flags) +{ + int npat = pat.numel (); + + const char *cstr = str.c_str (); - const char *cstr = str.c_str (); + for (int i = 0; i < npat; i++) + if (octave_fnmatch_wrapper (pat(i).c_str (), cstr, fnm_flags) + != octave_fnm_nomatch_wrapper ()) + return true; + + return false; +} - for (int i = 0; i < npat; i++) - if (octave_fnmatch_wrapper (pat(i).c_str (), cstr, fnm_flags) - != octave_fnm_nomatch_wrapper ()) - return true; +string_vector +glob (const string_vector& pat) +{ + string_vector retval; + + int npat = pat.numel (); - return false; - } + int k = 0; + + void *glob_info = octave_create_glob_info_struct (); - string_vector - glob (const string_vector& pat) + unwind_action cleanup_glob_info_struct + ([=] () { octave_destroy_glob_info_struct (glob_info); }); + + for (int i = 0; i < npat; i++) { - string_vector retval; - - int npat = pat.numel (); - - int k = 0; - - void *glob_info = octave_create_glob_info_struct (); + std::string xpat = pat(i); - unwind_action cleanup_glob_info_struct - ([=] () { octave_destroy_glob_info_struct (glob_info); }); - - for (int i = 0; i < npat; i++) + if (! xpat.empty ()) { - std::string xpat = pat(i); - - if (! xpat.empty ()) - { #if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - std::replace (xpat.begin (), xpat.end (), '\\', '/'); + std::replace (xpat.begin (), xpat.end (), '\\', '/'); #endif - int err = octave_glob_wrapper (xpat.c_str (), - octave_glob_nosort_wrapper (), - glob_info); + int err = octave_glob_wrapper (xpat.c_str (), + octave_glob_nosort_wrapper (), + glob_info); - if (! err) - { - int n = octave_glob_num_matches (glob_info); + if (! err) + { + int n = octave_glob_num_matches (glob_info); - const char * const *matches - = octave_glob_match_list (glob_info); + const char *const *matches + = octave_glob_match_list (glob_info); - // FIXME: we shouldn't have to check to see if - // a single match exists, but it seems that glob() won't - // check for us unless the pattern contains globbing - // characters. Hmm. + // FIXME: we shouldn't have to check to see if + // a single match exists, but it seems that glob() won't + // check for us unless the pattern contains globbing + // characters. Hmm. - if (n > 1 - || (n == 1 - && single_match_exists (std::string (matches[0])))) + if (n > 1 + || (n == 1 + && single_match_exists (std::string (matches[0])))) + { + retval.resize (k+n); + + for (int j = 0; j < n; j++) { - retval.resize (k+n); - - for (int j = 0; j < n; j++) - { - std::string tmp = matches[j]; + std::string tmp = matches[j]; #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM) - std::replace (tmp.begin (), tmp.end (), '/', '\\'); + std::replace (tmp.begin (), tmp.end (), '/', '\\'); #endif - retval[k++] = tmp; - } + retval[k++] = tmp; } + } - octave_globfree_wrapper (glob_info); - } + octave_globfree_wrapper (glob_info); } } + } - return retval.sort (); - } + return retval.sort (); +} #if defined (OCTAVE_USE_WINDOWS_API) - static void - find_files (std::list& dirlist, const std::string& dir, - const std::string& pat, std::string& file) +static void +find_files (std::list& dirlist, const std::string& dir, + const std::string& pat, std::string& file) +{ + // remove leading file separators + bool is_file_empty = file.empty (); + while (! file.empty () && sys::file_ops::is_dir_sep (file[0])) + file = file.substr (1, std::string::npos); + + bool is_trailing_file_sep = ! is_file_empty && file.empty (); + + if (! pat.compare (".") || ! pat.compare ("..")) { - // remove leading file separators - bool is_file_empty = file.empty (); - while (! file.empty () && sys::file_ops::is_dir_sep (file[0])) - file = file.substr (1, std::string::npos); + // shortcut for trivial patterns that would expand to a folder name + + // get next component of path (or file name) + std::size_t sep_pos + = file.find_first_of (sys::file_ops::dir_sep_chars ()); + std::string pat_str = file.substr (0, sep_pos); + std::string file_str = (sep_pos != std::string::npos) + ? file.substr (sep_pos) : ""; + + // Original pattern ends with "." or "..". Take it as we have it. + if (pat_str.empty ()) + { + if (is_trailing_file_sep) + pat_str = sys::file_ops::dir_sep_char (); + dirlist.push_back (sys::file_ops::concat (dir, pat) + pat_str); + return; + } + + // call this function recursively with next path component in PAT + find_files (dirlist, sys::file_ops::concat (dir, pat), + pat_str, file_str); + return; + } - bool is_trailing_file_sep = ! is_file_empty && file.empty (); + // find first file in directory that matches pattern in PAT + std::wstring wpat = u8_to_wstring (sys::file_ops::concat (dir, pat)); + _WIN32_FIND_DATAW ffd; + HANDLE h_find = FindFirstFileW (wpat.c_str (), &ffd); + // ignore any error + if (h_find == INVALID_HANDLE_VALUE) + return; + + unwind_action close_h_find ([=] () { FindClose (h_find); }); - if (! pat.compare (".") || ! pat.compare ("..")) + // find all files that match pattern + do + { + // must be directory if pattern continues + if (! (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + && (! file.empty () || is_trailing_file_sep)) + continue; + + std::string found_dir = u8_from_wstring (ffd.cFileName); + + if (file.empty ()) { - // shortcut for trivial patterns that would expand to a folder name - + // Don't include "." and ".." in matches. + if (found_dir.compare (".") && found_dir.compare ("..")) + { + if (is_trailing_file_sep) + found_dir += sys::file_ops::dir_sep_char (); + dirlist.push_back (sys::file_ops::concat (dir, found_dir)); + } + } + else + { // get next component of path (or file name) std::size_t sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ()); @@ -170,247 +224,193 @@ std::string file_str = (sep_pos != std::string::npos) ? file.substr (sep_pos) : ""; - // Original pattern ends with "." or "..". Take it as we have it. - if (pat_str.empty ()) - { - if (is_trailing_file_sep) - pat_str = sys::file_ops::dir_sep_char (); - dirlist.push_back (sys::file_ops::concat (dir, pat) + pat_str); - return; - } - // call this function recursively with next path component in PAT - find_files (dirlist, sys::file_ops::concat (dir, pat), + find_files (dirlist, sys::file_ops::concat (dir, found_dir), pat_str, file_str); - return; } - - // find first file in directory that matches pattern in PAT - std::wstring wpat = u8_to_wstring (sys::file_ops::concat (dir, pat)); - _WIN32_FIND_DATAW ffd; - HANDLE h_find = FindFirstFileW (wpat.c_str (), &ffd); - // ignore any error - if (h_find == INVALID_HANDLE_VALUE) - return; - - unwind_action close_h_find ([=] () { FindClose (h_find); }); - - // find all files that match pattern - do - { - // must be directory if pattern continues - if (! (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - && (! file.empty () || is_trailing_file_sep)) - continue; - - std::string found_dir = u8_from_wstring (ffd.cFileName); - - if (file.empty ()) - { - // Don't include "." and ".." in matches. - if (found_dir.compare (".") && found_dir.compare ("..")) - { - if (is_trailing_file_sep) - found_dir += sys::file_ops::dir_sep_char (); - dirlist.push_back (sys::file_ops::concat (dir, found_dir)); - } - } - else - { - // get next component of path (or file name) - std::size_t sep_pos - = file.find_first_of (sys::file_ops::dir_sep_chars ()); - std::string pat_str = file.substr (0, sep_pos); - std::string file_str = (sep_pos != std::string::npos) - ? file.substr (sep_pos) : ""; - - // call this function recursively with next path component in PAT - find_files (dirlist, sys::file_ops::concat (dir, found_dir), - pat_str, file_str); - } - } - while (FindNextFileW (h_find, &ffd) != 0); } + while (FindNextFileW (h_find, &ffd) != 0); +} #endif - // Glob like Windows "dir". Treat only * and ? as wildcards, - // and "*.*" matches filenames even if they do not contain ".". - string_vector - windows_glob (const string_vector& pat) - { - string_vector retval; +// Glob like Windows "dir". Treat only * and ? as wildcards, +// and "*.*" matches filenames even if they do not contain ".". +string_vector +windows_glob (const string_vector& pat) +{ + string_vector retval; - int npat = pat.numel (); + int npat = pat.numel (); #if defined (OCTAVE_USE_WINDOWS_API) - std::list dirlist; + std::list dirlist; + + for (int i = 0; i < npat; i++) + { + std::string xpat = pat(i); + if (xpat.empty ()) + continue; - for (int i = 0; i < npat; i++) + std::string dir = ""; + + // separate component until first file separator + std::size_t sep_pos + = xpat.find_first_of (sys::file_ops::dir_sep_chars ()); + + // handle UNC paths + if (sep_pos == 0 && xpat.length () > 1 + && sys::file_ops::is_dir_sep (xpat[1])) { - std::string xpat = pat(i); - if (xpat.empty ()) - continue; + // start pattern with a file, i.e., "\\SERVER\share\file" + sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), 2); + if (sep_pos != std::string::npos) + sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), + sep_pos + 1); + if (sep_pos != std::string::npos) + { + dir = xpat.substr(0, sep_pos); + xpat = xpat.substr (sep_pos+1); + sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars ()); + } + } - std::string dir = ""; + std::string file = (sep_pos != std::string::npos) + ? xpat.substr (sep_pos) : ""; + xpat = xpat.substr (0, sep_pos); - // separate component until first file separator - std::size_t sep_pos - = xpat.find_first_of (sys::file_ops::dir_sep_chars ()); + if ((sep_pos == 2 || xpat.length () == 2) && xpat[1] == ':') + { + // include disc root with first file or folder + + // remove leading file separators in path without disc root + while (file.length () > 1 && sys::file_ops::is_dir_sep (file[0])) + file = file.substr (1, std::string::npos); - // handle UNC paths - if (sep_pos == 0 && xpat.length () > 1 - && sys::file_ops::is_dir_sep (xpat[1])) + sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ()); + dir = xpat; + xpat = file.substr (0, sep_pos); + file = (sep_pos != std::string::npos) + ? file.substr (sep_pos) : ""; + if (xpat.empty ()) { - // start pattern with a file, i.e., "\\SERVER\share\file" - sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), 2); - if (sep_pos != std::string::npos) - sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars (), - sep_pos + 1); - if (sep_pos != std::string::npos) + // don't glob if input is only disc root + std::wstring wpat = u8_to_wstring (pat(i)); + if (PathFileExistsW (wpat.c_str ())) { - dir = xpat.substr(0, sep_pos); - xpat = xpat.substr (sep_pos+1); - sep_pos = xpat.find_first_of (sys::file_ops::dir_sep_chars ()); + if (sys::file_ops::is_dir_sep (pat(i).back ())) + dirlist.push_back (dir + + sys::file_ops::dir_sep_char ()); + else + dirlist.push_back (dir); + } + continue; + } + } + + find_files (dirlist, dir, xpat, file); + } + + retval = string_vector (dirlist); + +#else + + int k = 0; + + void *glob_info = octave_create_glob_info_struct (); + + unwind_action cleanup_glob_info_struct + ([=] () { octave_destroy_glob_info_struct (glob_info); }); + + for (int i = 0; i < npat; i++) + { + std::string xpat = pat(i); + + if (! xpat.empty ()) + { + std::string escaped; + escaped.reserve (xpat.length ()); + + for (std::size_t j = 0; j < xpat.length (); j++) + { +# if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ + && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) + if (xpat[j] == '\\') + escaped += '/'; + else +# endif + { + if (xpat[j] == ']' || xpat[j] == '[') + escaped += '\\'; + + escaped += xpat[j]; } } - std::string file = (sep_pos != std::string::npos) - ? xpat.substr (sep_pos) : ""; - xpat = xpat.substr (0, sep_pos); + // Replace trailing "*.*" by "*". + int len = escaped.length (); + if (len >= 3 && escaped.substr (len - 3) == "*.*") + escaped = escaped.substr (0, len - 2); - if ((sep_pos == 2 || xpat.length () == 2) && xpat[1] == ':') - { - // include disc root with first file or folder - - // remove leading file separators in path without disc root - while (file.length () > 1 && sys::file_ops::is_dir_sep (file[0])) - file = file.substr (1, std::string::npos); + int err = octave_glob_wrapper (escaped.c_str (), + octave_glob_nosort_wrapper (), + glob_info); - sep_pos = file.find_first_of (sys::file_ops::dir_sep_chars ()); - dir = xpat; - xpat = file.substr (0, sep_pos); - file = (sep_pos != std::string::npos) - ? file.substr (sep_pos) : ""; - if (xpat.empty ()) - { - // don't glob if input is only disc root - std::wstring wpat = u8_to_wstring (pat(i)); - if (PathFileExistsW (wpat.c_str ())) - { - if (sys::file_ops::is_dir_sep (pat(i).back ())) - dirlist.push_back (dir + - sys::file_ops::dir_sep_char ()); - else - dirlist.push_back (dir); - } - continue; - } - } + if (! err) + { + int n = octave_glob_num_matches (glob_info); + + const char *const *matches + = octave_glob_match_list (glob_info); + + // FIXME: we shouldn't have to check to see if + // a single match exists, but it seems that glob() won't + // check for us unless the pattern contains globbing + // characters. Hmm. - find_files (dirlist, dir, xpat, file); - } - - retval = string_vector (dirlist); - -#else - - int k = 0; + if (n > 1 + || (n == 1 + && single_match_exists (std::string (matches[0])))) + { + retval.resize (k + n); - void *glob_info = octave_create_glob_info_struct (); + for (int j = 0; j < n; j++) + { + std::string tmp = matches[j]; - unwind_action cleanup_glob_info_struct - ([=] () { octave_destroy_glob_info_struct (glob_info); }); - - for (int i = 0; i < npat; i++) - { - std::string xpat = pat(i); + std::string unescaped; + unescaped.reserve (tmp.length ()); - if (! xpat.empty ()) - { - std::string escaped; - escaped.reserve (xpat.length ()); - - for (std::size_t j = 0; j < xpat.length (); j++) - { + for (std::size_t m = 0; m < tmp.length (); m++) + { # if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ - && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - if (xpat[j] == '\\') - escaped += '/'; - else + && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) + if (tmp[m] == '/') + unescaped += '\\'; + else # endif - { - if (xpat[j] == ']' || xpat[j] == '[') - escaped += '\\'; + { + if (tmp[m] == '\\' + && ++m == tmp.length ()) + break; - escaped += xpat[j]; + unescaped += tmp[m]; + } + } + + retval[k++] = unescaped; } } - // Replace trailing "*.*" by "*". - int len = escaped.length (); - if (len >= 3 && escaped.substr (len - 3) == "*.*") - escaped = escaped.substr (0, len - 2); - - int err = octave_glob_wrapper (escaped.c_str (), - octave_glob_nosort_wrapper (), - glob_info); - - if (! err) - { - int n = octave_glob_num_matches (glob_info); - - const char * const *matches - = octave_glob_match_list (glob_info); - - // FIXME: we shouldn't have to check to see if - // a single match exists, but it seems that glob() won't - // check for us unless the pattern contains globbing - // characters. Hmm. - - if (n > 1 - || (n == 1 - && single_match_exists (std::string (matches[0])))) - { - retval.resize (k + n); - - for (int j = 0; j < n; j++) - { - std::string tmp = matches[j]; - - std::string unescaped; - unescaped.reserve (tmp.length ()); - - for (std::size_t m = 0; m < tmp.length (); m++) - { -# if (defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM) \ - && ! defined (OCTAVE_HAVE_POSIX_FILESYSTEM)) - if (tmp[m] == '/') - unescaped += '\\'; - else -# endif - { - if (tmp[m] == '\\' - && ++m == tmp.length ()) - break; - - unescaped += tmp[m]; - } - } - - retval[k++] = unescaped; - } - } - - octave_globfree_wrapper (glob_info); - } + octave_globfree_wrapper (glob_info); } } + } #endif - return retval.sort (); - } + return retval.sort (); +} OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-glob.h --- a/liboctave/util/oct-glob.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-glob.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,15 +34,15 @@ OCTAVE_BEGIN_NAMESPACE(sys) - extern OCTAVE_API bool - fnmatch (const string_vector& pat, const std::string& str, - int fnmatch_flags); +extern OCTAVE_API bool +fnmatch (const string_vector& pat, const std::string& str, + int fnmatch_flags); - extern OCTAVE_API string_vector - glob (const string_vector&); +extern OCTAVE_API string_vector +glob (const string_vector&); - extern OCTAVE_API string_vector - windows_glob (const string_vector&); +extern OCTAVE_API string_vector +windows_glob (const string_vector&); OCTAVE_END_NAMESPACE(sys) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-inttypes.h --- a/liboctave/util/oct-inttypes.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-inttypes.h Thu Dec 01 20:05:44 2022 -0800 @@ -44,15 +44,15 @@ OCTAVE_BEGIN_NAMESPACE(math) - inline long double round (long double x) - { - return std::roundl (x); - } +inline long double round (long double x) +{ + return std::roundl (x); +} - inline long double isnan (long double x) - { - return isnan (static_cast (x)); - } +inline long double isnan (long double x) +{ + return isnan (static_cast (x)); +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) @@ -259,8 +259,7 @@ \ template \ static OCTAVE_API bool external_mop (T, double) - - OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (int64_t); + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (int64_t); OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (uint64_t); #endif @@ -483,10 +482,10 @@ { // Promotion type for multiplication (if exists). - typedef typename query_integer_type<2*sizeof (T), false>::type mptype; + typedef typename query_integer_type<2* sizeof (T), false>::type mptype; return octave_int_base::truncate_int (static_cast (x) - * static_cast (y)); + * static_cast (y)); } // Division with rounding to nearest. Note that / and % are @@ -652,7 +651,7 @@ { // Promotion type for multiplication (if exists). - typedef typename query_integer_type<2*sizeof (T), true>::type mptype; + typedef typename query_integer_type<2* sizeof (T), true>::type mptype; return octave_int_base::truncate_int (static_cast (x) * static_cast (y)); @@ -933,12 +932,12 @@ OCTAVE_BEGIN_NAMESPACE(math) - template - bool - isnan (const octave_int&) - { - return false; - } +template +bool +isnan (const octave_int&) +{ + return false; +} OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) @@ -1105,8 +1104,8 @@ OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, mul); \ OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, div) - OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_int64); - OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_uint64); +OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_int64); +OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_uint64); #endif diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-mutex.cc --- a/liboctave/util/oct-mutex.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-mutex.cc Thu Dec 01 20:05:44 2022 -0800 @@ -38,145 +38,145 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - base_mutex::lock (void) - { - (*current_liboctave_error_handler) ("mutex not supported on this platform"); - } +void +base_mutex::lock (void) +{ + (*current_liboctave_error_handler) ("mutex not supported on this platform"); +} - void - base_mutex::unlock (void) - { - (*current_liboctave_error_handler) ("mutex not supported on this platform"); - } +void +base_mutex::unlock (void) +{ + (*current_liboctave_error_handler) ("mutex not supported on this platform"); +} - bool - base_mutex::try_lock (void) - { - (*current_liboctave_error_handler) ("mutex not supported on this platform"); +bool +base_mutex::try_lock (void) +{ + (*current_liboctave_error_handler) ("mutex not supported on this platform"); - return false; - } + return false; +} #if defined (OCTAVE_USE_WINDOWS_API) - class - w32_mutex : public base_mutex +class +w32_mutex : public base_mutex +{ +public: + w32_mutex (void) + : base_mutex () { - public: - w32_mutex (void) - : base_mutex () - { - InitializeCriticalSection (&cs); - } - - ~w32_mutex (void) - { - DeleteCriticalSection (&cs); - } - - void lock (void) - { - EnterCriticalSection (&cs); - } + InitializeCriticalSection (&cs); + } - void unlock (void) - { - LeaveCriticalSection (&cs); - } - - bool try_lock (void) - { - return (TryEnterCriticalSection (&cs) != 0); - } + ~w32_mutex (void) + { + DeleteCriticalSection (&cs); + } - private: - CRITICAL_SECTION cs; - }; - - static DWORD thread_id = 0; - - void - thread::init (void) + void lock (void) { - thread_id = GetCurrentThreadId (); + EnterCriticalSection (&cs); } - bool - thread::is_thread (void) + void unlock (void) + { + LeaveCriticalSection (&cs); + } + + bool try_lock (void) { - return (GetCurrentThreadId () == thread_id); + return (TryEnterCriticalSection (&cs) != 0); } +private: + CRITICAL_SECTION cs; +}; + +static DWORD thread_id = 0; + +void +thread::init (void) +{ + thread_id = GetCurrentThreadId (); +} + +bool +thread::is_thread (void) +{ + return (GetCurrentThreadId () == thread_id); +} + #elif defined (HAVE_PTHREAD_H) - class - pthread_mutex : public base_mutex +class +pthread_mutex : public base_mutex +{ +public: + pthread_mutex (void) + : base_mutex (), m_pm () { - public: - pthread_mutex (void) - : base_mutex (), m_pm () - { - pthread_mutexattr_t attr; - - pthread_mutexattr_init (&attr); - pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init (&m_pm, &attr); - pthread_mutexattr_destroy (&attr); - } - - ~pthread_mutex (void) - { - pthread_mutex_destroy (&m_pm); - } + pthread_mutexattr_t attr; - void lock (void) - { - pthread_mutex_lock (&m_pm); - } - - void unlock (void) - { - pthread_mutex_unlock (&m_pm); - } + pthread_mutexattr_init (&attr); + pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init (&m_pm, &attr); + pthread_mutexattr_destroy (&attr); + } - bool try_lock (void) - { - return (pthread_mutex_trylock (&m_pm) == 0); - } + ~pthread_mutex (void) + { + pthread_mutex_destroy (&m_pm); + } - private: - pthread_mutex_t m_pm; - }; - - static pthread_t thread_id = 0; - - void - thread::init (void) + void lock (void) { - thread_id = pthread_self (); + pthread_mutex_lock (&m_pm); } - bool - thread::is_thread (void) + void unlock (void) + { + pthread_mutex_unlock (&m_pm); + } + + bool try_lock (void) { - return (pthread_equal (thread_id, pthread_self ()) != 0); + return (pthread_mutex_trylock (&m_pm) == 0); } +private: + pthread_mutex_t m_pm; +}; + +static pthread_t thread_id = 0; + +void +thread::init (void) +{ + thread_id = pthread_self (); +} + +bool +thread::is_thread (void) +{ + return (pthread_equal (thread_id, pthread_self ()) != 0); +} + #endif - static base_mutex * - init_rep (void) - { +static base_mutex * +init_rep (void) +{ #if defined (OCTAVE_USE_WINDOWS_API) - return new w32_mutex (); + return new w32_mutex (); #elif defined (HAVE_PTHREAD_H) - return new pthread_mutex (); + return new pthread_mutex (); #else - return new base_mutex (); + return new base_mutex (); #endif - } +} - mutex::mutex (void) : m_rep (init_rep ()) { } +mutex::mutex (void) : m_rep (init_rep ()) { } OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-mutex.h --- a/liboctave/util/oct-mutex.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-mutex.h Thu Dec 01 20:05:44 2022 -0800 @@ -32,109 +32,109 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class mutex; +class mutex; - class - OCTAVE_API - base_mutex - { - public: - friend class mutex; +class +OCTAVE_API +base_mutex +{ +public: + friend class mutex; - base_mutex (void) = default; + base_mutex (void) = default; - virtual ~base_mutex (void) = default; + virtual ~base_mutex (void) = default; - virtual void lock (void); + virtual void lock (void); - virtual void unlock (void); + virtual void unlock (void); - virtual bool try_lock (void); - }; + virtual bool try_lock (void); +}; - class - OCTAVE_API - mutex - { - public: - mutex (void); +class +OCTAVE_API +mutex +{ +public: + mutex (void); - mutex (const mutex& m) = default; + mutex (const mutex& m) = default; - ~mutex (void) = default; + ~mutex (void) = default; - mutex& operator = (const mutex& m) = default; + mutex& operator = (const mutex& m) = default; - void lock (void) - { - m_rep->lock (); - } + void lock (void) + { + m_rep->lock (); + } - void unlock (void) - { - m_rep->unlock (); - } + void unlock (void) + { + m_rep->unlock (); + } - bool try_lock (void) - { - return m_rep->try_lock (); - } + bool try_lock (void) + { + return m_rep->try_lock (); + } - protected: - std::shared_ptr m_rep; - }; +protected: + std::shared_ptr m_rep; +}; - class - OCTAVE_API - autolock +class +OCTAVE_API +autolock +{ +public: + autolock (const mutex& m, bool block = true) + : m_mutex (m), m_lock_result (false) { - public: - autolock (const mutex& m, bool block = true) - : m_mutex (m), m_lock_result (false) - { - if (block) - { - m_mutex.lock (); - m_lock_result = true; - } - else - m_lock_result = m_mutex.try_lock (); - } + if (block) + { + m_mutex.lock (); + m_lock_result = true; + } + else + m_lock_result = m_mutex.try_lock (); + } - // No copying. + // No copying. - autolock (const autolock&) = delete; + autolock (const autolock&) = delete; + + autolock& operator = (const autolock&) = delete; - autolock& operator = (const autolock&) = delete; + ~autolock (void) + { + if (m_lock_result) + m_mutex.unlock (); + } - ~autolock (void) - { - if (m_lock_result) - m_mutex.unlock (); - } + bool ok (void) const { return m_lock_result; } - bool ok (void) const { return m_lock_result; } + operator bool (void) const { return ok (); } - operator bool (void) const { return ok (); } +private: - private: + mutex m_mutex; - mutex m_mutex; - - bool m_lock_result; - }; + bool m_lock_result; +}; - class - OCTAVE_API - thread - { - public: +class +OCTAVE_API +thread +{ +public: - static void init (void); + static void init (void); - static bool is_thread (void); - }; + static bool is_thread (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-refcount.h --- a/liboctave/util/oct-refcount.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-refcount.h Thu Dec 01 20:05:44 2022 -0800 @@ -32,60 +32,60 @@ OCTAVE_BEGIN_NAMESPACE(octave) - // Encapsulates a reference counter. +// Encapsulates a reference counter. - template - class refcount - { - public: +template +class refcount +{ +public: - typedef T count_type; + typedef T count_type; - refcount (count_type initial_count) - : m_count (initial_count) - { } + refcount (count_type initial_count) + : m_count (initial_count) + { } - refcount (const refcount&) = delete; + refcount (const refcount&) = delete; - refcount& operator = (const refcount&) = delete; + refcount& operator = (const refcount&) = delete; - ~refcount (void) = default; + ~refcount (void) = default; - // Increment/Decrement. int is postfix. - count_type operator++ (void) - { - return ++m_count; - } + // Increment/Decrement. int is postfix. + count_type operator++ (void) + { + return ++m_count; + } - count_type operator++ (int) - { - return m_count++; - } + count_type operator++ (int) + { + return m_count++; + } - count_type operator-- (void) - { - return --m_count; - } + count_type operator-- (void) + { + return --m_count; + } - count_type operator-- (int) - { - return m_count--; - } + count_type operator-- (int) + { + return m_count--; + } - count_type value (void) const - { - return m_count.load (); - } + count_type value (void) const + { + return m_count.load (); + } - operator count_type (void) const - { - return value (); - } + operator count_type (void) const + { + return value (); + } - private: +private: - std::atomic m_count; - }; + std::atomic m_count; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-shlib.cc --- a/liboctave/util/oct-shlib.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-shlib.cc Thu Dec 01 20:05:44 2022 -0800 @@ -36,10 +36,10 @@ # if defined (HAVE_DLFCN_H) # include # else -extern void * dlopen (const char *, int); -extern const char * dlerror (void); -extern void * dlsym (void *, const char *); -extern int dlclose (void *); + extern void * dlopen (const char *, int); + extern const char * dlerror (void); + extern void * dlsym (void *, const char *); + extern int dlclose (void *); # endif #elif defined (HAVE_LOADLIBRARY_API) # define WIN32_LEAN_AND_MEAN 1 @@ -60,392 +60,392 @@ OCTAVE_BEGIN_NAMESPACE(octave) - std::list possibly_unreferenced_dynamic_libraries; +std::list possibly_unreferenced_dynamic_libraries; + +void dynamic_library::delete_later (void) +{ + possibly_unreferenced_dynamic_libraries.push_back (*this); +} - void dynamic_library::delete_later (void) - { - possibly_unreferenced_dynamic_libraries.push_back (*this); - } +int release_unreferenced_dynamic_libraries (void) +{ + possibly_unreferenced_dynamic_libraries.clear (); - int release_unreferenced_dynamic_libraries (void) - { - possibly_unreferenced_dynamic_libraries.clear (); + return 0; +} + +dynamic_library::dynlib_rep::dynlib_rep (const std::string& f) + : m_count (1), m_fcn_names (), m_file (f), m_time_loaded (), + m_search_all_loaded (false) +{ + s_instances[f] = this; - return 0; - } + if (is_out_of_date ()) + (*current_liboctave_warning_with_id_handler) + ("Octave:warn-future-time-stamp", + "timestamp on file %s is in the future", m_file.c_str ()); +} - dynamic_library::dynlib_rep::dynlib_rep (const std::string& f) - : m_count (1), m_fcn_names (), m_file (f), m_time_loaded (), - m_search_all_loaded (false) - { - s_instances[f] = this; +bool +dynamic_library::dynlib_rep::is_out_of_date (void) const +{ + sys::file_stat fs (m_file); + return (fs && fs.is_newer (m_time_loaded)); +} - if (is_out_of_date ()) +void +dynamic_library::dynlib_rep::fake_reload (void) +{ + // We can't actually reload the library, but we'll pretend we did. + sys::file_stat fs (m_file); + if (fs && fs.is_newer (m_time_loaded)) + { + m_time_loaded = fs.mtime (); + (*current_liboctave_warning_with_id_handler) - ("Octave:warn-future-time-stamp", - "timestamp on file %s is in the future", m_file.c_str ()); - } - - bool - dynamic_library::dynlib_rep::is_out_of_date (void) const - { - sys::file_stat fs (m_file); - return (fs && fs.is_newer (m_time_loaded)); - } - - void - dynamic_library::dynlib_rep::fake_reload (void) - { - // We can't actually reload the library, but we'll pretend we did. - sys::file_stat fs (m_file); - if (fs && fs.is_newer (m_time_loaded)) - { - m_time_loaded = fs.mtime (); - - (*current_liboctave_warning_with_id_handler) - ("Octave:library-reload", - "library %s not reloaded due to existing references", m_file.c_str ()); - } - } + ("Octave:library-reload", + "library %s not reloaded due to existing references", m_file.c_str ()); + } +} - dynamic_library::dynlib_rep * - dynamic_library::dynlib_rep::get_instance (const std::string& f, bool fake) - { - dynlib_rep *retval = nullptr; - std::map::iterator p = s_instances.find (f); - if (p != s_instances.end ()) - { - retval = p->second; - retval->m_count++; - if (fake) - retval->fake_reload (); - } - else - retval = new_instance (f); +dynamic_library::dynlib_rep * +dynamic_library::dynlib_rep::get_instance (const std::string& f, bool fake) +{ + dynlib_rep *retval = nullptr; + std::map::iterator p = s_instances.find (f); + if (p != s_instances.end ()) + { + retval = p->second; + retval->m_count++; + if (fake) + retval->fake_reload (); + } + else + retval = new_instance (f); - return retval; - } + return retval; +} - std::list - dynamic_library::dynlib_rep::function_names (void) const - { - std::list retval; +std::list +dynamic_library::dynlib_rep::function_names (void) const +{ + std::list retval; - for (const auto& p : m_fcn_names) - retval.push_back (p.first); + for (const auto& p : m_fcn_names) + retval.push_back (p.first); - return retval; - } + return retval; +} - void - dynamic_library::dynlib_rep::add_fcn_name (const std::string& name) - { - auto p = m_fcn_names.find (name); +void +dynamic_library::dynlib_rep::add_fcn_name (const std::string& name) +{ + auto p = m_fcn_names.find (name); - if (p == m_fcn_names.end ()) - m_fcn_names[name] = 1; - else - ++(p->second); - } + if (p == m_fcn_names.end ()) + m_fcn_names[name] = 1; + else + ++(p->second); +} - bool - dynamic_library::dynlib_rep::remove_fcn_name (const std::string& fcn_name) - { - bool retval = false; +bool +dynamic_library::dynlib_rep::remove_fcn_name (const std::string& fcn_name) +{ + bool retval = false; - auto p = m_fcn_names.find (fcn_name); + auto p = m_fcn_names.find (fcn_name); - if (p != m_fcn_names.end () && --(p->second) == 0) - { - m_fcn_names.erase (fcn_name); - retval = true; - } + if (p != m_fcn_names.end () && --(p->second) == 0) + { + m_fcn_names.erase (fcn_name); + retval = true; + } - return retval; - } + return retval; +} - std::map - dynamic_library::dynlib_rep::s_instances; +std::map +dynamic_library::dynlib_rep::s_instances; - dynamic_library::dynlib_rep dynamic_library::s_nil_rep; +dynamic_library::dynlib_rep dynamic_library::s_nil_rep; #if defined (HAVE_DLOPEN_API) - class - octave_dlopen_shlib : public dynamic_library::dynlib_rep - { - public: +class +octave_dlopen_shlib : public dynamic_library::dynlib_rep +{ +public: - octave_dlopen_shlib (const std::string& f); + octave_dlopen_shlib (const std::string& f); - // No copying! + // No copying! - octave_dlopen_shlib (const octave_dlopen_shlib&) = delete; + octave_dlopen_shlib (const octave_dlopen_shlib&) = delete; - octave_dlopen_shlib& operator = (const octave_dlopen_shlib&) = delete; + octave_dlopen_shlib& operator = (const octave_dlopen_shlib&) = delete; - ~octave_dlopen_shlib (void); + ~octave_dlopen_shlib (void); - void * search (const std::string& name, - const dynamic_library::name_mangler& mangler - = dynamic_library::name_mangler ()); + void * search (const std::string& name, + const dynamic_library::name_mangler& mangler + = dynamic_library::name_mangler ()); - // FIXME: this is possibly redundant because failure to open a library will - // normally throw an exception, avoiding the construction of an invalid - // library. Leave it here for possible future use. + // FIXME: this is possibly redundant because failure to open a library will + // normally throw an exception, avoiding the construction of an invalid + // library. Leave it here for possible future use. - bool is_open (void) const - { - return (m_search_all_loaded || m_library != nullptr); - } + bool is_open (void) const + { + return (m_search_all_loaded || m_library != nullptr); + } - private: +private: - void *m_library; - }; + void *m_library; +}; - octave_dlopen_shlib::octave_dlopen_shlib (const std::string& f) - : dynamic_library::dynlib_rep (f), m_library (nullptr) - { - int flags = 0; +octave_dlopen_shlib::octave_dlopen_shlib (const std::string& f) + : dynamic_library::dynlib_rep (f), m_library (nullptr) +{ + int flags = 0; - // Use RTLD_NOW to resolve all symbols before dlopen returns. - // By using this option, dlopen will detect errors and Octave - // won't exit if there are unresolved symbols in the file we are - // loading, and we may even get a useful diagnostic. + // Use RTLD_NOW to resolve all symbols before dlopen returns. + // By using this option, dlopen will detect errors and Octave + // won't exit if there are unresolved symbols in the file we are + // loading, and we may even get a useful diagnostic. # if defined (RTLD_NOW) - flags |= RTLD_NOW; + flags |= RTLD_NOW; # endif - // Use RTLD_GLOBAL to export symbols from loaded objects so they are - // available to other subsequently loaded libraries. + // Use RTLD_GLOBAL to export symbols from loaded objects so they are + // available to other subsequently loaded libraries. # if defined (RTLD_GLOBAL) - flags |= RTLD_GLOBAL; + flags |= RTLD_GLOBAL; # endif - if (m_file.empty ()) - { - m_search_all_loaded = true; - return; - } + if (m_file.empty ()) + { + m_search_all_loaded = true; + return; + } - m_library = dlopen (m_file.c_str (), flags); + m_library = dlopen (m_file.c_str (), flags); - if (! m_library) - { - const char *msg = dlerror (); + if (! m_library) + { + const char *msg = dlerror (); - if (msg) - (*current_liboctave_error_handler) - ("%s: failed to load\nIncompatible version or missing dependency?" - "\n%s", m_file.c_str (), msg); - else - (*current_liboctave_error_handler) - ("%s: failed to load\nIncompatible version or missing dependency?", - m_file.c_str ()); - } - } + if (msg) + (*current_liboctave_error_handler) + ("%s: failed to load\nIncompatible version or missing dependency?" + "\n%s", m_file.c_str (), msg); + else + (*current_liboctave_error_handler) + ("%s: failed to load\nIncompatible version or missing dependency?", + m_file.c_str ()); + } +} - octave_dlopen_shlib::~octave_dlopen_shlib (void) - { - if (m_library) - dlclose (m_library); - } +octave_dlopen_shlib::~octave_dlopen_shlib (void) +{ + if (m_library) + dlclose (m_library); +} - void * - octave_dlopen_shlib::search (const std::string& name, - const dynamic_library::name_mangler& mangler) - { - void *function = nullptr; +void * +octave_dlopen_shlib::search (const std::string& name, + const dynamic_library::name_mangler& mangler) +{ + void *function = nullptr; - if (! is_open ()) - (*current_liboctave_error_handler) - ("shared library %s is not open", m_file.c_str ()); + if (! is_open ()) + (*current_liboctave_error_handler) + ("shared library %s is not open", m_file.c_str ()); - std::string sym_name = name; + std::string sym_name = name; - if (mangler) - sym_name = mangler (name); + if (mangler) + sym_name = mangler (name); - if (m_search_all_loaded) - function = dlsym (RTLD_DEFAULT, sym_name.c_str ()); - else - function = dlsym (m_library, sym_name.c_str ()); + if (m_search_all_loaded) + function = dlsym (RTLD_DEFAULT, sym_name.c_str ()); + else + function = dlsym (m_library, sym_name.c_str ()); - return function; - } + return function; +} #elif defined (HAVE_LOADLIBRARY_API) - class - octave_w32_shlib: public dynamic_library::dynlib_rep - { - public: - - octave_w32_shlib (const std::string& f); +class +octave_w32_shlib: public dynamic_library::dynlib_rep +{ +public: - // No copying! - - octave_w32_shlib (const octave_w32_shlib&) = delete; + octave_w32_shlib (const std::string& f); - octave_w32_shlib& operator = (const octave_w32_shlib&) = delete; + // No copying! - ~octave_w32_shlib (void); + octave_w32_shlib (const octave_w32_shlib&) = delete; - void * search (const std::string& name, - const dynamic_library::name_mangler& mangler - = dynamic_library::name_mangler ()); + octave_w32_shlib& operator = (const octave_w32_shlib&) = delete; - void * global_search (const std::string& sym_name); + ~octave_w32_shlib (void); - bool is_open (void) const - { - return (m_search_all_loaded || m_handle != nullptr); - } + void * search (const std::string& name, + const dynamic_library::name_mangler& mangler + = dynamic_library::name_mangler ()); - private: + void * global_search (const std::string& sym_name); - HINSTANCE m_handle; - }; - - octave_w32_shlib::octave_w32_shlib (const std::string& f) - : dynamic_library::dynlib_rep (f), m_handle (nullptr) + bool is_open (void) const { - if (f.empty()) - { - m_search_all_loaded = true; - return; - } - - std::string dir = sys::file_ops::dirname (f); - std::wstring wdir = sys::u8_to_wstring (dir); - SetDllDirectoryW (dir.empty () - ? nullptr : wdir.c_str ()); - - std::wstring wfile = sys::u8_to_wstring (m_file); - m_handle = LoadLibraryW (wfile.c_str ()); - - SetDllDirectoryW (nullptr); - - if (! m_handle) - { - DWORD last_error = GetLastError (); - - wchar_t *error_text = nullptr; - FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS, - nullptr, last_error, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - reinterpret_cast (&error_text), 0, nullptr); - - std::ostringstream err_str; - err_str << "opening the library '" << m_file << "' failed (error " - << last_error << "): "; - if (error_text != nullptr) - { - err_str << sys::u8_from_wstring (error_text); - LocalFree (error_text); - } - else - err_str << "Unknown error."; - - (*current_liboctave_error_handler) ("%s", err_str.str ().c_str ()); - } + return (m_search_all_loaded || m_handle != nullptr); } - octave_w32_shlib::~octave_w32_shlib (void) - { - if (m_handle) - FreeLibrary (m_handle); - } +private: + + HINSTANCE m_handle; +}; + +octave_w32_shlib::octave_w32_shlib (const std::string& f) + : dynamic_library::dynlib_rep (f), m_handle (nullptr) +{ + if (f.empty()) + { + m_search_all_loaded = true; + return; + } - void * - octave_w32_shlib::global_search (const std::string& sym_name) - { - void *function = nullptr; + std::string dir = sys::file_ops::dirname (f); + std::wstring wdir = sys::u8_to_wstring (dir); + SetDllDirectoryW (dir.empty () + ? nullptr : wdir.c_str ()); - HANDLE proc = GetCurrentProcess (); + std::wstring wfile = sys::u8_to_wstring (m_file); + m_handle = LoadLibraryW (wfile.c_str ()); - if (! proc) - (*current_liboctave_error_handler) - ("Unable to get handle to own process."); + SetDllDirectoryW (nullptr); + + if (! m_handle) + { + DWORD last_error = GetLastError (); - std::size_t lib_num = 64; - std::size_t size_lib = sizeof (HMODULE); - HMODULE *h_libs; - DWORD bytes_all_libs; - bool got_libs; + wchar_t *error_text = nullptr; + FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, last_error, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast (&error_text), 0, nullptr); - // Get a list of all the libraries in own process. - h_libs = static_cast (malloc (size_lib*lib_num)); - got_libs = EnumProcessModules (proc, h_libs, size_lib*lib_num, - &bytes_all_libs); - int ii = 0; - while (((size_lib*lib_num) < bytes_all_libs) && ii++ < 3) - { - lib_num = bytes_all_libs / size_lib; - h_libs = static_cast (realloc (h_libs, bytes_all_libs)); - got_libs = EnumProcessModules (proc, h_libs, bytes_all_libs, - &bytes_all_libs); - } + std::ostringstream err_str; + err_str << "opening the library '" << m_file << "' failed (error " + << last_error << "): "; + if (error_text != nullptr) + { + err_str << sys::u8_from_wstring (error_text); + LocalFree (error_text); + } + else + err_str << "Unknown error."; + + (*current_liboctave_error_handler) ("%s", err_str.str ().c_str ()); + } +} + +octave_w32_shlib::~octave_w32_shlib (void) +{ + if (m_handle) + FreeLibrary (m_handle); +} + +void * +octave_w32_shlib::global_search (const std::string& sym_name) +{ + void *function = nullptr; + + HANDLE proc = GetCurrentProcess (); - if (got_libs) - { - for (std::size_t i = 0; i < (bytes_all_libs / size_lib); i++) - { - // Check for function in library. - function = reinterpret_cast - (GetProcAddress (h_libs[i], sym_name.c_str ())); + if (! proc) + (*current_liboctave_error_handler) + ("Unable to get handle to own process."); + + std::size_t lib_num = 64; + std::size_t size_lib = sizeof (HMODULE); + HMODULE *h_libs; + DWORD bytes_all_libs; + bool got_libs; - if (function) - break; - } - } + // Get a list of all the libraries in own process. + h_libs = static_cast (malloc (size_lib*lib_num)); + got_libs = EnumProcessModules (proc, h_libs, size_lib*lib_num, + &bytes_all_libs); + int ii = 0; + while (((size_lib*lib_num) < bytes_all_libs) && ii++ < 3) + { + lib_num = bytes_all_libs / size_lib; + h_libs = static_cast (realloc (h_libs, bytes_all_libs)); + got_libs = EnumProcessModules (proc, h_libs, bytes_all_libs, + &bytes_all_libs); + } - // Release the handle to the process. - CloseHandle (proc); - - return function; - } + if (got_libs) + { + for (std::size_t i = 0; i < (bytes_all_libs / size_lib); i++) + { + // Check for function in library. + function = reinterpret_cast + (GetProcAddress (h_libs[i], sym_name.c_str ())); - void * - octave_w32_shlib::search (const std::string& name, - const dynamic_library::name_mangler& mangler) - { - void *function = nullptr; + if (function) + break; + } + } + + // Release the handle to the process. + CloseHandle (proc); - if (! m_search_all_loaded && ! is_open ()) - (*current_liboctave_error_handler) - ("shared library %s is not open", m_file.c_str ()); + return function; +} - std::string sym_name = name; +void * +octave_w32_shlib::search (const std::string& name, + const dynamic_library::name_mangler& mangler) +{ + void *function = nullptr; - if (mangler) - sym_name = mangler (name); + if (! m_search_all_loaded && ! is_open ()) + (*current_liboctave_error_handler) + ("shared library %s is not open", m_file.c_str ()); + + std::string sym_name = name; + + if (mangler) + sym_name = mangler (name); - if (m_search_all_loaded) - function = global_search (sym_name); - else - function = reinterpret_cast (GetProcAddress (m_handle, - sym_name.c_str ())); + if (m_search_all_loaded) + function = global_search (sym_name); + else + function = reinterpret_cast (GetProcAddress (m_handle, + sym_name.c_str ())); - return function; - } + return function; +} #endif - dynamic_library::dynlib_rep * - dynamic_library::dynlib_rep::new_instance (const std::string& f) - { +dynamic_library::dynlib_rep * +dynamic_library::dynlib_rep::new_instance (const std::string& f) +{ #if defined (HAVE_DLOPEN_API) - return new octave_dlopen_shlib (f); + return new octave_dlopen_shlib (f); #elif defined (HAVE_LOADLIBRARY_API) - return new octave_w32_shlib (f); + return new octave_w32_shlib (f); #else - (*current_liboctave_error_handler) - ("support for dynamically loaded libraries was unavailable or disabled when liboctave was built"); + (*current_liboctave_error_handler) + ("support for dynamically loaded libraries was unavailable or disabled when liboctave was built"); #endif - } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-shlib.h --- a/liboctave/util/oct-shlib.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-shlib.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,179 +38,179 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - dynamic_library - { - public: // FIXME: make this class private? - - typedef std::function name_mangler; +class +dynamic_library +{ +public: // FIXME: make this class private? - class dynlib_rep - { - public: + typedef std::function name_mangler; - dynlib_rep (void) - : m_count (1), m_fcn_names (), m_file (), m_time_loaded (OCTAVE_TIME_T ()), - m_search_all_loaded (false) - { } - - protected: + class dynlib_rep + { + public: - OCTAVE_API - dynlib_rep (const std::string& f); - - public: + dynlib_rep (void) + : m_count (1), m_fcn_names (), m_file (), m_time_loaded (OCTAVE_TIME_T ()), + m_search_all_loaded (false) + { } - virtual ~dynlib_rep (void) - { - s_instances.erase (m_file); - } + protected: - virtual bool is_open (void) const - { return false; } + OCTAVE_API + dynlib_rep (const std::string& f); + + public: - virtual void * search (const std::string&, - const name_mangler& = name_mangler ()) - { return nullptr; } - - OCTAVE_API bool is_out_of_date (void) const; - - // This method will be overridden conditionally. - static OCTAVE_API dynlib_rep * new_instance (const std::string& f); + virtual ~dynlib_rep (void) + { + s_instances.erase (m_file); + } - static OCTAVE_API dynlib_rep * get_instance (const std::string& f, bool fake); - - sys::time time_loaded (void) const - { return m_time_loaded; } + virtual bool is_open (void) const + { return false; } - std::string file_name (void) const - { return m_file; } - - std::size_t num_fcn_names (void) const { return m_fcn_names.size (); } + virtual void * search (const std::string&, + const name_mangler& = name_mangler ()) + { return nullptr; } - OCTAVE_API std::list function_names (void) const; - - OCTAVE_API void add_fcn_name (const std::string&); + OCTAVE_API bool is_out_of_date (void) const; - OCTAVE_API bool remove_fcn_name (const std::string&); + // This method will be overridden conditionally. + static OCTAVE_API dynlib_rep * new_instance (const std::string& f); - void clear_fcn_names (void) { m_fcn_names.clear (); } - - public: + static OCTAVE_API dynlib_rep * get_instance (const std::string& f, bool fake); - refcount m_count; - - protected: + sys::time time_loaded (void) const + { return m_time_loaded; } - OCTAVE_API void fake_reload (void); + std::string file_name (void) const + { return m_file; } - static OCTAVE_API std::map s_instances; + std::size_t num_fcn_names (void) const { return m_fcn_names.size (); } - // Set of hooked function names. - typedef std::map::iterator fcn_names_iterator; - typedef std::map::const_iterator fcn_names_const_iterator; + OCTAVE_API std::list function_names (void) const; + + OCTAVE_API void add_fcn_name (const std::string&); - std::map m_fcn_names; - std::string m_file; - sys::time m_time_loaded; - bool m_search_all_loaded; - }; + OCTAVE_API bool remove_fcn_name (const std::string&); - private: - - static OCTAVE_API dynlib_rep s_nil_rep; + void clear_fcn_names (void) { m_fcn_names.clear (); } public: - dynamic_library (void) : m_rep (&s_nil_rep) { m_rep->m_count++; } - - dynamic_library (const std::string& f, bool fake = true) - : m_rep (dynlib_rep::get_instance (f, fake)) { } + refcount m_count; - ~dynamic_library (void) - { - if (--m_rep->m_count == 0 && m_rep != &s_nil_rep) - delete m_rep; - } - - OCTAVE_API void delete_later (void); - - dynamic_library (const dynamic_library& sl) - : m_rep (sl.m_rep) - { - m_rep->m_count++; - } + protected: - dynamic_library& operator = (const dynamic_library& sl) - { - if (m_rep != sl.m_rep) - { - if (--m_rep->m_count == 0 && m_rep != &s_nil_rep) - delete m_rep; - - m_rep = sl.m_rep; - m_rep->m_count++; - } + OCTAVE_API void fake_reload (void); - return *this; - } - - bool operator == (const dynamic_library& sl) const - { return (m_rep == sl.m_rep); } - - operator bool () const { return m_rep->is_open (); } - - void open (const std::string& f) - { *this = dynamic_library (f); } + static OCTAVE_API std::map s_instances; - std::list close (void) - { - std::list removed_fcns = m_rep->function_names (); - - m_rep->clear_fcn_names (); - - *this = dynamic_library (); - - return removed_fcns; - } - - void * search (const std::string& nm, - const name_mangler& mangler = name_mangler ()) const - { - void *f = m_rep->search (nm, mangler); - if (f) - m_rep->add_fcn_name (nm); - - return f; - } + // Set of hooked function names. + typedef std::map::iterator fcn_names_iterator; + typedef std::map::const_iterator fcn_names_const_iterator; - void add (const std::string& name) - { m_rep->add_fcn_name (name); } - - bool remove (const std::string& name) - { return m_rep->remove_fcn_name (name); } - - std::size_t number_of_functions_loaded (void) const - { return m_rep->num_fcn_names (); } - - bool is_out_of_date (void) const - { return m_rep->is_out_of_date (); } - - std::string file_name (void) const - { return m_rep->file_name (); } - - sys::time time_loaded (void) const - { return m_rep->time_loaded (); } - - private: - - dynlib_rep *m_rep; + std::map m_fcn_names; + std::string m_file; + sys::time m_time_loaded; + bool m_search_all_loaded; }; - // FIXME: Currently must return int so that it may be used as an - // event_hook function. +private: + + static OCTAVE_API dynlib_rep s_nil_rep; + +public: + + dynamic_library (void) : m_rep (&s_nil_rep) { m_rep->m_count++; } + + dynamic_library (const std::string& f, bool fake = true) + : m_rep (dynlib_rep::get_instance (f, fake)) { } + + ~dynamic_library (void) + { + if (--m_rep->m_count == 0 && m_rep != &s_nil_rep) + delete m_rep; + } + + OCTAVE_API void delete_later (void); + + dynamic_library (const dynamic_library& sl) + : m_rep (sl.m_rep) + { + m_rep->m_count++; + } + + dynamic_library& operator = (const dynamic_library& sl) + { + if (m_rep != sl.m_rep) + { + if (--m_rep->m_count == 0 && m_rep != &s_nil_rep) + delete m_rep; + + m_rep = sl.m_rep; + m_rep->m_count++; + } + + return *this; + } + + bool operator == (const dynamic_library& sl) const + { return (m_rep == sl.m_rep); } + + operator bool () const { return m_rep->is_open (); } + + void open (const std::string& f) + { *this = dynamic_library (f); } - OCTAVE_API int release_unreferenced_dynamic_libraries (void); + std::list close (void) + { + std::list removed_fcns = m_rep->function_names (); + + m_rep->clear_fcn_names (); + + *this = dynamic_library (); + + return removed_fcns; + } + + void * search (const std::string& nm, + const name_mangler& mangler = name_mangler ()) const + { + void *f = m_rep->search (nm, mangler); + if (f) + m_rep->add_fcn_name (nm); + + return f; + } + + void add (const std::string& name) + { m_rep->add_fcn_name (name); } + + bool remove (const std::string& name) + { return m_rep->remove_fcn_name (name); } + + std::size_t number_of_functions_loaded (void) const + { return m_rep->num_fcn_names (); } + + bool is_out_of_date (void) const + { return m_rep->is_out_of_date (); } + + std::string file_name (void) const + { return m_rep->file_name (); } + + sys::time time_loaded (void) const + { return m_rep->time_loaded (); } + +private: + + dynlib_rep *m_rep; +}; + +// FIXME: Currently must return int so that it may be used as an +// event_hook function. + +OCTAVE_API int release_unreferenced_dynamic_libraries (void); OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-sparse.cc --- a/liboctave/util/oct-sparse.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-sparse.cc Thu Dec 01 20:05:44 2022 -0800 @@ -36,48 +36,48 @@ OCTAVE_BEGIN_NAMESPACE(octave) - static inline void - check_suitesparse_integer_size (void) - { - // FIXME: maybe it would be better to make this a configure check and - // disable suitesparse if it fails? +static inline void +check_suitesparse_integer_size (void) +{ + // FIXME: maybe it would be better to make this a configure check and + // disable suitesparse if it fails? - if (sizeof (suitesparse_integer) != sizeof (octave_idx_type)) - (*current_liboctave_error_handler) - ("size of suitesparse integer does not match octave_idx_type!"); - } + if (sizeof (suitesparse_integer) != sizeof (octave_idx_type)) + (*current_liboctave_error_handler) + ("size of suitesparse integer does not match octave_idx_type!"); +} - suitesparse_integer * - to_suitesparse_intptr (octave_idx_type *i) - { - check_suitesparse_integer_size (); +suitesparse_integer * +to_suitesparse_intptr (octave_idx_type *i) +{ + check_suitesparse_integer_size (); - return reinterpret_cast (i); - } + return reinterpret_cast (i); +} - const suitesparse_integer * - to_suitesparse_intptr (const octave_idx_type *i) - { - check_suitesparse_integer_size (); +const suitesparse_integer * +to_suitesparse_intptr (const octave_idx_type *i) +{ + check_suitesparse_integer_size (); - return reinterpret_cast (i); - } + return reinterpret_cast (i); +} - octave_idx_type * - to_octave_idx_type_ptr (suitesparse_integer *i) - { - check_suitesparse_integer_size (); +octave_idx_type * +to_octave_idx_type_ptr (suitesparse_integer *i) +{ + check_suitesparse_integer_size (); - return reinterpret_cast (i); - } + return reinterpret_cast (i); +} - const octave_idx_type * - to_octave_idx_type_ptr (const suitesparse_integer *i) - { - check_suitesparse_integer_size (); +const octave_idx_type * +to_octave_idx_type_ptr (const suitesparse_integer *i) +{ + check_suitesparse_integer_size (); - return reinterpret_cast (i); - } + return reinterpret_cast (i); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-sparse.h --- a/liboctave/util/oct-sparse.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-sparse.h Thu Dec 01 20:05:44 2022 -0800 @@ -168,44 +168,44 @@ OCTAVE_BEGIN_NAMESPACE(octave) # if defined (OCTAVE_ENABLE_64) - typedef SuiteSparse_long suitesparse_integer; +typedef SuiteSparse_long suitesparse_integer; # else - typedef int suitesparse_integer; +typedef int suitesparse_integer; # endif - extern OCTAVE_API suitesparse_integer * - to_suitesparse_intptr (octave_idx_type *i); +extern OCTAVE_API suitesparse_integer * +to_suitesparse_intptr (octave_idx_type *i); - extern const OCTAVE_API suitesparse_integer * - to_suitesparse_intptr (const octave_idx_type *i); +extern const OCTAVE_API suitesparse_integer * +to_suitesparse_intptr (const octave_idx_type *i); - extern OCTAVE_API octave_idx_type * - to_octave_idx_type_ptr (suitesparse_integer *i); +extern OCTAVE_API octave_idx_type * +to_octave_idx_type_ptr (suitesparse_integer *i); - extern const OCTAVE_API octave_idx_type * - to_octave_idx_type_ptr (const suitesparse_integer *i); +extern const OCTAVE_API octave_idx_type * +to_octave_idx_type_ptr (const suitesparse_integer *i); - inline octave_idx_type - from_suitesparse_long (SuiteSparse_long x) - { - if (x < std::numeric_limits::min () - || x > std::numeric_limits::max ()) - (*current_liboctave_error_handler) - ("integer dimension or index out of range for Octave's indexing type"); +inline octave_idx_type +from_suitesparse_long (SuiteSparse_long x) +{ + if (x < std::numeric_limits::min () + || x > std::numeric_limits::max ()) + (*current_liboctave_error_handler) + ("integer dimension or index out of range for Octave's indexing type"); - return static_cast (x); - } + return static_cast (x); +} - inline octave_idx_type - from_size_t (std::size_t x) - { - // std::size_t is guaranteed to be unsigned - if (x > std::numeric_limits::max ()) - (*current_liboctave_error_handler) - ("integer dimension or index out of range for Octave's index type"); +inline octave_idx_type +from_size_t (std::size_t x) +{ + // std::size_t is guaranteed to be unsigned + if (x > std::numeric_limits::max ()) + (*current_liboctave_error_handler) + ("integer dimension or index out of range for Octave's index type"); - return static_cast (x); - } + return static_cast (x); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/oct-string.h --- a/liboctave/util/oct-string.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/oct-string.h Thu Dec 01 20:05:44 2022 -0800 @@ -34,216 +34,216 @@ OCTAVE_BEGIN_NAMESPACE(octave) - //! Octave string utility functions. - //! - //! This functions provide a C++ interface to most string functions - //! available in the Octave interpreter. - //! - //! Specializations for Array may consider its dimensions in addition - //! to the actual string contents. - //! - //! @attention - //! Octave's string comparison functions return true when strings are - //! are equal, just the opposite of the corresponding C library functions. - //! In addition, Octave's function only return bool and do not check - //! lexicographical order. +//! Octave string utility functions. +//! +//! This functions provide a C++ interface to most string functions +//! available in the Octave interpreter. +//! +//! Specializations for Array may consider its dimensions in addition +//! to the actual string contents. +//! +//! @attention +//! Octave's string comparison functions return true when strings are +//! are equal, just the opposite of the corresponding C library functions. +//! In addition, Octave's function only return bool and do not check +//! lexicographical order. OCTAVE_BEGIN_NAMESPACE(string) - //! True if strings are the same. - //! - //! ## Specialization for Array - //! - //! When comparing whole Array of chars, the actual Array dimensions - //! are significant. A column vector and row vector with the same - //! char array, will still return false. +//! True if strings are the same. +//! +//! ## Specialization for Array +//! +//! When comparing whole Array of chars, the actual Array dimensions +//! are significant. A column vector and row vector with the same +//! char array, will still return false. - template - OCTAVE_API bool - strcmp (const T& str_a, const T& str_b); +template +OCTAVE_API bool +strcmp (const T& str_a, const T& str_b); - //! True if string is the same as character sequence. - //! - //! Compares a string to the null-terminated character sequence - //! beginning at the character pointed to by str_b. - //! - //! ## Specialization for Array - //! - //! For purposes of comparison of dimensions, the character sequence - //! is considered to be a row vector. +//! True if string is the same as character sequence. +//! +//! Compares a string to the null-terminated character sequence +//! beginning at the character pointed to by str_b. +//! +//! ## Specialization for Array +//! +//! For purposes of comparison of dimensions, the character sequence +//! is considered to be a row vector. - template - OCTAVE_API bool - strcmp (const T& str_a, const typename T::value_type *str_b); +template +OCTAVE_API bool +strcmp (const T& str_a, const typename T::value_type *str_b); - //! True if strings are the same, ignoring case. - //! - //! ## Specialization for Array - //! - //! When comparing whole Array of chars, the actual Array dimensions - //! are significant. A column vector and row vector with the same - //! char array, will still return false. +//! True if strings are the same, ignoring case. +//! +//! ## Specialization for Array +//! +//! When comparing whole Array of chars, the actual Array dimensions +//! are significant. A column vector and row vector with the same +//! char array, will still return false. - template - OCTAVE_API bool - strcmpi (const T& str_a, const T& str_b); +template +OCTAVE_API bool +strcmpi (const T& str_a, const T& str_b); - //! True if string is the same as character sequence, ignoring case. - //! - //! ## Specialization for Array - //! - //! For purposes of comparison of dimensions, the character sequence - //! is considered to be a row vector. +//! True if string is the same as character sequence, ignoring case. +//! +//! ## Specialization for Array +//! +//! For purposes of comparison of dimensions, the character sequence +//! is considered to be a row vector. - template - OCTAVE_API bool - strcmpi (const T& str_a, const typename T::value_type *str_b); +template +OCTAVE_API bool +strcmpi (const T& str_a, const typename T::value_type *str_b); - //! True if the first N characters are the same. - //! - //! ## Specialization for Array - //! - //! The comparison is done in the first N characters, the actual - //! dimensions of the Array are irrelevant. A row vector and - //! a column vector of the same still return true. +//! True if the first N characters are the same. +//! +//! ## Specialization for Array +//! +//! The comparison is done in the first N characters, the actual +//! dimensions of the Array are irrelevant. A row vector and +//! a column vector of the same still return true. - template - OCTAVE_API bool - strncmp (const T& str_a, const T& str_b, - const typename T::size_type n); +template +OCTAVE_API bool +strncmp (const T& str_a, const T& str_b, + const typename T::size_type n); - //! True if the first N characters are the same. - template - OCTAVE_API bool - strncmp (const T& str_a, const typename T::value_type *str_b, - const typename T::size_type n); +//! True if the first N characters are the same. +template +OCTAVE_API bool +strncmp (const T& str_a, const typename T::value_type *str_b, + const typename T::size_type n); - //! True if the first N characters are the same, ignoring case. - //! - //! ## Specialization for Array - //! - //! The comparison is done in the first N characters, the actual - //! dimensions of the Array are irrelevant. A row vector and - //! a column vector of the same still return true. +//! True if the first N characters are the same, ignoring case. +//! +//! ## Specialization for Array +//! +//! The comparison is done in the first N characters, the actual +//! dimensions of the Array are irrelevant. A row vector and +//! a column vector of the same still return true. - template - OCTAVE_API bool - strncmpi (const T& str_a, const T& str_b, - const typename T::size_type n); +template +OCTAVE_API bool +strncmpi (const T& str_a, const T& str_b, + const typename T::size_type n); - //! True if the first N characters are the same, ignoring case. - template - OCTAVE_API bool - strncmpi (const T& str_a, const typename T::value_type *str_b, - const typename T::size_type n); +//! True if the first N characters are the same, ignoring case. +template +OCTAVE_API bool +strncmpi (const T& str_a, const typename T::value_type *str_b, + const typename T::size_type n); - extern OCTAVE_API Complex - str2double (const std::string& str_arg); +extern OCTAVE_API Complex +str2double (const std::string& str_arg); - extern OCTAVE_API std::string - u8_to_encoding (const std::string& who, const std::string& u8_string, - const std::string& encoding); +extern OCTAVE_API std::string +u8_to_encoding (const std::string& who, const std::string& u8_string, + const std::string& encoding); - extern OCTAVE_API std::string - u8_from_encoding (const std::string& who, const std::string& native_string, - const std::string& encoding); +extern OCTAVE_API std::string +u8_from_encoding (const std::string& who, const std::string& native_string, + const std::string& encoding); - enum u8_fallback_type - { - U8_REPLACEMENT_CHAR, - U8_ISO_8859_1 - }; +enum u8_fallback_type +{ + U8_REPLACEMENT_CHAR, + U8_ISO_8859_1 +}; - extern OCTAVE_API unsigned int - u8_validate (const std::string& who, std::string& in_string, - const u8_fallback_type type = U8_REPLACEMENT_CHAR); +extern OCTAVE_API unsigned int +u8_validate (const std::string& who, std::string& in_string, + const u8_fallback_type type = U8_REPLACEMENT_CHAR); - template - struct - deletable_facet : Facet - { - template - deletable_facet (Args&& ...args) - : Facet (std::forward (args)...) - { } +template +struct + deletable_facet : Facet +{ + template + deletable_facet (Args&& ...args) + : Facet (std::forward (args)...) + { } - // destructor needs to be public - ~deletable_facet () {} - }; + // destructor needs to be public + ~deletable_facet () { } +}; - class - OCTAVE_API - codecvt_u8 : public std::codecvt - { - public: +class +OCTAVE_API +codecvt_u8 : public std::codecvt +{ +public: - // No copying! + // No copying! - codecvt_u8 (codecvt_u8 &) = delete; + codecvt_u8 (codecvt_u8&) = delete; - codecvt_u8& operator = (codecvt_u8 &) = delete; + codecvt_u8& operator = (codecvt_u8&) = delete; - codecvt_u8 (const std::string &enc) - : m_enc (enc) - { } + codecvt_u8 (const std::string& enc) + : m_enc (enc) + { } - virtual ~codecvt_u8 () { } + virtual ~codecvt_u8 () { } - typedef char InternT; - typedef char ExternT; - typedef std::mbstate_t StateT; + typedef char InternT; + typedef char ExternT; + typedef std::mbstate_t StateT; - private: +private: - OCTAVE_API - typename std::codecvt::result - do_out (StateT& state, - const InternT* from, const InternT* from_end, const InternT*& from_next, - ExternT* to, ExternT* to_end, ExternT*& to_next) const; + OCTAVE_API + typename std::codecvt::result + do_out (StateT& state, + const InternT *from, const InternT *from_end, const InternT *&from_next, + ExternT *to, ExternT *to_end, ExternT *&to_next) const; - OCTAVE_API - typename std::codecvt::result - do_in (StateT& state, - const ExternT* from, const ExternT* from_end, const ExternT*& from_next, - InternT* to, InternT* to_end, InternT*& to_next) const; + OCTAVE_API + typename std::codecvt::result + do_in (StateT& state, + const ExternT *from, const ExternT *from_end, const ExternT *&from_next, + InternT *to, InternT *to_end, InternT *&to_next) const; - typename std::codecvt::result - do_unshift (StateT& /* state */, ExternT* to, ExternT* /* to_end */, - ExternT*& to_next) const - { - // FIXME: What is the correct thing to unshift? - // Just reset? - to_next = to; + typename std::codecvt::result + do_unshift (StateT& /* state */, ExternT *to, ExternT * /* to_end */, + ExternT *&to_next) const + { + // FIXME: What is the correct thing to unshift? + // Just reset? + to_next = to; - return std::codecvt::ok; - } + return std::codecvt::ok; + } - int do_encoding () const throw () - { - // return 0 because UTF-8 encoding is variable length - return 0; - } + int do_encoding () const throw () + { + // return 0 because UTF-8 encoding is variable length + return 0; + } - bool do_always_noconv () const throw () - { - // return false to indicate non-identity conversion - return false; - } + bool do_always_noconv () const throw () + { + // return false to indicate non-identity conversion + return false; + } - OCTAVE_API int - do_length (StateT& state, const ExternT *src, const ExternT *end, - std::size_t max) const; + OCTAVE_API int + do_length (StateT& state, const ExternT *src, const ExternT *end, + std::size_t max) const; - int do_max_length() const throw () - { - // For UTF-8, a maximum of 4 bytes are needed for one character. - return 4; - } + int do_max_length() const throw () + { + // For UTF-8, a maximum of 4 bytes are needed for one character. + return 4; + } - std::string m_enc; + std::string m_enc; - }; +}; OCTAVE_END_NAMESPACE(string) OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/octave-preserve-stream-state.h --- a/liboctave/util/octave-preserve-stream-state.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/octave-preserve-stream-state.h Thu Dec 01 20:05:44 2022 -0800 @@ -32,32 +32,32 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - preserve_stream_state - { - public: +class +preserve_stream_state +{ +public: - preserve_stream_state (std::ios& s) - : m_stream (s), m_oflags (s.flags ()), m_oprecision (s.precision ()), - m_owidth (s.width ()), m_ofill (s.fill ()) - { } + preserve_stream_state (std::ios& s) + : m_stream (s), m_oflags (s.flags ()), m_oprecision (s.precision ()), + m_owidth (s.width ()), m_ofill (s.fill ()) + { } - ~preserve_stream_state (void) - { - m_stream.flags (m_oflags); - m_stream.precision (m_oprecision); - m_stream.width (m_owidth); - m_stream.fill (m_ofill); - } + ~preserve_stream_state (void) + { + m_stream.flags (m_oflags); + m_stream.precision (m_oprecision); + m_stream.width (m_owidth); + m_stream.fill (m_ofill); + } - private: +private: - std::ios& m_stream; - std::ios::fmtflags m_oflags; - std::streamsize m_oprecision; - int m_owidth; - char m_ofill; - }; + std::ios& m_stream; + std::ios::fmtflags m_oflags; + std::streamsize m_oprecision; + int m_owidth; + char m_ofill; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/pathsearch.cc --- a/liboctave/util/pathsearch.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/pathsearch.cc Thu Dec 01 20:05:44 2022 -0800 @@ -39,94 +39,94 @@ OCTAVE_BEGIN_NAMESPACE(octave) - directory_path::directory_path (const std::string& s) - : m_orig_path (s), m_initialized (false), m_expanded_path (), - m_path_elements () - { - if (! m_orig_path.empty ()) - init (); - } +directory_path::directory_path (const std::string& s) + : m_orig_path (s), m_initialized (false), m_expanded_path (), + m_path_elements () +{ + if (! m_orig_path.empty ()) + init (); +} - std::list directory_path::elements (void) - { - return m_initialized ? m_path_elements : std::list (); - } +std::list directory_path::elements (void) +{ + return m_initialized ? m_path_elements : std::list (); +} - std::list directory_path::all_directories (void) - { - std::list retval; +std::list directory_path::all_directories (void) +{ + std::list retval; - if (m_initialized) - { - for (const auto& elt : m_path_elements) - { - std::string elt_dir = kpse_element_dir (elt); + if (m_initialized) + { + for (const auto& elt : m_path_elements) + { + std::string elt_dir = kpse_element_dir (elt); - if (! elt_dir.empty ()) - retval.push_back (elt_dir); - } - } + if (! elt_dir.empty ()) + retval.push_back (elt_dir); + } + } - return retval; - } + return retval; +} - std::string directory_path::find_first (const std::string& nm) - { - return m_initialized ? kpse_path_search (m_expanded_path, nm) : ""; - } +std::string directory_path::find_first (const std::string& nm) +{ + return m_initialized ? kpse_path_search (m_expanded_path, nm) : ""; +} - std::list directory_path::find_all (const std::string& nm) - { - return (m_initialized - ? kpse_all_path_search (m_expanded_path, nm) - : std::list ()); - } +std::list directory_path::find_all (const std::string& nm) +{ + return (m_initialized + ? kpse_all_path_search (m_expanded_path, nm) + : std::list ()); +} - std::string - directory_path::find_first_of (const std::list& names) - { - return (m_initialized - ? kpse_path_find_first_of (m_expanded_path, names) : ""); - } +std::string +directory_path::find_first_of (const std::list& names) +{ + return (m_initialized + ? kpse_path_find_first_of (m_expanded_path, names) : ""); +} - std::list - directory_path::find_all_first_of (const std::list& names) - { - return (m_initialized - ? kpse_all_path_find_first_of (m_expanded_path, names) - : std::list ()); - } +std::list +directory_path::find_all_first_of (const std::list& names) +{ + return (m_initialized + ? kpse_all_path_find_first_of (m_expanded_path, names) + : std::list ()); +} - void directory_path::init (void) - { - static bool octave_kpse_initialized = false; +void directory_path::init (void) +{ + static bool octave_kpse_initialized = false; - if (! octave_kpse_initialized) - { - std::string val = sys::env::getenv ("KPATHSEA_DEBUG"); + if (! octave_kpse_initialized) + { + std::string val = sys::env::getenv ("KPATHSEA_DEBUG"); - if (! val.empty ()) - kpse_debug |= atoi (val.c_str ()); + if (! val.empty ()) + kpse_debug |= atoi (val.c_str ()); - octave_kpse_initialized = true; - } + octave_kpse_initialized = true; + } - m_expanded_path = kpse_path_expand (m_orig_path); + m_expanded_path = kpse_path_expand (m_orig_path); - for (kpse_path_iterator pi (m_expanded_path); pi != std::string::npos; pi++) - m_path_elements.push_back (*pi); + for (kpse_path_iterator pi (m_expanded_path); pi != std::string::npos; pi++) + m_path_elements.push_back (*pi); - m_initialized = true; - } + m_initialized = true; +} - char directory_path::path_sep_char (void) - { - return SEPCHAR; - } +char directory_path::path_sep_char (void) +{ + return SEPCHAR; +} - std::string directory_path::path_sep_str (void) - { - return SEPCHAR_STR; - } +std::string directory_path::path_sep_str (void) +{ + return SEPCHAR_STR; +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/pathsearch.h --- a/liboctave/util/pathsearch.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/pathsearch.h Thu Dec 01 20:05:44 2022 -0800 @@ -33,73 +33,73 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTAVE_API - directory_path - { - public: +class +OCTAVE_API +directory_path +{ +public: - directory_path (const std::string& s = ""); + directory_path (const std::string& s = ""); - directory_path (const directory_path&) = default; + directory_path (const directory_path&) = default; - directory_path& operator = (const directory_path&) = default; + directory_path& operator = (const directory_path&) = default; - ~directory_path (void) = default; + ~directory_path (void) = default; - void set (const std::string& s) - { - m_initialized = false; - m_orig_path = s; - init (); - } + void set (const std::string& s) + { + m_initialized = false; + m_orig_path = s; + init (); + } - std::list elements (void); + std::list elements (void); - std::list all_directories (void); + std::list all_directories (void); - std::string find_first (const std::string&); + std::string find_first (const std::string&); - std::string find (const std::string& nm) { return find_first (nm); } + std::string find (const std::string& nm) { return find_first (nm); } - std::list find_all (const std::string&); + std::list find_all (const std::string&); - std::string find_first_of (const std::list& names); + std::string find_first_of (const std::list& names); - std::list - find_all_first_of (const std::list& names); + std::list + find_all_first_of (const std::list& names); - void rehash (void) - { - m_initialized = false; - init (); - } + void rehash (void) + { + m_initialized = false; + init (); + } - static char path_sep_char (void); + static char path_sep_char (void); - // static void path_sep_char (char c); + // static void path_sep_char (char c); - static std::string path_sep_str (void); + static std::string path_sep_str (void); - static bool is_path_sep (char c) { return c == path_sep_char (); } + static bool is_path_sep (char c) { return c == path_sep_char (); } - private: +private: - // The colon separated list that we were given. - std::string m_orig_path; + // The colon separated list that we were given. + std::string m_orig_path; - // TRUE means we've unpacked the path p. - bool m_initialized; + // TRUE means we've unpacked the path p. + bool m_initialized; - // A version of the colon separate list on which we have performed - // tilde, variable, and possibly default path expansion. - std::string m_expanded_path; + // A version of the colon separate list on which we have performed + // tilde, variable, and possibly default path expansion. + std::string m_expanded_path; - // The elements of the list. - std::list m_path_elements; + // The elements of the list. + std::list m_path_elements; - void init (void); - }; + void init (void); +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/quit.cc --- a/liboctave/util/quit.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/quit.cc Thu Dec 01 20:05:44 2022 -0800 @@ -44,56 +44,56 @@ OCTAVE_BEGIN_NAMESPACE(octave) - std::string execution_exception::stack_trace (void) const - { - std::size_t nframes = m_stack_info.size (); +std::string execution_exception::stack_trace (void) const +{ + std::size_t nframes = m_stack_info.size (); - if (nframes == 0) - return std::string (); + if (nframes == 0) + return std::string (); - std::ostringstream buf; + std::ostringstream buf; - buf << "error: called from\n"; + buf << "error: called from\n"; - for (const auto& frm : m_stack_info) - { - buf << " " << frm.fcn_name (); + for (const auto& frm : m_stack_info) + { + buf << " " << frm.fcn_name (); - int line = frm.line (); + int line = frm.line (); - if (line > 0) - { - buf << " at line " << line; + if (line > 0) + { + buf << " at line " << line; - int column = frm.column (); + int column = frm.column (); - if (column > 0) - buf << " column " << column; - } + if (column > 0) + buf << " column " << column; + } - buf << "\n"; - } + buf << "\n"; + } - return buf.str (); - } + return buf.str (); +} - void execution_exception::display (std::ostream& os) const - { - if (! m_message.empty ()) - { - os << m_err_type << ": " << m_message; +void execution_exception::display (std::ostream& os) const +{ + if (! m_message.empty ()) + { + os << m_err_type << ": " << m_message; - if (m_message.back () != '\n') - { - os << "\n"; + if (m_message.back () != '\n') + { + os << "\n"; - std::string st = stack_trace (); + std::string st = stack_trace (); - if (! st.empty ()) - os << st; - } - } - } + if (! st.empty ()) + os << st; + } + } +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/quit.h --- a/liboctave/util/quit.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/quit.h Thu Dec 01 20:05:44 2022 -0800 @@ -44,162 +44,162 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class frame_info - { - public: +class frame_info +{ +public: + + frame_info (void) = default; - frame_info (void) = default; + frame_info (const std::string& file_name, const std::string& fcn_name, + int line, int column) + : m_file_name (file_name), m_fcn_name (fcn_name), m_line (line), + m_column (column) + { } + + frame_info (const frame_info&) = default; + + frame_info& operator = (const frame_info&) = default; - frame_info (const std::string& file_name, const std::string& fcn_name, - int line, int column) - : m_file_name (file_name), m_fcn_name (fcn_name), m_line (line), - m_column (column) - { } + ~frame_info (void) = default; + + std::string file_name (void) const { return m_file_name; } - frame_info (const frame_info&) = default; + std::string fcn_name (void) const { return m_fcn_name; } + + int line (void) const { return m_line; } - frame_info& operator = (const frame_info&) = default; + int column (void) const { return m_column; } - ~frame_info (void) = default; +private: - std::string file_name (void) const { return m_file_name; } + std::string m_file_name; - std::string fcn_name (void) const { return m_fcn_name; } + std::string m_fcn_name; + + int m_line; - int line (void) const { return m_line; } - - int column (void) const { return m_column; } + int m_column; +}; - private: +inline bool operator == (const frame_info& a, const frame_info& b) +{ + return (a.file_name () == b.file_name () + && a.fcn_name () == b.fcn_name () + && a.line () == b.line () + && a.column () == b.column ()); +} - std::string m_file_name; +class OCTAVE_EXCEPTION_API execution_exception : public std::runtime_error +{ +public: - std::string m_fcn_name; + typedef std::list stack_info_type; - int m_line; - - int m_column; - }; + execution_exception (const std::string& err_type = "error", + const std::string& id = "", + const std::string& message = "unspecified error", + const stack_info_type& stack_info = stack_info_type ()) + : runtime_error (message), m_err_type (err_type), m_id (id), + m_message (message), m_stack_info (stack_info) + { } - inline bool operator == (const frame_info& a, const frame_info& b) + execution_exception (const execution_exception&) = default; + + execution_exception& operator = (const execution_exception&) = default; + + ~execution_exception (void) = default; + + void set_err_type (const std::string& et) { - return (a.file_name () == b.file_name () - && a.fcn_name () == b.fcn_name () - && a.line () == b.line () - && a.column () == b.column ()); + m_err_type = et; } - class OCTAVE_EXCEPTION_API execution_exception : public std::runtime_error + std::string err_type (void) const { return m_err_type; } + + virtual std::string stack_trace (void) const; + + void set_identifier (const std::string& id) { - public: - - typedef std::list stack_info_type; + m_id = id; + } - execution_exception (const std::string& err_type = "error", - const std::string& id = "", - const std::string& message = "unspecified error", - const stack_info_type& stack_info = stack_info_type ()) - : runtime_error (message), m_err_type (err_type), m_id (id), - m_message (message), m_stack_info (stack_info) - { } - - execution_exception (const execution_exception&) = default; + virtual std::string identifier (void) const { return m_id; } - execution_exception& operator = (const execution_exception&) = default; - - ~execution_exception (void) = default; + void set_message (const std::string& msg) + { + m_message = msg; + } - void set_err_type (const std::string& et) - { - m_err_type = et; - } - - std::string err_type (void) const { return m_err_type; } + std::string message (void) const { return m_message; } - virtual std::string stack_trace (void) const; - - void set_identifier (const std::string& id) - { - m_id = id; - } + // Provided for std::exception interface. + const char * what (void) const noexcept { return m_message.c_str (); } - virtual std::string identifier (void) const { return m_id; } - - void set_message (const std::string& msg) - { - m_message = msg; - } + virtual stack_info_type stack_info (void) const + { + return m_stack_info; + } - std::string message (void) const { return m_message; } + void set_stack_info (const stack_info_type& stack_info) + { + m_stack_info = stack_info; + } - // Provided for std::exception interface. - const char * what (void) const noexcept { return m_message.c_str (); } + virtual void display (std::ostream& os) const; - virtual stack_info_type stack_info (void) const - { - return m_stack_info; - } +private: + + std::string m_err_type; - void set_stack_info (const stack_info_type& stack_info) - { - m_stack_info = stack_info; - } + std::string m_id; + + std::string m_message; - virtual void display (std::ostream& os) const; - - private: - - std::string m_err_type; + stack_info_type m_stack_info; +}; - std::string m_id; - - std::string m_message; - - stack_info_type m_stack_info; - }; +class OCTAVE_EXCEPTION_API exit_exception : public std::exception +{ +public: - class OCTAVE_EXCEPTION_API exit_exception : public std::exception - { - public: + exit_exception (int exit_status = 0, bool safe_to_return = false) + : std::exception (), m_exit_status (exit_status), + m_safe_to_return (safe_to_return) + { } + + exit_exception (const exit_exception&) = default; - exit_exception (int exit_status = 0, bool safe_to_return = false) - : std::exception (), m_exit_status (exit_status), - m_safe_to_return (safe_to_return) - { } + exit_exception& operator = (exit_exception&) = default; + + ~exit_exception (void) = default; - exit_exception (const exit_exception&) = default; + const char * what (void) const noexcept { return "exit exception"; } - exit_exception& operator = (exit_exception&) = default; - - ~exit_exception (void) = default; + int exit_status (void) const { return m_exit_status; } - const char * what (void) const noexcept { return "exit exception"; } + bool safe_to_return (void) const { return m_safe_to_return; } - int exit_status (void) const { return m_exit_status; } - - bool safe_to_return (void) const { return m_safe_to_return; } +private: - private: + int m_exit_status; - int m_exit_status; - - bool m_safe_to_return; - }; + bool m_safe_to_return; +}; - class interrupt_exception : public std::exception - { - public: +class interrupt_exception : public std::exception +{ +public: - interrupt_exception (void) = default; + interrupt_exception (void) = default; - interrupt_exception (const interrupt_exception&) = default; + interrupt_exception (const interrupt_exception&) = default; - interrupt_exception& operator = (const interrupt_exception&) = default; + interrupt_exception& operator = (const interrupt_exception&) = default; - ~interrupt_exception (void) = default; + ~interrupt_exception (void) = default; - const char * what (void) const noexcept { return "interrupt exception"; } - }; + const char * what (void) const noexcept { return "interrupt exception"; } +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/unwind-prot.cc --- a/liboctave/util/unwind-prot.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/unwind-prot.cc Thu Dec 01 20:05:44 2022 -0800 @@ -32,22 +32,22 @@ OCTAVE_BEGIN_NAMESPACE(octave) - void - unwind_protect_safe::warn_unhandled_exception (void) const - { - (*current_liboctave_warning_handler) - ("unhandled exception in unwind_protect_safe handler. " - "It is a bug in Octave for this to happen. " - "Please help improve Octave by reporting it."); - } +void +unwind_protect_safe::warn_unhandled_exception (void) const +{ + (*current_liboctave_warning_handler) + ("unhandled exception in unwind_protect_safe handler. " + "It is a bug in Octave for this to happen. " + "Please help improve Octave by reporting it."); +} - void - unwind_action_safe::warn_unhandled_exception (void) const - { - (*current_liboctave_warning_handler) - ("unhandled exception in unwind_action_safe handler. " - "It is a bug in Octave for this to happen. " - "Please help improve Octave by reporting it."); - } +void +unwind_action_safe::warn_unhandled_exception (void) const +{ + (*current_liboctave_warning_handler) + ("unhandled exception in unwind_action_safe handler. " + "It is a bug in Octave for this to happen. " + "Please help improve Octave by reporting it."); +} OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/unwind-prot.h --- a/liboctave/util/unwind-prot.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/unwind-prot.h Thu Dec 01 20:05:44 2022 -0800 @@ -37,318 +37,318 @@ OCTAVE_BEGIN_NAMESPACE(octave) - class - OCTAVE_API - unwind_protect : public action_container - { - public: +class +OCTAVE_API +unwind_protect : public action_container +{ +public: - unwind_protect (void) : m_lifo () { } + unwind_protect (void) : m_lifo () { } - // No copying! + // No copying! - unwind_protect (const unwind_protect&) = delete; + unwind_protect (const unwind_protect&) = delete; - unwind_protect& operator = (const unwind_protect&) = delete; + unwind_protect& operator = (const unwind_protect&) = delete; - // Destructor should not raise an exception, so all actions - // registered should be exception-safe. If you're not sure, see - // unwind_protect_safe. + // Destructor should not raise an exception, so all actions + // registered should be exception-safe. If you're not sure, see + // unwind_protect_safe. - ~unwind_protect (void) { run (); } + ~unwind_protect (void) { run (); } - operator bool (void) const { return ! empty (); } + operator bool (void) const { return ! empty (); } - void run_first (void) - { - if (! empty ()) - { - // No leak on exception! - std::unique_ptr ptr (m_lifo.top ()); - m_lifo.pop (); - ptr->run (); - } - } + void run_first (void) + { + if (! empty ()) + { + // No leak on exception! + std::unique_ptr ptr (m_lifo.top ()); + m_lifo.pop (); + ptr->run (); + } + } - void discard_first (void) - { - if (! empty ()) - { - elem *ptr = m_lifo.top (); - m_lifo.pop (); - delete ptr; - } - } + void discard_first (void) + { + if (! empty ()) + { + elem *ptr = m_lifo.top (); + m_lifo.pop (); + delete ptr; + } + } - std::size_t size (void) const { return m_lifo.size (); } + std::size_t size (void) const { return m_lifo.size (); } - protected: +protected: - virtual void add_action (elem *new_elem) - { - m_lifo.push (new_elem); - } + virtual void add_action (elem *new_elem) + { + m_lifo.push (new_elem); + } - std::stack m_lifo; - }; + std::stack m_lifo; +}; - // Like unwind_protect, but this one will guard against the possibility - // of seeing an exception (or interrupt) in the cleanup actions. - // Not that we can do much about it, but at least we won't crash. +// Like unwind_protect, but this one will guard against the possibility +// of seeing an exception (or interrupt) in the cleanup actions. +// Not that we can do much about it, but at least we won't crash. - class - OCTAVE_API - unwind_protect_safe : public unwind_protect - { - private: +class +OCTAVE_API +unwind_protect_safe : public unwind_protect +{ +private: - void warn_unhandled_exception (void) const; + void warn_unhandled_exception (void) const; - public: +public: - unwind_protect_safe (void) : unwind_protect () { } + unwind_protect_safe (void) : unwind_protect () { } - // No copying! + // No copying! - unwind_protect_safe (const unwind_protect_safe&) = delete; + unwind_protect_safe (const unwind_protect_safe&) = delete; - unwind_protect_safe& operator = (const unwind_protect_safe&) = delete; + unwind_protect_safe& operator = (const unwind_protect_safe&) = delete; - ~unwind_protect_safe (void) - { - while (! empty ()) - { - try - { - run_first (); - } - catch (...) // Yes, the black hole. Remember we're in a destructor. - { - warn_unhandled_exception (); - } - } - } - }; + ~unwind_protect_safe (void) + { + while (! empty ()) + { + try + { + run_first (); + } + catch (...) // Yes, the black hole. Remember we're in a destructor. + { + warn_unhandled_exception (); + } + } + } +}; - // In most cases, the following are preferred for efficiency. Some - // cases may require the flexibility of the general unwind_protect - // mechanism defined above. +// In most cases, the following are preferred for efficiency. Some +// cases may require the flexibility of the general unwind_protect +// mechanism defined above. - // Perform action at end of the current scope when unwind_action - // object destructor is called. - // - // For example: - // - // void fcn (int val) { ... } - // - // ... - // - // { - // int val = 42; - // - // // template parameters, std::bind and std::function provide - // // flexibility in calling forms (function pointer or lambda): - // - // unwind_action act1 (fcn, val); - // unwind_action act2 ([val] (void) { fcn (val); }); - // } - // - // NOTE: Don't forget to provide a name for the unwind_action - // variable. If you write - // - // unwind_action /* NO NAME! */ (...); - // - // then the destructor for the temporary anonymous object will be - // called immediately after the object is constructed instead of at - // the end of the current scope. +// Perform action at end of the current scope when unwind_action +// object destructor is called. +// +// For example: +// +// void fcn (int val) { ... } +// +// ... +// +// { +// int val = 42; +// +// // template parameters, std::bind and std::function provide +// // flexibility in calling forms (function pointer or lambda): +// +// unwind_action act1 (fcn, val); +// unwind_action act2 ([val] (void) { fcn (val); }); +// } +// +// NOTE: Don't forget to provide a name for the unwind_action +// variable. If you write +// +// unwind_action /* NO NAME! */ (...); +// +// then the destructor for the temporary anonymous object will be +// called immediately after the object is constructed instead of at +// the end of the current scope. - class OCTAVE_API unwind_action - { - public: +class OCTAVE_API unwind_action +{ +public: - unwind_action (void) : m_fcn () { } + unwind_action (void) : m_fcn () { } - // FIXME: Do we need to apply std::forward to the arguments to - // std::bind here? + // FIXME: Do we need to apply std::forward to the arguments to + // std::bind here? - template - unwind_action (F&& fcn, Args&&... args) - : m_fcn (std::bind (fcn, args...)) - { } + template + unwind_action (F&& fcn, Args&& ... args) + : m_fcn (std::bind (fcn, args...)) + { } - // No copying! + // No copying! - unwind_action (const unwind_action&) = delete; + unwind_action (const unwind_action&) = delete; - unwind_action& operator = (const unwind_action&) = delete; + unwind_action& operator = (const unwind_action&) = delete; - ~unwind_action (void) { run (); } + ~unwind_action (void) { run (); } - // FIXME: Do we need to apply std::forward to the arguments to - // std::bind here? + // FIXME: Do we need to apply std::forward to the arguments to + // std::bind here? - template - void set (F&& fcn, Args&&... args) - { - m_fcn = std::bind (fcn, args...); - } + template + void set (F&& fcn, Args&& ... args) + { + m_fcn = std::bind (fcn, args...); + } - void set (void) { m_fcn = nullptr; } + void set (void) { m_fcn = nullptr; } - // Alias for set() which is clearer about programmer intention. - void discard (void) { set (); } + // Alias for set() which is clearer about programmer intention. + void discard (void) { set (); } - void run (void) - { - if (m_fcn) - m_fcn (); + void run (void) + { + if (m_fcn) + m_fcn (); - // Invalidate so action won't run again when object is deleted. - discard (); - } + // Invalidate so action won't run again when object is deleted. + discard (); + } - private: +private: - std::function m_fcn; - }; + std::function m_fcn; +}; - // Like unwind_action, but this one will guard against the possibility - // of seeing an exception (or interrupt) in the cleanup actions. - // Not that we can do much about it, but at least we won't crash. +// Like unwind_action, but this one will guard against the possibility +// of seeing an exception (or interrupt) in the cleanup actions. +// Not that we can do much about it, but at least we won't crash. - class OCTAVE_API unwind_action_safe - { - private: +class OCTAVE_API unwind_action_safe +{ +private: - void warn_unhandled_exception (void) const; + void warn_unhandled_exception (void) const; - public: +public: - unwind_action_safe (void) : m_fcn () { } + unwind_action_safe (void) : m_fcn () { } - // FIXME: Do we need to apply std::forward to the arguments to - // std::bind here? + // FIXME: Do we need to apply std::forward to the arguments to + // std::bind here? - template - unwind_action_safe (F&& fcn, Args&&... args) - : m_fcn (std::bind (fcn, args...)) - { } + template + unwind_action_safe (F&& fcn, Args&& ... args) + : m_fcn (std::bind (fcn, args...)) + { } - // No copying! + // No copying! - unwind_action_safe (const unwind_action_safe&) = delete; + unwind_action_safe (const unwind_action_safe&) = delete; - unwind_action_safe& operator = (const unwind_action_safe&) = delete; + unwind_action_safe& operator = (const unwind_action_safe&) = delete; - ~unwind_action_safe (void) { run (); } + ~unwind_action_safe (void) { run (); } - // FIXME: Do we need to apply std::forward to the arguments to - // std::bind here? + // FIXME: Do we need to apply std::forward to the arguments to + // std::bind here? - template - void set (F&& fcn, Args&&... args) - { - m_fcn = std::bind (fcn, args...); - } + template + void set (F&& fcn, Args&& ... args) + { + m_fcn = std::bind (fcn, args...); + } - void set (void) { m_fcn = nullptr; } + void set (void) { m_fcn = nullptr; } - // Alias for set() which is clearer about programmer intention. - void discard (void) { set (); } + // Alias for set() which is clearer about programmer intention. + void discard (void) { set (); } - void run (void) - { - try - { - if (m_fcn) - m_fcn (); - } - catch (...) // Yes, the black hole. Remember we're in a destructor. - { - warn_unhandled_exception (); - } + void run (void) + { + try + { + if (m_fcn) + m_fcn (); + } + catch (...) // Yes, the black hole. Remember we're in a destructor. + { + warn_unhandled_exception (); + } - // Invalidate so action won't run again when object is deleted. - discard (); - } + // Invalidate so action won't run again when object is deleted. + discard (); + } - private: +private: - std::function m_fcn; - }; + std::function m_fcn; +}; - // Reset a variable value at the end of the current scope when - // unwind_protect_var object destructor is called. - // - // For example: - // - // { - // int x = 42; - // unwind_protect_var upv (x); // X will be reset at end of scope - // x = 13; // Set temporary value. - // } - // - // Temporary value may be set at construction: - // - // { - // int x = ...; - // unwind_protect_var upv (x, 13); // X will be reset. - // // temporary value is 13. - // } - // - // NOTE: Don't forget to provide a name for the unwind_protect_var - // variable. If you write - // - // unwind_protect_var /* NO NAME! */ (...); - // - // then the destructor for the temporary anonymous object will be - // called immediately after the object is constructed instead of at - // the end of the current scope. - // - // FIXME: Once we are able to use C++17, class template argument - // deduction will allow us to omit the explicit template type from the - // constructor expression: - // - // unwind_protect_var upv (...); +// Reset a variable value at the end of the current scope when +// unwind_protect_var object destructor is called. +// +// For example: +// +// { +// int x = 42; +// unwind_protect_var upv (x); // X will be reset at end of scope +// x = 13; // Set temporary value. +// } +// +// Temporary value may be set at construction: +// +// { +// int x = ...; +// unwind_protect_var upv (x, 13); // X will be reset. +// // temporary value is 13. +// } +// +// NOTE: Don't forget to provide a name for the unwind_protect_var +// variable. If you write +// +// unwind_protect_var /* NO NAME! */ (...); +// +// then the destructor for the temporary anonymous object will be +// called immediately after the object is constructed instead of at +// the end of the current scope. +// +// FIXME: Once we are able to use C++17, class template argument +// deduction will allow us to omit the explicit template type from the +// constructor expression: +// +// unwind_protect_var upv (...); - template - class unwind_protect_var - { - public: +template +class unwind_protect_var +{ +public: - // Ensure that the value referenced by REF will be reset when this - // unwind_protect_var object goes out of scope. + // Ensure that the value referenced by REF will be reset when this + // unwind_protect_var object goes out of scope. - explicit unwind_protect_var (T& ref) - : m_ref (ref), m_val (ref) - { } + explicit unwind_protect_var (T& ref) + : m_ref (ref), m_val (ref) + { } - // Set the value referenced by REF to NEW_VAL and ensure that it - // will be reset to its original value when this - // unwind_protect_var object goes out of scope. + // Set the value referenced by REF to NEW_VAL and ensure that it + // will be reset to its original value when this + // unwind_protect_var object goes out of scope. - unwind_protect_var (T& ref, const T& new_val) - : m_ref (ref), m_val (ref) - { - m_ref = new_val; - } + unwind_protect_var (T& ref, const T& new_val) + : m_ref (ref), m_val (ref) + { + m_ref = new_val; + } - // No copying! + // No copying! - unwind_protect_var (const unwind_protect_var&) = delete; + unwind_protect_var (const unwind_protect_var&) = delete; - unwind_protect_var& operator = (const unwind_protect_var&) = delete; + unwind_protect_var& operator = (const unwind_protect_var&) = delete; - ~unwind_protect_var (void) - { - m_ref = m_val; - } + ~unwind_protect_var (void) + { + m_ref = m_val; + } - private: +private: - T& m_ref; - T m_val; - }; + T& m_ref; + T m_val; +}; OCTAVE_END_NAMESPACE(octave) diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/url-transfer.cc --- a/liboctave/util/url-transfer.cc Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/url-transfer.cc Thu Dec 01 20:05:44 2022 -0800 @@ -48,216 +48,216 @@ OCTAVE_BEGIN_NAMESPACE(octave) - base_url_transfer::base_url_transfer (void) - : m_host_or_url (), m_valid (false), m_ftp (false), - m_ascii_mode (false), m_ok (true), m_errmsg (), - m_curr_istream (&std::cin), m_curr_ostream (&std::cout) - { } +base_url_transfer::base_url_transfer (void) + : m_host_or_url (), m_valid (false), m_ftp (false), + m_ascii_mode (false), m_ok (true), m_errmsg (), + m_curr_istream (&std::cin), m_curr_ostream (&std::cout) +{ } + +base_url_transfer::base_url_transfer (const std::string& host, + const std::string& /* user_arg */, + const std::string& /* passwd */, + std::ostream& os) + : m_host_or_url (host), m_valid (false), m_ftp (true), + m_ascii_mode (false), m_ok (true), m_errmsg (), + m_curr_istream (&std::cin), m_curr_ostream (&os) +{ } + +base_url_transfer::base_url_transfer (const std::string& url, + std::ostream& os) + : m_host_or_url (url), m_valid (false), m_ftp (false), + m_ascii_mode (false), m_ok (true), m_errmsg (), + m_curr_istream (&std::cin), m_curr_ostream (&os) +{ } + +void +base_url_transfer::mget_directory (const std::string& directory, + const std::string& target) +{ + std::string sep = sys::file_ops::dir_sep_str (); + sys::file_stat fs (directory); - base_url_transfer::base_url_transfer (const std::string& host, - const std::string& /* user_arg */, - const std::string& /* passwd */, - std::ostream& os) - : m_host_or_url (host), m_valid (false), m_ftp (true), - m_ascii_mode (false), m_ok (true), m_errmsg (), - m_curr_istream (&std::cin), m_curr_ostream (&os) - { } + if (! fs || ! fs.is_dir ()) + { + std::string msg; + int status = sys::mkdir (directory, 0777, msg); + + if (status < 0) + { + m_ok = false; + m_errmsg = "__ftp_mget__: can not create directory '" + + target + sep + directory + "': " + msg; + return; + } + } + + cwd (directory); + + if (good ()) + { + unwind_action_safe reset_path (&base_url_transfer::cwd, this, ".."); + + string_vector sv = list (); + + for (octave_idx_type i = 0; i < sv.numel (); i++) + { + OCTAVE_TIME_T ftime; + bool fisdir; + double fsize; + + get_fileinfo (sv(i), fsize, ftime, fisdir); - base_url_transfer::base_url_transfer (const std::string& url, - std::ostream& os) - : m_host_or_url (url), m_valid (false), m_ftp (false), - m_ascii_mode (false), m_ok (true), m_errmsg (), - m_curr_istream (&std::cin), m_curr_ostream (&os) - { } + if (fisdir) + mget_directory (sv(i), target + directory + sep); + else + { + std::string realfile = target + directory + sep + sv(i); + + std::ofstream ofile = + sys::ofstream (realfile.c_str (), + std::ios::out | std::ios::binary); + + if (! ofile.is_open ()) + { + m_ok = false; + m_errmsg = "__ftp_mget__: unable to open file"; + break; + } + int(*unlink_fptr)(const std::string&) = sys::unlink; + unwind_action_safe delete_file (unlink_fptr, realfile); + + get (sv(i), ofile); + + ofile.close (); + + if (good ()) + delete_file.discard (); + } - void - base_url_transfer::mget_directory (const std::string& directory, - const std::string& target) - { - std::string sep = sys::file_ops::dir_sep_str (); - sys::file_stat fs (directory); + if (! good ()) + break; + } + } +} + +string_vector +base_url_transfer::mput_directory (const std::string& base, + const std::string& directory) +{ + string_vector file_list; + + std::string realdir + = (base.empty () + ? directory : base + sys::file_ops::dir_sep_str () + directory); - if (! fs || ! fs.is_dir ()) - { - std::string msg; - int status = sys::mkdir (directory, 0777, msg); + mkdir (directory); + + if (! good ()) + return file_list; + + cwd (directory); - if (status < 0) + if (good ()) + { + unwind_action_safe reset_path (&base_url_transfer::cwd, this, ".."); + + string_vector files; + std::string msg; + + if (sys::get_dirlist (realdir, files, msg)) + for (octave_idx_type i = 0; i < files.numel (); i++) { - m_ok = false; - m_errmsg = "__ftp_mget__: can not create directory '" - + target + sep + directory + "': " + msg; - return; - } - } - - cwd (directory); + std::string file = files (i); - if (good ()) - { - unwind_action_safe reset_path (&base_url_transfer::cwd, this, ".."); - - string_vector sv = list (); + if (file == "." || file == "..") + continue; - for (octave_idx_type i = 0; i < sv.numel (); i++) - { - OCTAVE_TIME_T ftime; - bool fisdir; - double fsize; - - get_fileinfo (sv(i), fsize, ftime, fisdir); + std::string realfile + = realdir + sys::file_ops::dir_sep_str () + file; - if (fisdir) - mget_directory (sv(i), target + directory + sep); - else - { - std::string realfile = target + directory + sep + sv(i); - - std::ofstream ofile = - sys::ofstream (realfile.c_str (), - std::ios::out | std::ios::binary); + sys::file_stat fs (realfile); - if (! ofile.is_open ()) - { - m_ok = false; - m_errmsg = "__ftp_mget__: unable to open file"; - break; - } - int(*unlink_fptr)(const std::string&) = sys::unlink; - unwind_action_safe delete_file (unlink_fptr, realfile); - - get (sv(i), ofile); - - ofile.close (); - - if (good ()) - delete_file.discard (); + if (! fs.exists ()) + { + m_ok = false; + m_errmsg = "__ftp__mput: file '" + realfile + + "' does not exist"; + break; } - if (! good ()) - break; - } - } - } - - string_vector - base_url_transfer::mput_directory (const std::string& base, - const std::string& directory) - { - string_vector file_list; - - std::string realdir - = (base.empty () - ? directory : base + sys::file_ops::dir_sep_str () + directory); - - mkdir (directory); - - if (! good ()) - return file_list; + if (fs.is_dir ()) + { + file_list.append (mput_directory (realdir, file)); - cwd (directory); - - if (good ()) - { - unwind_action_safe reset_path (&base_url_transfer::cwd, this, ".."); - - string_vector files; - std::string msg; - - if (sys::get_dirlist (realdir, files, msg)) - for (octave_idx_type i = 0; i < files.numel (); i++) - { - std::string file = files (i); - - if (file == "." || file == "..") - continue; - - std::string realfile - = realdir + sys::file_ops::dir_sep_str () + file; - - sys::file_stat fs (realfile); + if (! good ()) + break; + } + else + { + // FIXME: Does ascii mode need to be flagged here? + std::ifstream ifile = + sys::ifstream (realfile.c_str (), + std::ios::in | std::ios::binary); - if (! fs.exists ()) - { - m_ok = false; - m_errmsg = "__ftp__mput: file '" + realfile - + "' does not exist"; - break; - } + if (! ifile.is_open ()) + { + m_ok = false; + m_errmsg = "__ftp_mput__: unable to open file '" + + realfile + "'"; + break; + } - if (fs.is_dir ()) - { - file_list.append (mput_directory (realdir, file)); + put (file, ifile); - if (! good ()) - break; - } - else - { - // FIXME: Does ascii mode need to be flagged here? - std::ifstream ifile = - sys::ifstream (realfile.c_str (), - std::ios::in | std::ios::binary); + ifile.close (); - if (! ifile.is_open ()) - { - m_ok = false; - m_errmsg = "__ftp_mput__: unable to open file '" - + realfile + "'"; - break; - } - - put (file, ifile); - - ifile.close (); + if (! good ()) + break; - if (! good ()) - break; + file_list.append (realfile); + } + } + else + { + m_ok = false; + m_errmsg = "__ftp_mput__: can not read the directory '" + + realdir + "'"; + } + } - file_list.append (realfile); - } - } - else - { - m_ok = false; - m_errmsg = "__ftp_mput__: can not read the directory '" - + realdir + "'"; - } - } - - return file_list; - } + return file_list; +} #if defined (HAVE_CURL) - static int - write_data (void *buffer, std::size_t size, std::size_t nmemb, void *streamp) - { - std::ostream& stream = *(static_cast (streamp)); - stream.write (static_cast (buffer), size*nmemb); - return (stream.fail () ? 0 : size * nmemb); - } +static int +write_data (void *buffer, std::size_t size, std::size_t nmemb, void *streamp) +{ + std::ostream& stream = *(static_cast (streamp)); + stream.write (static_cast (buffer), size*nmemb); + return (stream.fail () ? 0 : size * nmemb); +} - static int - read_data (void *buffer, std::size_t size, std::size_t nmemb, void *streamp) - { - std::istream& stream = *(static_cast (streamp)); - stream.read (static_cast (buffer), size*nmemb); - if (stream.eof ()) - return stream.gcount (); - else - return (stream.fail () ? 0 : size * nmemb); - } +static int +read_data (void *buffer, std::size_t size, std::size_t nmemb, void *streamp) +{ + std::istream& stream = *(static_cast (streamp)); + stream.read (static_cast (buffer), size*nmemb); + if (stream.eof ()) + return stream.gcount (); + else + return (stream.fail () ? 0 : size * nmemb); +} - static std::size_t - throw_away (void *, std::size_t size, std::size_t nmemb, void *) - { - return static_cast (size * nmemb); - } +static std::size_t +throw_away (void *, std::size_t size, std::size_t nmemb, void *) +{ + return static_cast (size * nmemb); +} - // I'd love to rewrite this as a private method of the url_transfer - // class, but you can't pass the va_list from the wrapper SETOPT to - // the curl_easy_setopt function. +// I'd love to rewrite this as a private method of the url_transfer +// class, but you can't pass the va_list from the wrapper SETOPT to +// the curl_easy_setopt function. #define SETOPT(option, parameter) \ do \ { \ @@ -271,7 +271,7 @@ } \ while (0) - // Same as above but with a return value. +// Same as above but with a return value. #define SETOPTR(option, parameter) \ do \ { \ @@ -285,628 +285,628 @@ } \ while (0) - class curl_transfer : public base_url_transfer - { - public: - - curl_transfer (void) - : base_url_transfer (), m_curl (curl_easy_init ()), m_errnum (), m_url (), - m_userpwd () - { - if (m_curl) - m_valid = true; - else - m_errmsg = "can not create curl object"; - } +class curl_transfer : public base_url_transfer +{ +public: - curl_transfer (const std::string& host, const std::string& user_arg, - const std::string& passwd, std::ostream& os) - : base_url_transfer (host, user_arg, passwd, os), - m_curl (curl_easy_init ()), m_errnum (), m_url (), m_userpwd () - { - if (m_curl) - m_valid = true; - else - { - m_errmsg = "can not create curl object"; - return; - } - - init (user_arg, passwd, std::cin, os); - - m_url = "ftp://" + host; - SETOPT (CURLOPT_URL, m_url.c_str ()); + curl_transfer (void) + : base_url_transfer (), m_curl (curl_easy_init ()), m_errnum (), m_url (), + m_userpwd () + { + if (m_curl) + m_valid = true; + else + m_errmsg = "can not create curl object"; + } - // Set up the link, with no transfer. - perform (); - } + curl_transfer (const std::string& host, const std::string& user_arg, + const std::string& passwd, std::ostream& os) + : base_url_transfer (host, user_arg, passwd, os), + m_curl (curl_easy_init ()), m_errnum (), m_url (), m_userpwd () + { + if (m_curl) + m_valid = true; + else + { + m_errmsg = "can not create curl object"; + return; + } - curl_transfer (const std::string& url_str, std::ostream& os) - : base_url_transfer (url_str, os), m_curl (curl_easy_init ()), - m_errnum (), m_url (), m_userpwd () - { - if (m_curl) - m_valid = true; - else - { - m_errmsg = "can not create curl object"; - return; - } + init (user_arg, passwd, std::cin, os); - init ("", "", std::cin, os); + m_url = "ftp://" + host; + SETOPT (CURLOPT_URL, m_url.c_str ()); - std::string cainfo = sys::env::getenv ("CURLOPT_CAINFO"); - if (! cainfo.empty ()) - SETOPT (CURLOPT_CAINFO, cainfo.c_str ()); - - std::string capath = sys::env::getenv ("CURLOPT_CAPATH"); - if (! capath.empty ()) - SETOPT (CURLOPT_CAPATH, capath.c_str ()); - - SETOPT (CURLOPT_NOBODY, 0); + // Set up the link, with no transfer. + perform (); + } - // Restore the default HTTP request method to GET after setting - // NOBODY to true (in the init method) and back to false (above). - // This is needed for backward compatibility with versions of - // libcurl < 7.18.2. - SETOPT (CURLOPT_HTTPGET, 1); - } + curl_transfer (const std::string& url_str, std::ostream& os) + : base_url_transfer (url_str, os), m_curl (curl_easy_init ()), + m_errnum (), m_url (), m_userpwd () + { + if (m_curl) + m_valid = true; + else + { + m_errmsg = "can not create curl object"; + return; + } - // No copying! - - curl_transfer (const curl_transfer&) = delete; + init ("", "", std::cin, os); - curl_transfer& operator = (const curl_transfer&) = delete; + std::string cainfo = sys::env::getenv ("CURLOPT_CAINFO"); + if (! cainfo.empty ()) + SETOPT (CURLOPT_CAINFO, cainfo.c_str ()); - ~curl_transfer (void) - { - if (m_curl) - curl_easy_cleanup (m_curl); - } + std::string capath = sys::env::getenv ("CURLOPT_CAPATH"); + if (! capath.empty ()) + SETOPT (CURLOPT_CAPATH, capath.c_str ()); - void perform (void) - { - m_errnum = curl_easy_perform (m_curl); + SETOPT (CURLOPT_NOBODY, 0); - if (m_errnum != CURLE_OK) - { - m_ok = false; - m_errmsg = curl_easy_strerror (m_errnum); - } - } + // Restore the default HTTP request method to GET after setting + // NOBODY to true (in the init method) and back to false (above). + // This is needed for backward compatibility with versions of + // libcurl < 7.18.2. + SETOPT (CURLOPT_HTTPGET, 1); + } - std::string lasterror (void) const - { - return std::string (curl_easy_strerror (m_errnum)); - } + // No copying! - std::ostream& set_ostream (std::ostream& os) - { - std::ostream& retval = *m_curr_ostream; - m_curr_ostream = &os; - SETOPTR (CURLOPT_WRITEDATA, static_cast (m_curr_ostream)); - return retval; - } + curl_transfer (const curl_transfer&) = delete; + + curl_transfer& operator = (const curl_transfer&) = delete; - std::istream& set_istream (std::istream& is) - { - std::istream& retval = *m_curr_istream; - m_curr_istream = &is; - SETOPTR (CURLOPT_READDATA, static_cast (m_curr_istream)); - return retval; - } + ~curl_transfer (void) + { + if (m_curl) + curl_easy_cleanup (m_curl); + } - void ascii (void) - { - m_ascii_mode = true; - SETOPT (CURLOPT_TRANSFERTEXT, 1); - } - - void binary (void) - { - m_ascii_mode = false; - SETOPT (CURLOPT_TRANSFERTEXT, 0); - } + void perform (void) + { + m_errnum = curl_easy_perform (m_curl); - void cwd (const std::string& path) - { - ftp_file_or_dir_action (path, "cwd"); - } - - void del (const std::string& file) - { - ftp_file_or_dir_action (file, "dele"); - } + if (m_errnum != CURLE_OK) + { + m_ok = false; + m_errmsg = curl_easy_strerror (m_errnum); + } + } - void rmdir (const std::string& path) - { - ftp_file_or_dir_action (path, "rmd"); - } + std::string lasterror (void) const + { + return std::string (curl_easy_strerror (m_errnum)); + } - void mkdir (const std::string& path) - { - ftp_file_or_dir_action (path, "mkd"); - } + std::ostream& set_ostream (std::ostream& os) + { + std::ostream& retval = *m_curr_ostream; + m_curr_ostream = &os; + SETOPTR (CURLOPT_WRITEDATA, static_cast (m_curr_ostream)); + return retval; + } - void rename (const std::string& oldname, const std::string& newname) - { - struct curl_slist *slist = nullptr; - - unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); - - std::string cmd = "rnfr " + oldname; - slist = curl_slist_append (slist, cmd.c_str ()); - cmd = "rnto " + newname; - slist = curl_slist_append (slist, cmd.c_str ()); - SETOPT (CURLOPT_POSTQUOTE, slist); + std::istream& set_istream (std::istream& is) + { + std::istream& retval = *m_curr_istream; + m_curr_istream = &is; + SETOPTR (CURLOPT_READDATA, static_cast (m_curr_istream)); + return retval; + } - perform (); - if (! good ()) - return; - - SETOPT (CURLOPT_POSTQUOTE, 0); - } + void ascii (void) + { + m_ascii_mode = true; + SETOPT (CURLOPT_TRANSFERTEXT, 1); + } - void put (const std::string& file, std::istream& is) - { - m_url = "ftp://" + m_host_or_url + '/' + file; - SETOPT (CURLOPT_URL, m_url.c_str ()); - SETOPT (CURLOPT_UPLOAD, 1); - SETOPT (CURLOPT_NOBODY, 0); - std::istream& old_is = set_istream (is); + void binary (void) + { + m_ascii_mode = false; + SETOPT (CURLOPT_TRANSFERTEXT, 0); + } - perform (); - if (! good ()) - return; + void cwd (const std::string& path) + { + ftp_file_or_dir_action (path, "cwd"); + } - set_istream (old_is); - SETOPT (CURLOPT_NOBODY, 1); - SETOPT (CURLOPT_UPLOAD, 0); - m_url = "ftp://" + m_host_or_url; - SETOPT (CURLOPT_URL, m_url.c_str ()); - } + void del (const std::string& file) + { + ftp_file_or_dir_action (file, "dele"); + } - void get (const std::string& file, std::ostream& os) - { - m_url = "ftp://" + m_host_or_url + '/' + file; - SETOPT (CURLOPT_URL, m_url.c_str ()); - SETOPT (CURLOPT_NOBODY, 0); - std::ostream& old_os = set_ostream (os); + void rmdir (const std::string& path) + { + ftp_file_or_dir_action (path, "rmd"); + } - perform (); - if (! good ()) - return; + void mkdir (const std::string& path) + { + ftp_file_or_dir_action (path, "mkd"); + } - set_ostream (old_os); - SETOPT (CURLOPT_NOBODY, 1); - m_url = "ftp://" + m_host_or_url; - SETOPT (CURLOPT_URL, m_url.c_str ()); - } + void rename (const std::string& oldname, const std::string& newname) + { + struct curl_slist *slist = nullptr; + + unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); - void dir (void) - { - m_url = "ftp://" + m_host_or_url + '/'; - SETOPT (CURLOPT_URL, m_url.c_str ()); - SETOPT (CURLOPT_NOBODY, 0); + std::string cmd = "rnfr " + oldname; + slist = curl_slist_append (slist, cmd.c_str ()); + cmd = "rnto " + newname; + slist = curl_slist_append (slist, cmd.c_str ()); + SETOPT (CURLOPT_POSTQUOTE, slist); - perform (); - if (! good ()) - return; - - SETOPT (CURLOPT_NOBODY, 1); - m_url = "ftp://" + m_host_or_url; - SETOPT (CURLOPT_URL, m_url.c_str ()); - } + perform (); + if (! good ()) + return; - string_vector list (void) - { - string_vector retval; + SETOPT (CURLOPT_POSTQUOTE, 0); + } + + void put (const std::string& file, std::istream& is) + { + m_url = "ftp://" + m_host_or_url + '/' + file; + SETOPT (CURLOPT_URL, m_url.c_str ()); + SETOPT (CURLOPT_UPLOAD, 1); + SETOPT (CURLOPT_NOBODY, 0); + std::istream& old_is = set_istream (is); - std::ostringstream buf; - m_url = "ftp://" + m_host_or_url + '/'; - SETOPTR (CURLOPT_WRITEDATA, static_cast (&buf)); - SETOPTR (CURLOPT_URL, m_url.c_str ()); - SETOPTR (CURLOPT_DIRLISTONLY, 1); - SETOPTR (CURLOPT_NOBODY, 0); + perform (); + if (! good ()) + return; - perform (); - if (! good ()) - return retval; + set_istream (old_is); + SETOPT (CURLOPT_NOBODY, 1); + SETOPT (CURLOPT_UPLOAD, 0); + m_url = "ftp://" + m_host_or_url; + SETOPT (CURLOPT_URL, m_url.c_str ()); + } - SETOPTR (CURLOPT_NOBODY, 1); - m_url = "ftp://" + m_host_or_url; - SETOPTR (CURLOPT_WRITEDATA, static_cast (m_curr_ostream)); - SETOPTR (CURLOPT_DIRLISTONLY, 0); - SETOPTR (CURLOPT_URL, m_url.c_str ()); + void get (const std::string& file, std::ostream& os) + { + m_url = "ftp://" + m_host_or_url + '/' + file; + SETOPT (CURLOPT_URL, m_url.c_str ()); + SETOPT (CURLOPT_NOBODY, 0); + std::ostream& old_os = set_ostream (os); - // Count number of directory entries - std::string str = buf.str (); - octave_idx_type n = 0; - std::size_t pos = 0; - while (true) - { - pos = str.find_first_of ('\n', pos); - if (pos == std::string::npos) - break; - pos++; - n++; - } - retval.resize (n); - pos = 0; - for (octave_idx_type i = 0; i < n; i++) - { - std::size_t newpos = str.find_first_of ('\n', pos); - if (newpos == std::string::npos) - break; + perform (); + if (! good ()) + return; - retval(i) = str.substr(pos, newpos - pos); - pos = newpos + 1; - } + set_ostream (old_os); + SETOPT (CURLOPT_NOBODY, 1); + m_url = "ftp://" + m_host_or_url; + SETOPT (CURLOPT_URL, m_url.c_str ()); + } - return retval; - } - - void get_fileinfo (const std::string& filename, double& filesize, - OCTAVE_TIME_T& filetime, bool& fileisdir) - { - std::string path = pwd (); - - m_url = "ftp://" + m_host_or_url + '/' + path + '/' + filename; - SETOPT (CURLOPT_URL, m_url.c_str ()); - SETOPT (CURLOPT_FILETIME, 1); - SETOPT (CURLOPT_HEADERFUNCTION, throw_away); - SETOPT (CURLOPT_WRITEFUNCTION, throw_away); + void dir (void) + { + m_url = "ftp://" + m_host_or_url + '/'; + SETOPT (CURLOPT_URL, m_url.c_str ()); + SETOPT (CURLOPT_NOBODY, 0); - // FIXME - // The MDTM command fails for a directory on the servers I tested - // so this is a means of testing for directories. It also means - // I can't get the date of directories! + perform (); + if (! good ()) + return; - perform (); - if (! good ()) - { - fileisdir = true; - filetime = -1; - filesize = 0; + SETOPT (CURLOPT_NOBODY, 1); + m_url = "ftp://" + m_host_or_url; + SETOPT (CURLOPT_URL, m_url.c_str ()); + } - return; - } + string_vector list (void) + { + string_vector retval; - fileisdir = false; - OCTAVE_TIME_T ft; - curl_easy_getinfo (m_curl, CURLINFO_FILETIME, &ft); - filetime = ft; - double fs; - curl_easy_getinfo (m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs); - filesize = fs; - - SETOPT (CURLOPT_WRITEFUNCTION, write_data); - SETOPT (CURLOPT_HEADERFUNCTION, 0); - SETOPT (CURLOPT_FILETIME, 0); - m_url = "ftp://" + m_host_or_url; - SETOPT (CURLOPT_URL, m_url.c_str ()); + std::ostringstream buf; + m_url = "ftp://" + m_host_or_url + '/'; + SETOPTR (CURLOPT_WRITEDATA, static_cast (&buf)); + SETOPTR (CURLOPT_URL, m_url.c_str ()); + SETOPTR (CURLOPT_DIRLISTONLY, 1); + SETOPTR (CURLOPT_NOBODY, 0); - // The MDTM command seems to reset the path to the root with the - // servers I tested with, so cd again into the correct path. Make - // the path absolute so that this will work even with servers that - // don't end up in the root after an MDTM command. - cwd ('/' + path); - } - - std::string pwd (void) - { - std::string retval; + perform (); + if (! good ()) + return retval; - struct curl_slist *slist = nullptr; - - unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); - - slist = curl_slist_append (slist, "pwd"); - SETOPTR (CURLOPT_POSTQUOTE, slist); - SETOPTR (CURLOPT_HEADERFUNCTION, write_data); - - std::ostringstream buf; - SETOPTR (CURLOPT_WRITEHEADER, static_cast(&buf)); + SETOPTR (CURLOPT_NOBODY, 1); + m_url = "ftp://" + m_host_or_url; + SETOPTR (CURLOPT_WRITEDATA, static_cast (m_curr_ostream)); + SETOPTR (CURLOPT_DIRLISTONLY, 0); + SETOPTR (CURLOPT_URL, m_url.c_str ()); - perform (); - if (! good ()) - return retval; - - retval = buf.str (); - - // Can I assume that the path is always in "" on the last line - std::size_t pos2 = retval.rfind ('"'); - std::size_t pos1 = retval.rfind ('"', pos2 - 1); - retval = retval.substr (pos1 + 1, pos2 - pos1 - 1); - - SETOPTR (CURLOPT_HEADERFUNCTION, 0); - SETOPTR (CURLOPT_WRITEHEADER, 0); - SETOPTR (CURLOPT_POSTQUOTE, 0); - - return retval; - } + // Count number of directory entries + std::string str = buf.str (); + octave_idx_type n = 0; + std::size_t pos = 0; + while (true) + { + pos = str.find_first_of ('\n', pos); + if (pos == std::string::npos) + break; + pos++; + n++; + } + retval.resize (n); + pos = 0; + for (octave_idx_type i = 0; i < n; i++) + { + std::size_t newpos = str.find_first_of ('\n', pos); + if (newpos == std::string::npos) + break; - void http_get (const Array& param) - { - http_action (param, "get"); - } + retval(i) = str.substr(pos, newpos - pos); + pos = newpos + 1; + } + + return retval; + } - void http_post (const Array& param) - { - http_action (param, "post"); - } + void get_fileinfo (const std::string& filename, double& filesize, + OCTAVE_TIME_T& filetime, bool& fileisdir) + { + std::string path = pwd (); - void http_action (const Array& param, const std::string& action) - { - m_url = m_host_or_url; - - std::string query_string; - - query_string = form_query_string (param); + m_url = "ftp://" + m_host_or_url + '/' + path + '/' + filename; + SETOPT (CURLOPT_URL, m_url.c_str ()); + SETOPT (CURLOPT_FILETIME, 1); + SETOPT (CURLOPT_HEADERFUNCTION, throw_away); + SETOPT (CURLOPT_WRITEFUNCTION, throw_away); - if (action.empty () || action == "get") - { - if (! query_string.empty ()) - m_url += '?' + query_string; - - SETOPT (CURLOPT_URL, m_url.c_str ()); - } - else if (action == "post" || action == "put" || action == "delete") - { - SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ()); - - if (action == "put") - { - SETOPT (CURLOPT_CUSTOMREQUEST, "PUT"); - } + // FIXME + // The MDTM command fails for a directory on the servers I tested + // so this is a means of testing for directories. It also means + // I can't get the date of directories! - if (action == "delete") - { - SETOPT (CURLOPT_CUSTOMREQUEST, "DELETE"); - } + perform (); + if (! good ()) + { + fileisdir = true; + filetime = -1; + filesize = 0; - SETOPT (CURLOPT_URL, m_url.c_str ()); - } - else - { - m_ok = false; - m_errmsg = "curl_transfer: unknown http action"; - } + return; + } - if (m_ok) - perform (); - } + fileisdir = false; + OCTAVE_TIME_T ft; + curl_easy_getinfo (m_curl, CURLINFO_FILETIME, &ft); + filetime = ft; + double fs; + curl_easy_getinfo (m_curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fs); + filesize = fs; - void cookie_jar (const std::string& filename) - { - SETOPT (CURLOPT_COOKIEJAR, filename.c_str ()); - - SETOPT (CURLOPT_COOKIEFILE, filename.c_str ()); - } + SETOPT (CURLOPT_WRITEFUNCTION, write_data); + SETOPT (CURLOPT_HEADERFUNCTION, 0); + SETOPT (CURLOPT_FILETIME, 0); + m_url = "ftp://" + m_host_or_url; + SETOPT (CURLOPT_URL, m_url.c_str ()); - // Sets the header fields in a transfer. Input should be in the form - // of an array of strings with pairs of keys and values together - void set_header_fields (const Array& param) - { - struct curl_slist *slist = nullptr; - - unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); + // The MDTM command seems to reset the path to the root with the + // servers I tested with, so cd again into the correct path. Make + // the path absolute so that this will work even with servers that + // don't end up in the root after an MDTM command. + cwd ('/' + path); + } - if (param.numel () >= 2) - { - for (int i = 0; i < param.numel (); i += 2) - { - std::string header = param(i) + ": " + param(i+1); + std::string pwd (void) + { + std::string retval; - slist = curl_slist_append (slist, header.c_str ()); - } + struct curl_slist *slist = nullptr; + + unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); - SETOPT (CURLOPT_HTTPHEADER, slist); - } - } + slist = curl_slist_append (slist, "pwd"); + SETOPTR (CURLOPT_POSTQUOTE, slist); + SETOPTR (CURLOPT_HEADERFUNCTION, write_data); - // Sets and sends the form data associated with a transfer. - // Input should be an array of strings with each pair of strings - // corresponding to the fieldname and it's value. - // To attach a file, you should use 'file' as the fieldname with the - // path of the file as its value. - void form_data_post (const Array& param) - { - struct curl_httppost *post = nullptr; - struct curl_httppost *last = nullptr; + std::ostringstream buf; + SETOPTR (CURLOPT_WRITEHEADER, static_cast(&buf)); - SETOPT (CURLOPT_URL, m_host_or_url.c_str ()); + perform (); + if (! good ()) + return retval; - unwind_action cleanup_httppost ([=] () { curl_formfree (post); }); + retval = buf.str (); - if (param.numel () >= 2) - { - for (int i = 0; i < param.numel (); i += 2) - { - std::string name = param(i); - std::string data = param(i+1); + // Can I assume that the path is always in "" on the last line + std::size_t pos2 = retval.rfind ('"'); + std::size_t pos1 = retval.rfind ('"', pos2 - 1); + retval = retval.substr (pos1 + 1, pos2 - pos1 - 1); + + SETOPTR (CURLOPT_HEADERFUNCTION, 0); + SETOPTR (CURLOPT_WRITEHEADER, 0); + SETOPTR (CURLOPT_POSTQUOTE, 0); - if (name == "file") - curl_formadd (&post, &last, CURLFORM_COPYNAME, name.c_str (), - CURLFORM_FILE, data.c_str (), CURLFORM_END); - else - curl_formadd(&post, &last, CURLFORM_COPYNAME, name.c_str (), - CURLFORM_COPYCONTENTS, data.c_str (), CURLFORM_END); - } - - SETOPT (CURLOPT_HTTPPOST, post); - } + return retval; + } - perform (); - } + void http_get (const Array& param) + { + http_action (param, "get"); + } - // Sets the various options specified by weboptions object. - void set_weboptions (const struct weboptions& options) - { - // Remove this after completing fixmes. - std::string temp = ""; - - set_header_fields (options.HeaderFields); - - SETOPT (CURLOPT_TIMEOUT, options.Timeout); + void http_post (const Array& param) + { + http_action (param, "post"); + } - if (! options.UserAgent.empty ()) - SETOPT (CURLOPT_USERAGENT, options.UserAgent.c_str ()); + void http_action (const Array& param, const std::string& action) + { + m_url = m_host_or_url; + + std::string query_string; - if (! options.Username.empty ()) - { - if (! options.Password.empty ()) - { - std::string tmp = options.Username + ":" + options.Password; - SETOPT (CURLOPT_USERPWD, tmp.c_str ()); - } - else - { - std::string tmp = options.Username + ":"; - SETOPT (CURLOPT_USERPWD, tmp.c_str ()); - } - } + query_string = form_query_string (param); + + if (action.empty () || action == "get") + { + if (! query_string.empty ()) + m_url += '?' + query_string; - // Unimplemented. Only for MATLAB compatibility. - if (! options.ContentReader.empty ()) - temp = options.ContentReader; - - // Unimplemented. Only for MATLAB compatibility. - if (! options.ArrayFormat.empty ()) - temp = options.ArrayFormat; + SETOPT (CURLOPT_URL, m_url.c_str ()); + } + else if (action == "post" || action == "put" || action == "delete") + { + SETOPT (CURLOPT_POSTFIELDS, query_string.c_str ()); - // Unimplemented. Only for MATLAB compatibility. - if (! options.CertificateFilename.empty ()) - temp = options.CertificateFilename; - } + if (action == "put") + { + SETOPT (CURLOPT_CUSTOMREQUEST, "PUT"); + } - private: - - // Pointer to cURL object. - CURL *m_curl; - - // cURL error code. - CURLcode m_errnum; + if (action == "delete") + { + SETOPT (CURLOPT_CUSTOMREQUEST, "DELETE"); + } - // The cURL library changed the curl_easy_setopt call to make an - // internal copy of string parameters in version 7.17.0. Prior - // versions only held a pointer to a string provided by the caller - // that must persist for the lifetime of the CURL handle. - // - // The associated API did not change, only the behavior of the library - // implementing the function call. - // - // To be compatible with any version of cURL, the caller must keep a - // copy of all string parameters associated with a CURL handle until - // the handle is released. The curl_handle::curl_handle_rep class - // contains the pointer to the CURL handle and so is the best - // candidate for storing the strings as well. (bug #36717) - std::string m_url; - std::string m_userpwd; + SETOPT (CURLOPT_URL, m_url.c_str ()); + } + else + { + m_ok = false; + m_errmsg = "curl_transfer: unknown http action"; + } + + if (m_ok) + perform (); + } - void init (const std::string& user, const std::string& passwd, - std::istream& is, std::ostream& os) - { - // No data transfer by default - SETOPT (CURLOPT_NOBODY, 1); + void cookie_jar (const std::string& filename) + { + SETOPT (CURLOPT_COOKIEJAR, filename.c_str ()); + + SETOPT (CURLOPT_COOKIEFILE, filename.c_str ()); + } - // Set the username and password - m_userpwd = user; - if (! passwd.empty ()) - m_userpwd += ':' + passwd; - if (! m_userpwd.empty ()) - SETOPT (CURLOPT_USERPWD, m_userpwd.c_str ()); + // Sets the header fields in a transfer. Input should be in the form + // of an array of strings with pairs of keys and values together + void set_header_fields (const Array& param) + { + struct curl_slist *slist = nullptr; - // Define our callback to get called when there's data to be written. - SETOPT (CURLOPT_WRITEFUNCTION, write_data); - - // Set a pointer to our struct to pass to the callback. - SETOPT (CURLOPT_WRITEDATA, static_cast (&os)); + unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); - // Define our callback to get called when there's data to be read - SETOPT (CURLOPT_READFUNCTION, read_data); - - // Set a pointer to our struct to pass to the callback. - SETOPT (CURLOPT_READDATA, static_cast (&is)); + if (param.numel () >= 2) + { + for (int i = 0; i < param.numel (); i += 2) + { + std::string header = param(i) + ": " + param(i+1); - // Follow redirects. - SETOPT (CURLOPT_FOLLOWLOCATION, true); + slist = curl_slist_append (slist, header.c_str ()); + } - // Don't use EPSV since connecting to sites that don't support it - // will hang for some time (3 minutes?) before moving on to try PASV - // instead. - SETOPT (CURLOPT_FTP_USE_EPSV, false); + SETOPT (CURLOPT_HTTPHEADER, slist); + } + } - // Set the user agent for the curl request - // Needed by mediaWiki API. - curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); - const char *lib_ver = data->version; - std::string user_agent - ("GNU Octave/" - + std::string (OCTAVE_VERSION) - + " (https://www.gnu.org/software/octave/ ; help@octave.org) libcurl/" - + std::string (lib_ver)); - - SETOPT (CURLOPT_USERAGENT, user_agent.c_str ()); + // Sets and sends the form data associated with a transfer. + // Input should be an array of strings with each pair of strings + // corresponding to the fieldname and it's value. + // To attach a file, you should use 'file' as the fieldname with the + // path of the file as its value. + void form_data_post (const Array& param) + { + struct curl_httppost *post = nullptr; + struct curl_httppost *last = nullptr; - SETOPT (CURLOPT_NOPROGRESS, true); - SETOPT (CURLOPT_FAILONERROR, true); + SETOPT (CURLOPT_URL, m_host_or_url.c_str ()); - SETOPT (CURLOPT_POSTQUOTE, 0); - SETOPT (CURLOPT_QUOTE, 0); - } + unwind_action cleanup_httppost ([=] () { curl_formfree (post); }); - std::string form_query_string (const Array& param) - { - std::ostringstream query; - - if (param.numel () >= 2) + if (param.numel () >= 2) + { for (int i = 0; i < param.numel (); i += 2) { std::string name = param(i); - std::string text = param(i+1); - - // Encode strings. - char *enc_name = curl_easy_escape (m_curl, name.c_str (), - name.length ()); - char *enc_text = curl_easy_escape (m_curl, text.c_str (), - text.length ()); + std::string data = param(i+1); - query << enc_name << '=' << enc_text; - - curl_free (enc_name); - curl_free (enc_text); - - if (i < param.numel ()-2) - query << '&'; + if (name == "file") + curl_formadd (&post, &last, CURLFORM_COPYNAME, name.c_str (), + CURLFORM_FILE, data.c_str (), CURLFORM_END); + else + curl_formadd(&post, &last, CURLFORM_COPYNAME, name.c_str (), + CURLFORM_COPYCONTENTS, data.c_str (), CURLFORM_END); } - query.flush (); + SETOPT (CURLOPT_HTTPPOST, post); + } + + perform (); + } + + // Sets the various options specified by weboptions object. + void set_weboptions (const struct weboptions& options) + { + // Remove this after completing fixmes. + std::string temp = ""; + + set_header_fields (options.HeaderFields); + + SETOPT (CURLOPT_TIMEOUT, options.Timeout); + + if (! options.UserAgent.empty ()) + SETOPT (CURLOPT_USERAGENT, options.UserAgent.c_str ()); - return query.str (); - } + if (! options.Username.empty ()) + { + if (! options.Password.empty ()) + { + std::string tmp = options.Username + ":" + options.Password; + SETOPT (CURLOPT_USERPWD, tmp.c_str ()); + } + else + { + std::string tmp = options.Username + ":"; + SETOPT (CURLOPT_USERPWD, tmp.c_str ()); + } + } + + // Unimplemented. Only for MATLAB compatibility. + if (! options.ContentReader.empty ()) + temp = options.ContentReader; + + // Unimplemented. Only for MATLAB compatibility. + if (! options.ArrayFormat.empty ()) + temp = options.ArrayFormat; - void ftp_file_or_dir_action (const std::string& file_or_dir, - const std::string& action) - { - struct curl_slist *slist = nullptr; + // Unimplemented. Only for MATLAB compatibility. + if (! options.CertificateFilename.empty ()) + temp = options.CertificateFilename; + } + +private: + + // Pointer to cURL object. + CURL *m_curl; + + // cURL error code. + CURLcode m_errnum; - unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); + // The cURL library changed the curl_easy_setopt call to make an + // internal copy of string parameters in version 7.17.0. Prior + // versions only held a pointer to a string provided by the caller + // that must persist for the lifetime of the CURL handle. + // + // The associated API did not change, only the behavior of the library + // implementing the function call. + // + // To be compatible with any version of cURL, the caller must keep a + // copy of all string parameters associated with a CURL handle until + // the handle is released. The curl_handle::curl_handle_rep class + // contains the pointer to the CURL handle and so is the best + // candidate for storing the strings as well. (bug #36717) + std::string m_url; + std::string m_userpwd; + + void init (const std::string& user, const std::string& passwd, + std::istream& is, std::ostream& os) + { + // No data transfer by default + SETOPT (CURLOPT_NOBODY, 1); + + // Set the username and password + m_userpwd = user; + if (! passwd.empty ()) + m_userpwd += ':' + passwd; + if (! m_userpwd.empty ()) + SETOPT (CURLOPT_USERPWD, m_userpwd.c_str ()); + + // Define our callback to get called when there's data to be written. + SETOPT (CURLOPT_WRITEFUNCTION, write_data); - std::string cmd = action + ' ' + file_or_dir; + // Set a pointer to our struct to pass to the callback. + SETOPT (CURLOPT_WRITEDATA, static_cast (&os)); + + // Define our callback to get called when there's data to be read + SETOPT (CURLOPT_READFUNCTION, read_data); + + // Set a pointer to our struct to pass to the callback. + SETOPT (CURLOPT_READDATA, static_cast (&is)); + + // Follow redirects. + SETOPT (CURLOPT_FOLLOWLOCATION, true); + + // Don't use EPSV since connecting to sites that don't support it + // will hang for some time (3 minutes?) before moving on to try PASV + // instead. + SETOPT (CURLOPT_FTP_USE_EPSV, false); - slist = curl_slist_append (slist, cmd.c_str ()); + // Set the user agent for the curl request + // Needed by mediaWiki API. + curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); + const char *lib_ver = data->version; + std::string user_agent + ("GNU Octave/" + + std::string (OCTAVE_VERSION) + + " (https://www.gnu.org/software/octave/ ; help@octave.org) libcurl/" + + std::string (lib_ver)); - SETOPT (CURLOPT_POSTQUOTE, slist); + SETOPT (CURLOPT_USERAGENT, user_agent.c_str ()); + + SETOPT (CURLOPT_NOPROGRESS, true); + SETOPT (CURLOPT_FAILONERROR, true); + + SETOPT (CURLOPT_POSTQUOTE, 0); + SETOPT (CURLOPT_QUOTE, 0); + } + + std::string form_query_string (const Array& param) + { + std::ostringstream query; - perform (); + if (param.numel () >= 2) + for (int i = 0; i < param.numel (); i += 2) + { + std::string name = param(i); + std::string text = param(i+1); + + // Encode strings. + char *enc_name = curl_easy_escape (m_curl, name.c_str (), + name.length ()); + char *enc_text = curl_easy_escape (m_curl, text.c_str (), + text.length ()); + + query << enc_name << '=' << enc_text; + + curl_free (enc_name); + curl_free (enc_text); + + if (i < param.numel ()-2) + query << '&'; + } + + query.flush (); - if (! good ()) - return; + return query.str (); + } + + void ftp_file_or_dir_action (const std::string& file_or_dir, + const std::string& action) + { + struct curl_slist *slist = nullptr; + + unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); }); + + std::string cmd = action + ' ' + file_or_dir; - SETOPT (CURLOPT_POSTQUOTE, 0); - } - }; + slist = curl_slist_append (slist, cmd.c_str ()); + + SETOPT (CURLOPT_POSTQUOTE, slist); + + perform (); + + if (! good ()) + return; + + SETOPT (CURLOPT_POSTQUOTE, 0); + } +}; #undef SETOPT @@ -918,17 +918,17 @@ # define REP_CLASS base_url_transfer #endif - url_transfer::url_transfer (void) : m_rep (new REP_CLASS ()) - { } +url_transfer::url_transfer (void) : m_rep (new REP_CLASS ()) +{ } - url_transfer::url_transfer (const std::string& host, const std::string& user, - const std::string& passwd, std::ostream& os) - : m_rep (new REP_CLASS (host, user, passwd, os)) - { } +url_transfer::url_transfer (const std::string& host, const std::string& user, + const std::string& passwd, std::ostream& os) + : m_rep (new REP_CLASS (host, user, passwd, os)) +{ } - url_transfer::url_transfer (const std::string& url, std::ostream& os) - : m_rep (new REP_CLASS (url, os)) - { } +url_transfer::url_transfer (const std::string& url, std::ostream& os) + : m_rep (new REP_CLASS (url, os)) +{ } #undef REP_CLASS diff -r dfa5d9c3ae72 -r 23664317f0d3 liboctave/util/url-transfer.h --- a/liboctave/util/url-transfer.h Thu Dec 01 14:28:07 2022 -0800 +++ b/liboctave/util/url-transfer.h Thu Dec 01 20:05:44 2022 -0800 @@ -38,262 +38,262 @@ OCTAVE_BEGIN_NAMESPACE(octave) - struct weboptions - { - std::string UserAgent; - long Timeout; - std::string Username; - std::string Password; - Array HeaderFields; - std::string ContentReader; - std::string RequestMethod; - std::string ArrayFormat; - std::string CertificateFilename; - }; +struct weboptions +{ + std::string UserAgent; + long Timeout; + std::string Username; + std::string Password; + Array HeaderFields; + std::string ContentReader; + std::string RequestMethod; + std::string ArrayFormat; + std::string CertificateFilename; +}; - class - OCTAVE_API - base_url_transfer - { - public: +class +OCTAVE_API +base_url_transfer +{ +public: - friend class url_transfer; + friend class url_transfer; - base_url_transfer (void); + base_url_transfer (void); - base_url_transfer (const std::string& host, - const std::string& /* user_arg */, - const std::string& /* passwd */, - std::ostream& os); + base_url_transfer (const std::string& host, + const std::string& /* user_arg */, + const std::string& /* passwd */, + std::ostream& os); - base_url_transfer (const std::string& url, std::ostream& os); + base_url_transfer (const std::string& url, std::ostream& os); - // No copying! + // No copying! - base_url_transfer (const base_url_transfer&) = delete; + base_url_transfer (const base_url_transfer&) = delete; - base_url_transfer& operator = (const base_url_transfer&) = delete; + base_url_transfer& operator = (const base_url_transfer&) = delete; - virtual ~base_url_transfer (void) = default; + virtual ~base_url_transfer (void) = default; - bool is_valid (void) const { return m_valid; } + bool is_valid (void) const { return m_valid; } - bool good (void) const { return m_valid && m_ok; } + bool good (void) const { return m_valid && m_ok; } - virtual void perform (void) { } + virtual void perform (void) { } - virtual std::string lasterror (void) const { return m_errmsg; } + virtual std::string lasterror (void) const { return m_errmsg; } - virtual std::ostream& set_ostream (std::ostream& /* os */) - { - return *m_curr_ostream; - } + virtual std::ostream& set_ostream (std::ostream& /* os */) + { + return *m_curr_ostream; + } - virtual std::istream& set_istream (std::istream& /* is */) - { - return *m_curr_istream; - } + virtual std::istream& set_istream (std::istream& /* is */) + { + return *m_curr_istream; + } - virtual void ascii (void) { } + virtual void ascii (void) { } - virtual void binary (void) { } + virtual void binary (void) { } - bool is_ascii (void) const { return m_ascii_mode; } + bool is_ascii (void) const { return m_ascii_mode; } - bool is_binary (void) const { return ! m_ascii_mode; } + bool is_binary (void) const { return ! m_ascii_mode; } - virtual void cwd (const std::string& /* path */) { } + virtual void cwd (const std::string& /* path */) { } - virtual void del (const std::string& /* file */) { } + virtual void del (const std::string& /* file */) { } - virtual void rmdir (const std::string& /* path */) { } + virtual void rmdir (const std::string& /* path */) { } - virtual void mkdir (const std::string& /* path */) { } + virtual void mkdir (const std::string& /* path */) { } - virtual void rename (const std::string& /* oldname */, - const std::string& /* newname */) { } + virtual void rename (const std::string& /* oldname */, + const std::string& /* newname */) { } - virtual void put (const std::string& /* file */, - std::istream& /* is */) { } + virtual void put (const std::string& /* file */, + std::istream& /* is */) { } - virtual void get (const std::string& /* file */, - std::ostream& /* os */) { } + virtual void get (const std::string& /* file */, + std::ostream& /* os */) { } - void mget_directory (const std::string& directory, - const std::string& target); + void mget_directory (const std::string& directory, + const std::string& target); - string_vector mput_directory (const std::string& base, - const std::string& directory); + string_vector mput_directory (const std::string& base, + const std::string& directory); - virtual void dir (void) { } + virtual void dir (void) { } - virtual string_vector list (void) { return string_vector (); } + virtual string_vector list (void) { return string_vector (); } - virtual void get_fileinfo (const std::string& /* filename */, - double& /* filesize */, - OCTAVE_TIME_T& /* filetime */, - bool& /* fileisdir */) { } + virtual void get_fileinfo (const std::string& /* filename */, + double& /* filesize */, + OCTAVE_TIME_T& /* filetime */, + bool& /* fileisdir */) { } - virtual std::string pwd (void) { return ""; } + virtual std::string pwd (void) { return ""; } - virtual void http_get (const Array& /* param */) { } + virtual void http_get (const Array& /* param */) { } - virtual void http_post (const Array& /* param */) { } + virtual void http_post (const Array& /* param */) { } - virtual void http_action (const Array& /* param */, - const std::string& /* action */) { } + virtual void http_action (const Array& /* param */, + const std::string& /* action */) { } - virtual void cookie_jar (const std::string& /* filename */) { } + virtual void cookie_jar (const std::string& /* filename */) { } - virtual void set_header_fields (const Array& /* param */) { } + virtual void set_header_fields (const Array& /* param */) { } - virtual void form_data_post (const Array& /* param */) { } + virtual void form_data_post (const Array& /* param */) { } - virtual void set_weboptions (const struct weboptions& /* param */) { } + virtual void set_weboptions (const struct weboptions& /* param */) { } - protected: +protected: - // Host for ftp transfers or full URL for http requests. - std::string m_host_or_url; - bool m_valid; - bool m_ftp; - bool m_ascii_mode; - bool m_ok; - std::string m_errmsg; - std::istream *m_curr_istream; - std::ostream *m_curr_ostream; - }; + // Host for ftp transfers or full URL for http requests. + std::string m_host_or_url; + bool m_valid; + bool m_ftp; + bool m_ascii_mode; + bool m_ok; + std::string m_errmsg; + std::istream *m_curr_istream; + std::ostream *m_curr_ostream; +}; - class - OCTAVE_API - url_transfer - { - public: +class +OCTAVE_API +url_transfer +{ +public: - url_transfer (void); + url_transfer (void); - url_transfer (const std::string& host, const std::string& user, - const std::string& passwd, std::ostream& os); + url_transfer (const std::string& host, const std::string& user, + const std::string& passwd, std::ostream& os); - url_transfer (const std::string& url, std::ostream& os); + url_transfer (const std::string& url, std::ostream& os); - url_transfer (const url_transfer&) = default; + url_transfer (const url_transfer&) = default; - url_transfer& operator = (const url_transfer&) = default; + url_transfer& operator = (const url_transfer&) = default; - ~url_transfer (void) = default; + ~url_transfer (void) = default; - bool is_valid (void) const { return m_rep->is_valid (); } + bool is_valid (void) const { return m_rep->is_valid (); } - bool good (void) const { return m_rep->good (); } + bool good (void) const { return m_rep->good (); } - std::string lasterror (void) const { return m_rep->lasterror (); } + std::string lasterror (void) const { return m_rep->lasterror (); } - std::ostream& set_ostream (std::ostream& os) - { - return m_rep->set_ostream (os); - } + std::ostream& set_ostream (std::ostream& os) + { + return m_rep->set_ostream (os); + } - std::istream& set_istream (std::istream& is) - { - return m_rep->set_istream (is); - } + std::istream& set_istream (std::istream& is) + { + return m_rep->set_istream (is); + } - void ascii (void) { m_rep->ascii (); } + void ascii (void) { m_rep->ascii (); } - void binary (void) { m_rep->binary (); } + void binary (void) { m_rep->binary (); } - bool is_ascii (void) const { return m_rep->is_ascii (); } + bool is_ascii (void) const { return m_rep->is_ascii (); } - bool is_binary (void) const { return m_rep->is_binary (); } + bool is_binary (void) const { return m_rep->is_binary (); } - void cwd (const std::string& path) { m_rep->cwd (path); } + void cwd (const std::string& path) { m_rep->cwd (path); } - void del (const std::string& file) { m_rep->del (file); } + void del (const std::string& file) { m_rep->del (file); } - void rmdir (const std::string& path) { m_rep->rmdir (path); } + void rmdir (const std::string& path) { m_rep->rmdir (path); } - void mkdir (const std::string& path) { m_rep->mkdir (path); } + void mkdir (const std::string& path) { m_rep->mkdir (path); } - void rename (const std::string& oldname, const std::string& newname) - { - m_rep->rename (oldname, newname); - } + void rename (const std::string& oldname, const std::string& newname) + { + m_rep->rename (oldname, newname); + } - void put (const std::string& file, std::istream& is) - { - m_rep->put (file, is); - } + void put (const std::string& file, std::istream& is) + { + m_rep->put (file, is); + } - void get (const std::string& file, std::ostream& os) - { - m_rep->get (file, os); - } + void get (const std::string& file, std::ostream& os) + { + m_rep->get (file, os); + } - void mget_directory (const std::string& directory, - const std::string& target) - { - m_rep->mget_directory (directory, target); - } + void mget_directory (const std::string& directory, + const std::string& target) + { + m_rep->mget_directory (directory, target); + } - string_vector mput_directory (const std::string& base, - const std::string& directory) - { - return m_rep->mput_directory (base, directory); - } + string_vector mput_directory (const std::string& base, + const std::string& directory) + { + return m_rep->mput_directory (base, directory); + } - void dir (void) { m_rep->dir (); } + void dir (void) { m_rep->dir (); } - string_vector list (void) { return m_rep->list (); } + string_vector list (void) { return m_rep->list (); } - void get_fileinfo (const std::string& filename, double& filesize, - OCTAVE_TIME_T& filetime, bool& fileisdir) - { - m_rep->get_fileinfo (filename, filesize, filetime, fileisdir); - } + void get_fileinfo (const std::string& filename, double& filesize, + OCTAVE_TIME_T& filetime, bool& fileisdir) + { + m_rep->get_fileinfo (filename, filesize, filetime, fileisdir); + } - std::string pwd (void) { return m_rep->pwd (); } + std::string pwd (void) { return m_rep->pwd (); } - void http_get (const Array& param) - { - m_rep->http_get (param); - } + void http_get (const Array& param) + { + m_rep->http_get (param); + } - void http_post (const Array& param) - { - m_rep->http_post (param); - } + void http_post (const Array& param) + { + m_rep->http_post (param); + } - void http_action (const Array& param, - const std::string& action) - { - m_rep->http_action (param, action); - } + void http_action (const Array& param, + const std::string& action) + { + m_rep->http_action (param, action); + } - void cookie_jar (const std::string& filename) - { - m_rep->cookie_jar (filename); - } + void cookie_jar (const std::string& filename) + { + m_rep->cookie_jar (filename); + } - void set_header_fields (const Array& param) - { - m_rep->set_header_fields (param); - } + void set_header_fields (const Array& param) + { + m_rep->set_header_fields (param); + } - void form_data_post (const Array& param) - { - m_rep->form_data_post (param); - } + void form_data_post (const Array& param) + { + m_rep->form_data_post (param); + } - void set_weboptions (const struct weboptions& param) - { - m_rep->set_weboptions (param); - } + void set_weboptions (const struct weboptions& param) + { + m_rep->set_weboptions (param); + } - private: +private: - std::shared_ptr m_rep; - }; + std::shared_ptr m_rep; +}; OCTAVE_END_NAMESPACE(octave)